Skip to content

[5.9] Print package-name in .private.swiftinterface only for better abstraction #66256

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/Frontend/ModuleInterfaceSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define SWIFT_COMPILER_VERSION_KEY "swift-compiler-version"
#define SWIFT_MODULE_FLAGS_KEY "swift-module-flags"
#define SWIFT_MODULE_FLAGS_IGNORABLE_KEY "swift-module-flags-ignorable"
#define SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY "swift-module-flags-ignorable-private"

namespace swift {

Expand Down Expand Up @@ -50,6 +51,10 @@ struct ModuleInterfaceOptions {
/// ignored by the earlier version of the compiler.
std::string IgnorableFlags;

/// Ignorable flags that should only be printed in .private.swiftinterface file;
/// e.g. -package-name PACKAGE_ID
std::string IgnorablePrivateFlags;

/// Print for a private swiftinterface file, SPI decls and attributes.
bool PrintPrivateInterfaceContent = false;

Expand Down
1 change: 1 addition & 0 deletions include/swift/Option/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace options {
SwiftAPIDigesterOption = (1 << 17),
NewDriverOnlyOption = (1 << 18),
ModuleInterfaceOptionIgnorable = (1 << 19),
ModuleInterfaceOptionIgnorablePrivate = (1 << 20),
};

enum ID {
Expand Down
7 changes: 6 additions & 1 deletion include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def ModuleInterfaceOption : OptionFlag;
// The option can be safely ignored by the older compiler.
def ModuleInterfaceOptionIgnorable : OptionFlag;

// The option should be written into a .private.swiftinterface module interface file,
// and read/parsed from there when reconstituting a .swiftmodule from it.
// The option can be safely ignored by the older compiler.
def ModuleInterfaceOptionIgnorablePrivate : OptionFlag;

// The option causes the output of a supplementary output, or is the path option
// for a supplementary output. E.g., `-emit-module` and `-emit-module-path`.
def SupplementaryOutput : OptionFlag;
Expand Down Expand Up @@ -526,7 +531,7 @@ def module_abi_name : Separate<["-"], "module-abi-name">,
Flags<[FrontendOption, ModuleInterfaceOption]>,
HelpText<"ABI name to use for the contents of this module">;
def package_name : Separate<["-"], "package-name">,
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>,
Flags<[FrontendOption, ModuleInterfaceOptionIgnorablePrivate]>,
HelpText<"Name of the package the module belongs to">;
def export_as : Separate<["-"], "export-as">,
Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>,
Expand Down
11 changes: 10 additions & 1 deletion lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,14 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
return;
ArgStringList RenderedArgs;
ArgStringList RenderedArgsIgnorable;
ArgStringList RenderedArgsIgnorablePrivate;
for (auto A : Args) {
if (!ShouldIncludeModuleInterfaceArg(A))
continue;

if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorablePrivate)) {
A->render(Args, RenderedArgsIgnorablePrivate);
} else if (A->getOption().hasFlag(options::ModuleInterfaceOptionIgnorable)) {
A->render(Args, RenderedArgsIgnorable);
} else if (A->getOption().hasFlag(options::ModuleInterfaceOption)) {
A->render(Args, RenderedArgs);
Expand All @@ -437,6 +440,12 @@ static void SaveModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
if (FOpts.ModuleName == "_Concurrency")
OS << " -disable-availability-checking";
}
{
llvm::raw_string_ostream OS(Opts.IgnorablePrivateFlags);
interleave(RenderedArgsIgnorablePrivate,
[&](const char *Argument) { PrintArg(OS, Argument, StringRef()); },
[&] { OS << " "; });
}
{
llvm::raw_string_ostream OS(Opts.IgnorableFlags);
interleave(RenderedArgsIgnorable,
Expand Down
4 changes: 2 additions & 2 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1185,8 +1185,8 @@ ModuleDecl *CompilerInstance::getMainModule() const {
Invocation.getFrontendOptions().ModuleABIName));
}
if (!Invocation.getLangOptions().PackageName.empty()) {
MainModule->setPackageName(getASTContext().getIdentifier(
Invocation.getLangOptions().PackageName));
auto pkgName = Invocation.getLangOptions().PackageName;
MainModule->setPackageName(getASTContext().getIdentifier(pkgName));
}
if (!Invocation.getFrontendOptions().ExportAsName.empty()) {
MainModule->setExportAsName(getASTContext().getIdentifier(
Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/ModuleInterfaceSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ static void printToolVersionAndFlagsComment(raw_ostream &out,
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_KEY ": "
<< Opts.IgnorableFlags << "\n";
}

auto hasPrivateIgnorableFlags = Opts.PrintPrivateInterfaceContent && !Opts.IgnorablePrivateFlags.empty();
if (hasPrivateIgnorableFlags) {
out << "// " SWIFT_MODULE_FLAGS_IGNORABLE_PRIVATE_KEY ": "
<< Opts.IgnorablePrivateFlags << "\n";
}
}

std::string
Expand Down
21 changes: 17 additions & 4 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1162,12 +1162,25 @@ bool swift::extractCompilerFlagsFromInterface(StringRef interfacePath,
// Cherry-pick supported options from the ignorable list.
auto IgnFlagRe = llvm::Regex("^// swift-module-flags-ignorable:(.*)$",
llvm::Regex::Newline);
// It's OK the interface doesn't have the ignorable list, we just ignore them
// all.
if (!IgnFlagRe.match(buffer, &IgnFlagMatches))
auto hasIgnorableFlags = IgnFlagRe.match(buffer, &IgnFlagMatches);

// Check for ignorable-private flags
SmallVector<StringRef, 1> IgnPrivateFlagMatches;
auto IgnPrivateFlagRe = llvm::Regex("^// swift-module-flags-ignorable-private:(.*)$",
llvm::Regex::Newline);
auto hasIgnorablePrivateFlags = IgnPrivateFlagRe.match(buffer, &IgnPrivateFlagMatches);

// It's OK the interface doesn't have the ignorable list (private or not), we just
// ignore them all.
if (!hasIgnorableFlags && !hasIgnorablePrivateFlags)
return false;

SmallVector<const char *, 8> IgnSubArgs;
llvm::cl::TokenizeGNUCommandLine(IgnFlagMatches[1], ArgSaver, IgnSubArgs);
if (hasIgnorableFlags)
llvm::cl::TokenizeGNUCommandLine(IgnFlagMatches[1], ArgSaver, IgnSubArgs);
if (hasIgnorablePrivateFlags)
llvm::cl::TokenizeGNUCommandLine(IgnPrivateFlagMatches[1], ArgSaver, IgnSubArgs);

std::unique_ptr<llvm::opt::OptTable> table = swift::createSwiftOptTable();
unsigned missingArgIdx = 0;
unsigned missingArgCount = 0;
Expand Down
4 changes: 2 additions & 2 deletions test/Sema/accessibility_package_inline_interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.swiftinterface) -I%t

// RUN: %FileCheck %s -check-prefix CHECK-UTILS < %t/Utils.swiftinterface
// CHECK-UTILS: -module-name Utils -enable-library-evolution
// CHECK-UTILS: swift-module-flags-ignorable: -package-name myLib
// CHECK-UTILS: -module-name Utils
// CHECK-UTILS-NOT: -package-name myLib
// CHECK-UTILS: @usableFromInline
// CHECK-UTILS: package class PackageKlassProto {
// CHECK-UTILS: @usableFromInline
Expand Down
38 changes: 38 additions & 0 deletions test/Sema/accessibility_package_interface.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -emit-module %t/Utils.swift \
// RUN: -module-name Utils -swift-version 5 -I %t \
// RUN: -package-name swift-utils.log \
// RUN: -enable-library-evolution \
// RUN: -emit-module-path %t/Utils.swiftmodule \
// RUN: -emit-module-interface-path %t/Utils.swiftinterface \
// RUN: -emit-private-module-interface-path %t/Utils.private.swiftinterface

// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.swiftinterface) -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/Utils.swiftinterface
// CHECK-PUBLIC-NOT: -package-name swift-utils.log
// CHECK-PUBLIC-NOT: package func packageFunc()
// CHECK-PUBLIC: -module-name Utils
// CHECK-PUBLIC: public func publicFunc()

// RUN: %target-swift-typecheck-module-from-interface(%t/Utils.private.swiftinterface) -module-name Utils -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/Utils.private.swiftinterface

// CHECK-PRIVATE-NOT: package func packageFunc()
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name swift-utils.log
// CHECK-PRIVATE: public func publicFunc()

// RUN: %target-swift-frontend -typecheck %t/Client.swift -package-name swift-utils.log -I %t -verify

//--- Utils.swift
package func packageFunc() {}
public func publicFunc() {}

//--- Client.swift
import Utils

func clientFunc() {
packageFunc()
publicFunc()
}
67 changes: 42 additions & 25 deletions test/Serialization/load_package_module.swift
Original file line number Diff line number Diff line change
@@ -1,40 +1,57 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t

// RUN: %target-swift-frontend -module-name LibFromInterface -emit-module -emit-module-interface-path %t/LibFromInterface.swiftinterface -parse-as-library %t/Lib.swift -enable-library-evolution -package-name mypkg -swift-version 5
// RUN: test -f %t/LibFromInterface.swiftinterface
// RUN: %FileCheck %s -check-prefix CHECK-LIB < %t/LibFromInterface.swiftinterface
// CHECK-LIB: -package-name mypkg
// CHECK-LIB-NOT: func log(level: Int)
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
// RUN: -module-name LibBinary -swift-version 5 -I %t \
// RUN: -package-name libPkg \
// RUN: -emit-module-path %t/LibBinary.swiftmodule

// RUN: not %target-swift-frontend -module-name ClientInSamePkg %t/ClientLoadInterfaceModule.swift -emit-module -emit-module-path %t/ClientInSamePkg.swiftmodule -package-name mypkg -I %t 2> %t/resultA.output
// RUN: %FileCheck %s -check-prefix CHECK-A < %t/resultA.output
// CHECK-A: error: module 'LibFromInterface' is in package 'mypkg' but was built from interface; modules of the same package can only be loaded if built from source: {{.*}}LibFromInterface.swiftinterface
// RUN: %target-swift-frontend -typecheck %t/ClientLoadBinary.swift -package-name libPkg -I %t -verify

// RUN: not %target-swift-frontend -module-name ClientInDiffPkg %t/ClientLoadInterfaceModule.swift -emit-module -emit-module-path %t/ClientInDiffPkg.swiftmodule -package-name otherPkg -I %t 2> %t/resultB.output
// RUN: %FileCheck %s -check-prefix CHECK-B < %t/resultB.output
// CHECK-B: error: cannot find 'log' in scope
// RUN: %target-swift-frontend -emit-module %t/Lib.swift \
// RUN: -module-name LibInterface -swift-version 5 -I %t \
// RUN: -package-name libPkg \
// RUN: -enable-library-evolution \
// RUN: -emit-module-path %t/LibBinary.swiftmodule \
// RUN: -emit-module-interface-path %t/LibInterface.swiftinterface \
// RUN: -emit-private-module-interface-path %t/LibInterface.private.swiftinterface

// RUN: %target-swift-frontend -module-name LibFromSource -emit-module -emit-module-path %t/LibFromSource.swiftmodule -parse-as-library %t/Lib.swift -package-name mypkg
// RUN: test -f %t/LibFromSource.swiftmodule
// RUN: %target-swift-typecheck-module-from-interface(%t/LibInterface.swiftinterface) -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/LibInterface.swiftinterface
// CHECK-PUBLIC: -module-name LibInterface
// CHECK-PUBLIC-NOT: -package-name

// RUN: %target-swift-typecheck-module-from-interface(%t/LibInterface.private.swiftinterface) -module-name LibInterface -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/LibInterface.private.swiftinterface
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name libPkg

// RUN: not %target-swift-frontend -typecheck %t/ClientLoadInterface.swift -package-name otherPkg -I %t 2> %t/resultX.output
// RUN: %FileCheck %s -check-prefix CHECK-X < %t/resultX.output
// CHECK-X: error: cannot find 'packageLog' in scope

// RUN: not %target-swift-frontend -typecheck %t/ClientLoadInterface.swift -package-name libPkg -I %t 2> %t/resultY.output
// RUN: %FileCheck %s -check-prefix CHECK-Y < %t/resultY.output
// CHECK-Y: error: module 'LibInterface' is in package 'libPkg' but was built from interface; modules of the same package can only be loaded if built from source: {{.*}}LibInterface.private.swiftinterface

// RUN: %target-swift-frontend -module-name ClientInSamePkgSrc %t/ClientLoadSourceModule.swift -emit-module -emit-module-path %t/ClientInSamePkgSrc.swiftmodule -package-name mypkg -I %t
// RUN: test -f %t/ClientInSamePkgSrc.swiftmodule

//--- Lib.swift
package func log(level: Int) {}
public func publicLog(_ level: Int) {}
package func packageLog(_ level: Int) {}
func internalLog(_ level: Int) {}

//--- ClientLoadInterfaceModule.swift
import LibFromInterface

func someFun() {
log(level: 1)
//--- ClientLoadInterface.swift
import LibInterface

func someFunc() {
publicLog(1)
packageLog(2)
}

//--- ClientLoadSourceModule.swift
import LibFromSource
//--- ClientLoadBinary.swift
import LibBinary

func someFun() {
log(level: 1)
func someFunc() {
publicLog(1)
packageLog(2)
}

19 changes: 13 additions & 6 deletions test/Serialization/module_package_name.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
// RUN: %empty-directory(%t)
// RUN: %{python} %utils/split_file.py -o %t %s
// RUN: split-file %s %t

// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-path %t/Logging.swiftmodule
// RUN: test -f %t/Logging.swiftmodule
// RUN: llvm-bcanalyzer -dump %t/Logging.swiftmodule | %FileCheck %s -check-prefix CHECK-BLOB
// CHECK-BLOB: <MODULE_PACKAGE_NAME abbrevid=5/> blob data = 'MyLoggingPkg'

// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-interface-path %t/Logging.swiftinterface -swift-version 5 -enable-library-evolution -I %t
// RUN: test -f %t/Logging.swiftinterface
// RUN: %FileCheck %s -input-file %t/Logging.swiftinterface -check-prefix CHECK-FLAG
// CHECK-FLAG: -package-name MyLoggingPkg
// RUN: %target-swift-frontend -module-name Logging -package-name MyLoggingPkg %t/File.swift -emit-module -emit-module-interface-path %t/Logging.swiftinterface -emit-private-module-interface-path %t/Logging.private.swiftinterface -swift-version 5 -enable-library-evolution -I %t

// BEGIN File.swift
// RUN: %target-swift-typecheck-module-from-interface(%t/Logging.swiftinterface) -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PUBLIC < %t/Logging.swiftinterface
// CHECK-PUBLIC: -module-name Logging
// CHECK-PUBLIC-NOT: -package-name

// RUN: %target-swift-typecheck-module-from-interface(%t/Logging.private.swiftinterface) -module-name Logging -I %t
// RUN: %FileCheck %s --check-prefix=CHECK-PRIVATE < %t/Logging.private.swiftinterface
// CHECK-PRIVATE: -module-name Logging
// CHECK-PRIVATE: swift-module-flags-ignorable-private: -package-name MyLoggingPkg

//--- File.swift
public func log(level: Int) {}