diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index 8320435945672..38c9aca02e278 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -25,7 +25,7 @@ /// SWIFTSCAN_VERSION_MINOR should increase when there are API additions. /// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes. #define SWIFTSCAN_VERSION_MAJOR 0 -#define SWIFTSCAN_VERSION_MINOR 9 +#define SWIFTSCAN_VERSION_MINOR 10 SWIFTSCAN_BEGIN_DECLS @@ -46,6 +46,9 @@ typedef struct swiftscan_module_details_s *swiftscan_module_details_t; /// Opaque container to a dependency info of a given module. typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t; +/// Opaque container to a link library info. +typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t; + /// Opaque container to an overall result of a dependency scan. typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t; @@ -64,6 +67,12 @@ typedef struct { size_t count; } swiftscan_dependency_set_t; +/// Set of linked libraries +typedef struct { + swiftscan_link_library_info_t *link_libraries; + size_t count; +} swiftscan_link_library_set_t; + typedef enum { SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0, SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1, @@ -127,9 +136,21 @@ swiftscan_module_info_get_source_files(swiftscan_dependency_info_t info); SWIFTSCAN_PUBLIC swiftscan_string_set_t * swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info); +SWIFTSCAN_PUBLIC swiftscan_link_library_set_t * +swiftscan_module_info_get_link_libraries(swiftscan_dependency_info_t info); + SWIFTSCAN_PUBLIC swiftscan_module_details_t swiftscan_module_info_get_details(swiftscan_dependency_info_t info); +//=== Link Library Info Functions ------------------------------------===// +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_link_library_info_get_link_name( + swiftscan_link_library_info_t info); +SWIFTSCAN_PUBLIC bool swiftscan_link_library_info_get_is_framework( + swiftscan_link_library_info_t info); +SWIFTSCAN_PUBLIC bool swiftscan_link_library_info_get_should_force_load( + swiftscan_link_library_info_t info); + //=== Dependency Module Info Details Functions ----------------------------===// SWIFTSCAN_PUBLIC swiftscan_dependency_info_kind_t diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index 68654b5974e68..0c7bbc8ef3cc6 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -337,6 +337,9 @@ class IRGenOptions { /// Whether we should disable inserting autolink directives altogether. unsigned DisableAllAutolinking : 1; + /// Whether we should disable inserting __swift_FORCE_LOAD_ symbols. + unsigned DisableForceLoadSymbols : 1; + /// Print the LLVM inline tree at the end of the LLVM pass pipeline. unsigned PrintInlineTree : 1; diff --git a/include/swift/AST/Import.h b/include/swift/AST/Import.h index 8f3bfaa961c95..0e014d5e24036 100644 --- a/include/swift/AST/Import.h +++ b/include/swift/AST/Import.h @@ -36,6 +36,7 @@ namespace swift { class ASTContext; class ModuleDecl; +class ImportDecl; // MARK: - Fundamental import enums @@ -102,6 +103,8 @@ using ImportOptions = OptionSet; void simple_display(llvm::raw_ostream &out, ImportOptions options); +ImportOptions getImportOptions(ImportDecl *ID); + // MARK: - Import Paths namespace detail { diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index 980affdaa4013..e6a02d3a14756 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -19,6 +19,7 @@ #define SWIFT_AST_MODULE_DEPENDENCIES_H #include "swift/AST/Import.h" +#include "swift/AST/LinkLibrary.h" #include "swift/AST/SearchPathOptions.h" #include "swift/Basic/LLVM.h" #include "clang/CAS/CASOptions.h" @@ -50,6 +51,7 @@ class SourceFile; class ASTContext; class Identifier; class CompilerInstance; +class IRGenOptions; /// Which kind of module dependencies we are looking for. enum class ModuleDependencyKind : int8_t { @@ -93,12 +95,10 @@ struct ModuleDependencyID { std::string ModuleName; ModuleDependencyKind Kind; bool operator==(const ModuleDependencyID &Other) const { - return std::tie(ModuleName, Kind) == - std::tie(Other.ModuleName, Other.Kind); + return std::tie(ModuleName, Kind) == std::tie(Other.ModuleName, Other.Kind); } - bool operator<(const ModuleDependencyID& Other) const { - return std::tie(ModuleName, Kind) < - std::tie(Other.ModuleName, Other.Kind); + bool operator<(const ModuleDependencyID &Other) const { + return std::tie(ModuleName, Kind) < std::tie(Other.ModuleName, Other.Kind); } }; @@ -115,50 +115,50 @@ struct ModuleDependencyIDHash { }; using ModuleDependencyIDSet = - std::unordered_set; + std::unordered_set; using ModuleDependencyIDSetVector = llvm::SetVector, std::set>; namespace dependencies { - std::string createEncodedModuleKindAndName(ModuleDependencyID id); - bool checkImportNotTautological(const ImportPath::Module, - const SourceLoc, - const SourceFile&, - bool); -} +std::string createEncodedModuleKindAndName(ModuleDependencyID id); +bool checkImportNotTautological(const ImportPath::Module, const SourceLoc, + const SourceFile &, bool); +void registerBackDeployLibraries( + const IRGenOptions &IRGenOpts, + std::function RegistrationCallback); +void registerCxxInteropLibraries( + const llvm::Triple &Target, StringRef mainModuleName, bool hasStaticCxx, + bool hasStaticCxxStdlib, + std::function RegistrationCallback); +} // namespace dependencies struct ScannerImportStatementInfo { struct ImportDiagnosticLocationInfo { ImportDiagnosticLocationInfo() = delete; ImportDiagnosticLocationInfo(std::string bufferIdentifier, - uint32_t lineNumber, - uint32_t columnNumber) - : bufferIdentifier(bufferIdentifier), - lineNumber(lineNumber), - columnNumber(columnNumber) {} + uint32_t lineNumber, uint32_t columnNumber) + : bufferIdentifier(bufferIdentifier), lineNumber(lineNumber), + columnNumber(columnNumber) {} std::string bufferIdentifier; uint32_t lineNumber; uint32_t columnNumber; }; ScannerImportStatementInfo(std::string importIdentifier) - : importLocations(), - importIdentifier(importIdentifier) {} + : importLocations(), importIdentifier(importIdentifier) {} ScannerImportStatementInfo(std::string importIdentifier, ImportDiagnosticLocationInfo location) - : importLocations({location}), - importIdentifier(importIdentifier) {} + : importLocations({location}), importIdentifier(importIdentifier) {} void addImportLocation(ImportDiagnosticLocationInfo location) { importLocations.push_back(location); } - // Buffer, line & column number of the import statement + /// Buffer, line & column number of the import statement SmallVector importLocations; - // Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar' + /// Imported module string. e.g. "Foo.Bar" in 'import Foo.Bar' std::string importIdentifier; }; @@ -170,19 +170,21 @@ class ModuleDependencyInfoStorageBase { const ModuleDependencyKind dependencyKind; ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind, + ArrayRef linkLibraries, StringRef moduleCacheKey = "") - : dependencyKind(dependencyKind), moduleCacheKey(moduleCacheKey.str()), - resolved(false), finalized(false) {} + : dependencyKind(dependencyKind), linkLibraries(linkLibraries), + moduleCacheKey(moduleCacheKey.str()), resolved(false), + finalized(false) {} ModuleDependencyInfoStorageBase( ModuleDependencyKind dependencyKind, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, - StringRef moduleCacheKey = "") + ArrayRef moduleImports, + ArrayRef optionalModuleImports, + ArrayRef linkLibraries, StringRef moduleCacheKey = "") : dependencyKind(dependencyKind), moduleImports(moduleImports), optionalModuleImports(optionalModuleImports), - moduleCacheKey(moduleCacheKey.str()), resolved(false), - finalized(false) {} + linkLibraries(linkLibraries), moduleCacheKey(moduleCacheKey.str()), + resolved(false), finalized(false) {} virtual ModuleDependencyInfoStorageBase *clone() const = 0; @@ -196,6 +198,10 @@ class ModuleDependencyInfoStorageBase { /// or `internal` imports. std::vector optionalModuleImports; + /// A collection of libraries that must be linked to + /// use this module. + std::vector linkLibraries; + /// The set of modules on which this module depends, resolved /// to Module IDs, qualified by module kind: Swift, Clang, etc. std::vector resolvedDirectModuleDependencies; @@ -221,7 +227,7 @@ class ModuleDependencyInfoStorageBase { struct CommonSwiftTextualModuleDependencyDetails { CommonSwiftTextualModuleDependencyDetails( ArrayRef extraPCMArgs, ArrayRef buildCommandLine, - const std::string &CASFileSystemRootID) + StringRef CASFileSystemRootID) : extraPCMArgs(extraPCMArgs.begin(), extraPCMArgs.end()), buildCommandLine(buildCommandLine.begin(), buildCommandLine.end()), CASFileSystemRootID(CASFileSystemRootID) {} @@ -251,11 +257,12 @@ struct CommonSwiftTextualModuleDependencyDetails { std::string CASBridgingHeaderIncludeTreeRootID; }; -/// Describes the dependencies of a Swift module described by an Swift interface file. +/// Describes the dependencies of a Swift module described by an Swift interface +/// file. /// /// This class is mostly an implementation detail for \c ModuleDependencyInfo. -class SwiftInterfaceModuleDependenciesStorage : - public ModuleDependencyInfoStorageBase { +class SwiftInterfaceModuleDependenciesStorage + : public ModuleDependencyInfoStorageBase { public: /// Destination output path const std::string moduleOutputPath; @@ -272,23 +279,25 @@ class SwiftInterfaceModuleDependenciesStorage : /// A flag that indicates this dependency is a framework const bool isFramework; + /// A flag that indicates this dependency is associated with a static archive + const bool isStatic; + /// Details common to Swift textual (interface or source) modules CommonSwiftTextualModuleDependencyDetails textualModuleDetails; SwiftInterfaceModuleDependenciesStorage( - const std::string &moduleOutputPath, - const std::string &swiftInterfaceFile, - ArrayRef compiledModuleCandidates, - ArrayRef buildCommandLine, ArrayRef extraPCMArgs, - StringRef contextHash, bool isFramework, const std::string &RootID, - const std::string &moduleCacheKey) + StringRef moduleOutputPath, StringRef swiftInterfaceFile, + ArrayRef compiledModuleCandidates, + ArrayRef buildCommandLine, ArrayRef linkLibraries, + ArrayRef extraPCMArgs, StringRef contextHash, bool isFramework, + bool isStatic, StringRef RootID, StringRef moduleCacheKey) : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftInterface, - moduleCacheKey), + linkLibraries, moduleCacheKey), moduleOutputPath(moduleOutputPath), swiftInterfaceFile(swiftInterfaceFile), compiledModuleCandidates(compiledModuleCandidates.begin(), compiledModuleCandidates.end()), - contextHash(contextHash), isFramework(isFramework), + contextHash(contextHash), isFramework(isFramework), isStatic(isStatic), textualModuleDetails(extraPCMArgs, buildCommandLine, RootID) {} ModuleDependencyInfoStorageBase *clone() const override { @@ -307,10 +316,9 @@ class SwiftInterfaceModuleDependenciesStorage : /// Describes the dependencies of a Swift module /// /// This class is mostly an implementation detail for \c ModuleDependencyInfo. -class SwiftSourceModuleDependenciesStorage : - public ModuleDependencyInfoStorageBase { +class SwiftSourceModuleDependenciesStorage + : public ModuleDependencyInfoStorageBase { public: - /// Swift source files that are part of the Swift module, when known. std::vector sourceFiles; @@ -324,10 +332,10 @@ class SwiftSourceModuleDependenciesStorage : std::vector bridgingHeaderBuildCommandLine; SwiftSourceModuleDependenciesStorage( - const std::string &RootID, ArrayRef buildCommandLine, + StringRef RootID, ArrayRef buildCommandLine, ArrayRef bridgingHeaderBuildCommandLine, ArrayRef extraPCMArgs) - : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftSource), + : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftSource, {}), textualModuleDetails(extraPCMArgs, buildCommandLine, RootID), testableImports(llvm::StringSet<>()), bridgingHeaderBuildCommandLine(bridgingHeaderBuildCommandLine.begin(), @@ -363,18 +371,18 @@ class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBase { public: SwiftBinaryModuleDependencyStorage( - const std::string &compiledModulePath, const std::string &moduleDocPath, - const std::string &sourceInfoPath, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, - const std::string &headerImport, const bool isFramework, - const std::string &moduleCacheKey) + StringRef compiledModulePath, StringRef moduleDocPath, + StringRef sourceInfoPath, + ArrayRef moduleImports, + ArrayRef optionalModuleImports, + ArrayRef linkLibraries, StringRef headerImport, + bool isFramework, bool isStatic, StringRef moduleCacheKey) : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftBinary, moduleImports, optionalModuleImports, - moduleCacheKey), + linkLibraries, moduleCacheKey), compiledModulePath(compiledModulePath), moduleDocPath(moduleDocPath), sourceInfoPath(sourceInfoPath), headerImport(headerImport), - isFramework(isFramework) {} + isFramework(isFramework), isStatic(isStatic) {} ModuleDependencyInfoStorageBase *clone() const override { return new SwiftBinaryModuleDependencyStorage(*this); @@ -401,6 +409,9 @@ class SwiftBinaryModuleDependencyStorage /// A flag that indicates this dependency is a framework const bool isFramework; + /// A flag that indicates this dependency is associated with a static archive + const bool isStatic; + static bool classof(const ModuleDependencyInfoStorageBase *base) { return base->dependencyKind == ModuleDependencyKind::SwiftBinary; } @@ -443,19 +454,17 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase { /// Whether this is a "system" module. bool IsSystem; - ClangModuleDependencyStorage(const std::string &pcmOutputPath, - const std::string &mappedPCMPath, - const std::string &moduleMapFile, - const std::string &contextHash, - const std::vector &buildCommandLine, - const std::vector &fileDependencies, - const std::vector &capturedPCMArgs, - const std::string &CASFileSystemRootID, - const std::string &clangIncludeTreeRoot, - const std::string &moduleCacheKey, - bool IsSystem) + ClangModuleDependencyStorage(StringRef pcmOutputPath, StringRef mappedPCMPath, + StringRef moduleMapFile, StringRef contextHash, + ArrayRef buildCommandLine, + ArrayRef fileDependencies, + ArrayRef capturedPCMArgs, + ArrayRef linkLibraries, + StringRef CASFileSystemRootID, + StringRef clangIncludeTreeRoot, + StringRef moduleCacheKey, bool IsSystem) : ModuleDependencyInfoStorageBase(ModuleDependencyKind::Clang, - moduleCacheKey), + linkLibraries, moduleCacheKey), pcmOutputPath(pcmOutputPath), mappedPCMPath(mappedPCMPath), moduleMapFile(moduleMapFile), contextHash(contextHash), buildCommandLine(buildCommandLine), fileDependencies(fileDependencies), @@ -471,7 +480,7 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase { return base->dependencyKind == ModuleDependencyKind::Clang; } - void updateCommandLine(const std::vector &newCommandLine) { + void updateCommandLine(ArrayRef newCommandLine) { buildCommandLine = newCommandLine; } }; @@ -480,14 +489,15 @@ class ClangModuleDependencyStorage : public ModuleDependencyInfoStorageBase { /// /// This class is mostly an implementation detail for \c ModuleDependencyInfo. -class SwiftPlaceholderModuleDependencyStorage : public ModuleDependencyInfoStorageBase { +class SwiftPlaceholderModuleDependencyStorage + : public ModuleDependencyInfoStorageBase { public: - SwiftPlaceholderModuleDependencyStorage(const std::string &compiledModulePath, - const std::string &moduleDocPath, - const std::string &sourceInfoPath) - : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftPlaceholder), - compiledModulePath(compiledModulePath), - moduleDocPath(moduleDocPath), + SwiftPlaceholderModuleDependencyStorage(StringRef compiledModulePath, + StringRef moduleDocPath, + StringRef sourceInfoPath) + : ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftPlaceholder, + {}), + compiledModulePath(compiledModulePath), moduleDocPath(moduleDocPath), sourceInfoPath(sourceInfoPath) {} ModuleDependencyInfoStorageBase *clone() const override { @@ -518,13 +528,14 @@ class ModuleDependencyInfo { private: std::unique_ptr storage; - ModuleDependencyInfo(std::unique_ptr &&storage) - : storage(std::move(storage)) { } + ModuleDependencyInfo( + std::unique_ptr &&storage) + : storage(std::move(storage)) {} public: ModuleDependencyInfo() = default; ModuleDependencyInfo(const ModuleDependencyInfo &other) - : storage(other.storage->clone()) { } + : storage(other.storage->clone()) {} ModuleDependencyInfo(ModuleDependencyInfo &&other) = default; ModuleDependencyInfo &operator=(const ModuleDependencyInfo &other) { @@ -536,36 +547,32 @@ class ModuleDependencyInfo { /// Describe the module dependencies for a Swift module that can be /// built from a Swift interface file (\c .swiftinterface). - static ModuleDependencyInfo - forSwiftInterfaceModule(const std::string &moduleOutputPath, - const std::string &swiftInterfaceFile, - ArrayRef compiledCandidates, - ArrayRef buildCommands, - ArrayRef extraPCMArgs, - StringRef contextHash, bool isFramework, - const std::string &CASFileSystemRootID, - const std::string &moduleCacheKey) { + static ModuleDependencyInfo forSwiftInterfaceModule( + StringRef moduleOutputPath, StringRef swiftInterfaceFile, + ArrayRef compiledCandidates, ArrayRef buildCommands, + ArrayRef linkLibraries, ArrayRef extraPCMArgs, + StringRef contextHash, bool isFramework, bool isStatic, + StringRef CASFileSystemRootID, StringRef moduleCacheKey) { return ModuleDependencyInfo( std::make_unique( moduleOutputPath, swiftInterfaceFile, compiledCandidates, - buildCommands, extraPCMArgs, contextHash, isFramework, - CASFileSystemRootID, moduleCacheKey)); + buildCommands, linkLibraries, extraPCMArgs, contextHash, + isFramework, isStatic, CASFileSystemRootID, moduleCacheKey)); } /// Describe the module dependencies for a serialized or parsed Swift module. static ModuleDependencyInfo forSwiftBinaryModule( - const std::string &compiledModulePath, - const std::string &moduleDocPath, - const std::string &sourceInfoPath, - const std::vector &moduleImports, - const std::vector &optionalModuleImports, - const std::string &headerImport, - bool isFramework, const std::string &moduleCacheKey) { + StringRef compiledModulePath, StringRef moduleDocPath, + StringRef sourceInfoPath, + ArrayRef moduleImports, + ArrayRef optionalModuleImports, + ArrayRef linkLibraries, StringRef headerImport, + bool isFramework, bool isStatic, StringRef moduleCacheKey) { return ModuleDependencyInfo( std::make_unique( - compiledModulePath, moduleDocPath, sourceInfoPath, - moduleImports, optionalModuleImports, - headerImport, isFramework, moduleCacheKey)); + compiledModulePath, moduleDocPath, sourceInfoPath, moduleImports, + optionalModuleImports, linkLibraries, headerImport, isFramework, + isStatic, moduleCacheKey)); } /// Describe the main Swift module. @@ -583,29 +590,26 @@ class ModuleDependencyInfo { /// Describe the module dependencies for a Clang module that can be /// built from a module map and headers. static ModuleDependencyInfo forClangModule( - const std::string &pcmOutputPath, const std::string &mappedPCMPath, - const std::string &moduleMapFile, const std::string &contextHash, - const std::vector &nonPathCommandLine, - const std::vector &fileDependencies, - const std::vector &capturedPCMArgs, - const std::string &CASFileSystemRootID, - const std::string &clangIncludeTreeRoot, - const std::string &moduleCacheKey, - bool IsSystem) { + StringRef pcmOutputPath, StringRef mappedPCMPath, StringRef moduleMapFile, + StringRef contextHash, ArrayRef nonPathCommandLine, + ArrayRef fileDependencies, + ArrayRef capturedPCMArgs, + ArrayRef linkLibraries, StringRef CASFileSystemRootID, + StringRef clangIncludeTreeRoot, StringRef moduleCacheKey, bool IsSystem) { return ModuleDependencyInfo(std::make_unique( pcmOutputPath, mappedPCMPath, moduleMapFile, contextHash, - nonPathCommandLine, fileDependencies, capturedPCMArgs, + nonPathCommandLine, fileDependencies, capturedPCMArgs, linkLibraries, CASFileSystemRootID, clangIncludeTreeRoot, moduleCacheKey, IsSystem)); } /// Describe a placeholder dependency swift module. - static ModuleDependencyInfo forPlaceholderSwiftModuleStub( - const std::string &compiledModulePath, - const std::string &moduleDocPath, - const std::string &sourceInfoPath) { + static ModuleDependencyInfo + forPlaceholderSwiftModuleStub(StringRef compiledModulePath, + StringRef moduleDocPath, + StringRef sourceInfoPath) { return ModuleDependencyInfo( std::make_unique( - compiledModulePath, moduleDocPath, sourceInfoPath)); + compiledModulePath, moduleDocPath, sourceInfoPath)); } /// Retrieve the module-level imports. @@ -634,22 +638,43 @@ class ModuleDependencyInfo { } /// Resolve a dependency's set of `imports` with qualified Module IDs - void resolveDirectDependencies(const ArrayRef dependencyIDs) { + void + resolveDirectDependencies(const ArrayRef dependencyIDs) { assert(!storage->resolved && "Resolving an already-resolved dependency"); storage->resolved = true; - storage->resolvedDirectModuleDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); + storage->resolvedDirectModuleDependencies.assign(dependencyIDs.begin(), + dependencyIDs.end()); } /// Set this module's set of Swift Overlay dependencies - void setOverlayDependencies(const ArrayRef dependencyIDs) { + void + setOverlayDependencies(const ArrayRef dependencyIDs) { assert(isSwiftModule()); - storage->swiftOverlayDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); + storage->swiftOverlayDependencies.assign(dependencyIDs.begin(), + dependencyIDs.end()); } const ArrayRef getSwiftOverlayDependencies() const { return storage->swiftOverlayDependencies; } + const ArrayRef getLinkLibraries() const { + return storage->linkLibraries; + } + + void + setLinkLibraries(const ArrayRef linkLibraries) { + storage->linkLibraries.assign(linkLibraries.begin(), linkLibraries.end()); + } + + bool isStaticLibrary() const { + if (auto *detail = getAsSwiftInterfaceModule()) + return detail->isStatic; + else if (auto *detail = getAsSwiftBinaryModule()) + return detail->isStatic; + return false; + } + const ArrayRef getHeaderInputSourceFiles() const { if (auto *detail = getAsSwiftInterfaceModule()) return detail->textualModuleDetails.bridgingSourceFiles; @@ -725,19 +750,11 @@ class ModuleDependencyInfo { llvm_unreachable("Unexpected type"); } - bool isResolved() const { - return storage->resolved; - } - void setIsResolved(bool isResolved) { - storage->resolved = isResolved; - } + bool isResolved() const { return storage->resolved; } + void setIsResolved(bool isResolved) { storage->resolved = isResolved; } - bool isFinalized() const { - return storage->finalized; - } - void setIsFinalized(bool isFinalized) { - storage->finalized = isFinalized; - } + bool isFinalized() const { return storage->finalized; } + void setIsFinalized(bool isFinalized) { storage->finalized = isFinalized; } /// For a Source dependency, register a `Testable` import void addTestableImport(ImportPath::Module module); @@ -746,10 +763,12 @@ class ModuleDependencyInfo { /// of this module. Can only return `true` for Swift source modules. bool isTestableImport(StringRef moduleName) const; - /// Whether the dependencies are for a Swift module: either Textual, Source, Binary, or Placeholder. + /// Whether the dependencies are for a Swift module: either Textual, Source, + /// Binary, or Placeholder. bool isSwiftModule() const; - /// Whether the dependencies are for a textual interface Swift module or a Source Swift module. + /// Whether the dependencies are for a textual interface Swift module or a + /// Source Swift module. bool isTextualSwiftModule() const; /// Whether the dependencies are for a textual Swift module. @@ -767,12 +786,11 @@ class ModuleDependencyInfo { /// Whether the dependencies are for a Clang module. bool isClangModule() const; - ModuleDependencyKind getKind() const { - return storage->dependencyKind; - } + ModuleDependencyKind getKind() const { return storage->dependencyKind; } /// Retrieve the dependencies for a Swift textual-interface module. - const SwiftInterfaceModuleDependenciesStorage *getAsSwiftInterfaceModule() const; + const SwiftInterfaceModuleDependenciesStorage * + getAsSwiftInterfaceModule() const; /// Retrieve the dependencies for a Swift module. const SwiftSourceModuleDependenciesStorage *getAsSwiftSourceModule() const; @@ -785,11 +803,12 @@ class ModuleDependencyInfo { /// Retrieve the dependencies for a placeholder dependency module stub. const SwiftPlaceholderModuleDependencyStorage * - getAsPlaceholderDependencyModule() const; + getAsPlaceholderDependencyModule() const; /// Add a dependency on the given module, if it was not already in the set. - void addOptionalModuleImport(StringRef module, - llvm::StringSet<> *alreadyAddedModules = nullptr); + void + addOptionalModuleImport(StringRef module, + llvm::StringSet<> *alreadyAddedModules = nullptr); /// Add all of the module imports in the given source /// file to the set of module imports. @@ -852,11 +871,11 @@ class ModuleDependencyInfo { std::vector> &overlayFiles) const; }; -using ModuleDependencyVector = llvm::SmallVector, 1>; +using ModuleDependencyVector = + llvm::SmallVector, 1>; using ModuleNameToDependencyMap = llvm::StringMap; using ModuleDependenciesKindMap = - std::unordered_map; using ModuleDependenciesKindRefMap = std::unordered_map getCachingFS() const { return CacheFS; } + llvm::IntrusiveRefCntPtr + getCachingFS() const { + return CacheFS; + } llvm::cas::CachingOnDiskFileSystem &getSharedCachingFS() const { assert(CacheFS && "Expect CachingOnDiskFileSystem"); @@ -988,6 +1011,7 @@ class SwiftDependencyScanningService { /// Setup caching service. bool setupCachingDependencyScanningService(CompilerInstance &Instance); + private: /// Enforce clients not being allowed to query this cache directly, it must be /// wrapped in an instance of `ModuleDependenciesCache`. @@ -1024,16 +1048,18 @@ class SwiftDependencyScanningService { StringRef scanContextHash) const; /// Record dependencies for the given module. - const ModuleDependencyInfo *recordDependency(StringRef moduleName, - ModuleDependencyInfo dependencies, - StringRef scanContextHash); + const ModuleDependencyInfo * + recordDependency(StringRef moduleName, ModuleDependencyInfo dependencies, + StringRef scanContextHash); /// Update stored dependencies for the given module. - const ModuleDependencyInfo *updateDependency(ModuleDependencyID moduleID, - ModuleDependencyInfo dependencies, - StringRef scanContextHash); + const ModuleDependencyInfo * + updateDependency(ModuleDependencyID moduleID, + ModuleDependencyInfo dependencies, + StringRef scanContextHash); - /// Reference the list of all module dependency infos for a given scanning context + /// Reference the list of all module dependency infos for a given scanning + /// context const std::vector & getAllModules(StringRef scanningContextHash) const { auto contextSpecificCache = @@ -1054,7 +1080,8 @@ class ModuleDependenciesCache { /// References to data in the `globalScanningService` for module dependencies ModuleDependenciesKindRefMap ModuleDependenciesMap; /// Set containing all of the Clang modules that have already been seen. - llvm::DenseSet alreadySeenClangModules; + llvm::DenseSet + alreadySeenClangModules; /// Name of the module under scan std::string mainScanModuleName; /// The context hash of the current scanning invocation @@ -1092,15 +1119,14 @@ class ModuleDependenciesCache { const SwiftDependencyScanningService &getScanService() const { return globalScanningService; } - const llvm::DenseSet& getAlreadySeenClangModules() const { + const llvm::DenseSet & + getAlreadySeenClangModules() const { return alreadySeenClangModules; } void addSeenClangModule(clang::tooling::dependencies::ModuleID newModule) { alreadySeenClangModules.insert(newModule); } - std::string getModuleOutputPath() const { - return moduleOutputPath; - } + std::string getModuleOutputPath() const { return moduleOutputPath; } /// Query all dependencies, direct and Swift overlay. std::vector @@ -1152,19 +1178,18 @@ class ModuleDependenciesCache { /// Resolve a dependency module's set of imports /// to a kind-qualified set of module IDs. - void resolveDependencyImports(ModuleDependencyID moduleID, - const ArrayRef dependencyIDs); + void + resolveDependencyImports(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs); /// Resolve a dependency module's set of Swift module dependencies /// that are Swift overlays of Clang module dependencies. - void setSwiftOverlayDependencies(ModuleDependencyID moduleID, - const ArrayRef dependencyIDs); - - StringRef getMainModuleName() const { - return mainScanModuleName; - } -}; + void + setSwiftOverlayDependencies(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs); + StringRef getMainModuleName() const { return mainScanModuleName; } +}; } // namespace swift namespace std { diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index a00dff1d6749a..64681e469dcfb 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -60,10 +60,19 @@ struct swiftscan_dependency_info_s { */ swiftscan_string_set_t *direct_dependencies; + /// The list of link libraries for this module. + swiftscan_link_library_set_t *link_libraries; + /// Specific details of a particular kind of module. swiftscan_module_details_t details; }; +struct swiftscan_link_library_info_s { + swiftscan_string_ref_t name; + bool isFramework; + bool forceLoad; +}; + /// Swift modules to be built from a module interface, may have a bridging /// header. typedef struct { @@ -103,6 +112,9 @@ typedef struct { /// A flag to indicate whether or not this module is a framework. bool is_framework; + /// A flag that indicates this dependency is associated with a static archive + bool is_static; + /// The CASID for CASFileSystemRoot swiftscan_string_ref_t cas_fs_root_id; @@ -140,6 +152,9 @@ typedef struct { /// A flag to indicate whether or not this module is a framework. bool is_framework; + /// A flag that indicates this dependency is associated with a static archive + bool is_static; + /// ModuleCacheKey swiftscan_string_ref_t module_cache_key; } swiftscan_swift_binary_details_t; diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index f5895cf28eeb5..f520cca659fbc 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -55,6 +55,8 @@ using ContextHashIDField = IdentifierIDField; using IsFrameworkField = BCFixed<1>; /// A bit that indicates whether or not a module is a system module using IsSystemField = BCFixed<1>; +/// A bit that indicates whether or not a module is that of a static archive +using IsStaticField = BCFixed<1>; /// Arrays of various identifiers, distinguished for readability using IdentifierIDArryField = llvm::BCArray; @@ -140,10 +142,11 @@ using SwiftInterfaceModuleDetailsLayout = FlagIDArrayIDField, // extraPCMArgs ContextHashIDField, // contextHash IsFrameworkField, // isFramework + IsStaticField, // isStatic FileIDField, // bridgingHeaderFile FileIDArrayIDField, // sourceFiles FileIDArrayIDField, // bridgingSourceFiles - IdentifierIDField, // bridgingModuleDependencies + IdentifierIDField, // bridgingModuleDependencies DependencyIDArrayIDField, // swiftOverlayDependencies IdentifierIDField, // CASFileSystemRootID IdentifierIDField, // bridgingHeaderIncludeTree @@ -174,6 +177,7 @@ using SwiftBinaryModuleDetailsLayout = IdentifierIDField, // headerModuleDependencies FileIDArrayIDField, // headerSourceFiles IsFrameworkField, // isFramework + IsStaticField, // isStatic IdentifierIDField // moduleCacheKey >; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index a50cf5cd7c6ad..1cbcc3e8a4341 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -557,6 +557,10 @@ def disable_autolink_frameworks : Flag<["-"],"disable-autolink-frameworks">, def disable_all_autolinking : Flag<["-"],"disable-all-autolinking">, HelpText<"Disable all Swift autolink directives">; +def disable_force_load_symbols : Flag<["-"],"disable-force-load-symbols">, + Flags<[FrontendOption, HelpHidden]>, + HelpText<"Disable generation of all Swift _FORCE_LOAD symbols">; + def disable_diagnostic_passes : Flag<["-"], "disable-diagnostic-passes">, HelpText<"Don't run diagnostic passes">; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index e6d38cb396e41..b310870c49387 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1376,6 +1376,10 @@ def explain_module_dependency : Separate<["-"], "explain-module-dependency">, Flags<[NewDriverOnlyOption]>, HelpText<"Emit remark/notes describing why compilation may depend on a module with a given name.">; +def explicit_auto_linking : Flag<["-"], "explicit-auto-linking">, + Flags<[NewDriverOnlyOption]>, + HelpText<"Instead of linker-load directives, have the driver specify all link dependencies on the linker invocation. Requires '-explicit-module-build'.">; + def min_inlining_target_version : Separate<["-"], "target-min-inlining-version">, Flags<[FrontendOption, ModuleInterfaceOption]>, HelpText<"Require inlinable code with no '@available' attribute to back-deploy " diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 6c2606ed07b7e..03051d88d8bad 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -306,9 +306,9 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal, if (!proto) continue; auto kp = proto->getKnownProtocolKind(); - assert(!found.isSuppressed || - kp.has_value() && - "suppressed conformance for non-known protocol!?"); + assert(!found.isSuppressed || + kp.has_value() && + "suppressed conformance for non-known protocol!?"); if (!found.isSuppressed) { addProtocol(proto, found.Loc, source.withUncheckedLoc(found.uncheckedLoc) diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 618876627fb7d..17dbb88505d3f 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -483,7 +483,7 @@ SwiftDependencyScanningService::SwiftDependencyScanningService() { } bool -swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath, +swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath, const SourceLoc importLoc, const SourceFile &SF, bool isExported) { @@ -509,6 +509,85 @@ swift::dependencies::checkImportNotTautological(const ImportPath::Module moduleP return false; } +void +swift::dependencies::registerCxxInteropLibraries( + const llvm::Triple &Target, + StringRef mainModuleName, + bool hasStaticCxx, bool hasStaticCxxStdlib, + std::function RegistrationCallback) { + if (Target.isOSDarwin()) + RegistrationCallback(LinkLibrary("c++", LibraryKind::Library)); + else if (Target.isOSLinux()) + RegistrationCallback(LinkLibrary("stdc++", LibraryKind::Library)); + + // Do not try to link Cxx with itself. + if (mainModuleName != "Cxx") { + RegistrationCallback(LinkLibrary(Target.isOSWindows() && hasStaticCxx + ? "libswiftCxx" + : "swiftCxx", + LibraryKind::Library)); + } + + // Do not try to link CxxStdlib with the C++ standard library, Cxx or + // itself. + if (llvm::none_of(llvm::ArrayRef{"Cxx", "CxxStdlib", "std"}, + [mainModuleName](StringRef Name) { + return mainModuleName == Name; + })) { + // Only link with CxxStdlib on platforms where the overlay is available. + switch (Target.getOS()) { + case llvm::Triple::Linux: + if (!Target.isAndroid()) + RegistrationCallback(LinkLibrary("swiftCxxStdlib", + LibraryKind::Library)); + break; + case llvm::Triple::Win32: { + RegistrationCallback( + LinkLibrary(hasStaticCxxStdlib ? "libswiftCxxStdlib" : "swiftCxxStdlib", + LibraryKind::Library)); + break; + } + default: + if (Target.isOSDarwin()) + RegistrationCallback(LinkLibrary("swiftCxxStdlib", + LibraryKind::Library)); + break; + } + } +} + +void +swift::dependencies::registerBackDeployLibraries( + const IRGenOptions &IRGenOpts, + std::function RegistrationCallback) { + auto addBackDeployLib = [&](llvm::VersionTuple version, + StringRef libraryName, bool forceLoad) { + std::optional compatibilityVersion; + if (libraryName == "swiftCompatibilityDynamicReplacements") { + compatibilityVersion = IRGenOpts. + AutolinkRuntimeCompatibilityDynamicReplacementLibraryVersion; + } else if (libraryName == "swiftCompatibilityConcurrency") { + compatibilityVersion = + IRGenOpts.AutolinkRuntimeCompatibilityConcurrencyLibraryVersion; + } else { + compatibilityVersion = IRGenOpts. + AutolinkRuntimeCompatibilityLibraryVersion; + } + + if (!compatibilityVersion) + return; + + if (*compatibilityVersion > version) + return; + + RegistrationCallback({libraryName, LibraryKind::Library, forceLoad}); + }; + +#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \ + addBackDeployLib(llvm::VersionTuple Version, LibraryName, ForceLoad); + #include "swift/Frontend/BackDeploymentLibs.def" +} + void SwiftDependencyTracker::addCommonSearchPathDeps( const SearchPathOptions &Opts) { // Add SDKSetting file. diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 06f12575bee2f..cf054231728d6 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -285,12 +285,19 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies( if (Mapper) Mapper->mapInPlace(mappedPCMPath); + std::vector LinkLibraries; + for (const auto &ll : clangModuleDep.LinkLibraries) + LinkLibraries.push_back( + {ll.Library, + ll.IsFramework ? LibraryKind::Framework : LibraryKind::Library}); + // Module-level dependencies. llvm::StringSet<> alreadyAddedModules; auto dependencies = ModuleDependencyInfo::forClangModule( pcmPath, mappedPCMPath, clangModuleDep.ClangModuleMapFile, clangModuleDep.ID.ContextHash, swiftArgs, fileDeps, capturedPCMArgs, - RootID, IncludeTree, /*module-cache-key*/ "", clangModuleDep.IsSystem); + LinkLibraries, RootID, IncludeTree, /*module-cache-key*/ "", + clangModuleDep.IsSystem); for (const auto &moduleName : clangModuleDep.ClangModuleDeps) { dependencies.addModuleImport(moduleName.ModuleName, &alreadyAddedModules); // It is safe to assume that all dependencies of a Clang module are Clang modules. diff --git a/lib/DependencyScan/DependencyScanJSON.cpp b/lib/DependencyScan/DependencyScanJSON.cpp index 133b98b7e7329..7d89271a6051c 100644 --- a/lib/DependencyScan/DependencyScanJSON.cpp +++ b/lib/DependencyScan/DependencyScanJSON.cpp @@ -202,6 +202,46 @@ static void writeDependencies(llvm::raw_ostream &out, out << "\n"; } +void writeLinkLibraries(llvm::raw_ostream &out, + const swiftscan_link_library_set_t *link_libraries, + unsigned indentLevel, bool trailingComma) { + out.indent(indentLevel * 2); + out << "\"linkLibraries\": "; + out << "[\n"; + + for (size_t i = 0; i < link_libraries->count; ++i) { + const auto &llInfo = *link_libraries->link_libraries[i]; + out.indent((indentLevel + 1) * 2); + out << "{\n"; + auto entryIndentLevel = ((indentLevel + 2) * 2); + out.indent(entryIndentLevel); + out << "\"linkName\": "; + writeJSONValue(out, llInfo.name, indentLevel); + out << ",\n"; + out.indent(entryIndentLevel); + out << "\"isFramework\": "; + writeJSONValue(out, llInfo.isFramework, entryIndentLevel); + out << ",\n"; + out.indent(entryIndentLevel); + out << "\"shouldForceLoad\": "; + writeJSONValue(out, llInfo.forceLoad, entryIndentLevel); + out << "\n"; + out.indent((indentLevel + 1) * 2); + out << "}"; + if (i != link_libraries->count - 1) { + out << ","; + } + out << "\n"; + } + + out.indent(indentLevel * 2); + out << "]"; + + if (trailingComma) + out << ","; + out << "\n"; +} + static const swiftscan_swift_textual_details_t * getAsTextualDependencyModule(swiftscan_module_details_t details) { if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL) @@ -295,10 +335,13 @@ void writeJSON(llvm::raw_ostream &out, } // Direct dependencies. - if (swiftTextualDeps || swiftBinaryDeps || clangDeps) + if (swiftTextualDeps || swiftBinaryDeps || clangDeps) { writeDependencies(out, directDependencies, "directDependencies", 3, /*trailingComma=*/true); + writeLinkLibraries(out, moduleInfo.link_libraries, + 3, /*trailingComma=*/true); + } // Swift and Clang-specific details. out.indent(3 * 2); out << "\"details\": {\n"; diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index 3783957c3099c..6eeec2b04cee1 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -251,14 +251,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi cache.configureForContextHash(getContextHash()); unsigned outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, - extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, + extraPCMArgsArrayID, contextHashID, isFramework, isStatic, bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, overlayDependencyIDArrayID, CASFileSystemRootID, bridgingHeaderIncludeTreeID, moduleCacheKeyID; SwiftInterfaceModuleDetailsLayout::readRecord( Scratch, outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, - extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, + extraPCMArgsArrayID, contextHashID, isFramework, isStatic, bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, overlayDependencyIDArrayID, CASFileSystemRootID, bridgingHeaderIncludeTreeID, moduleCacheKeyID); @@ -293,6 +293,9 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi std::vector extraPCMRefs; for (auto &arg : *extraPCMArgs) extraPCMRefs.push_back(arg); + std::vector compiledCandidatesRefs; + for (auto &cc : compiledCandidatesRefs) + compiledCandidatesRefs.push_back(cc); auto rootFileSystemID = getIdentifier(CASFileSystemRootID); if (!rootFileSystemID) @@ -301,11 +304,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi if (!moduleCacheKeyID) llvm::report_fatal_error("Bad moduleCacheKey"); + // TODO: LinkLibraries // Form the dependencies storage object auto moduleDep = ModuleDependencyInfo::forSwiftInterfaceModule( outputModulePath.value(), optionalSwiftInterfaceFile.value(), - *compiledModuleCandidates, buildCommandRefs, extraPCMRefs, - *contextHash, isFramework, *rootFileSystemID, *moduleCacheKey); + compiledCandidatesRefs, buildCommandRefs, {}, extraPCMRefs, + *contextHash, isFramework, isStatic, *rootFileSystemID, *moduleCacheKey); // Add imports of this module for (const auto &moduleName : currentModuleImports) @@ -484,13 +488,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi unsigned compiledModulePathID, moduleDocPathID, moduleSourceInfoPathID, overlayDependencyIDArrayID, headerImportID, headerModuleDependenciesArrayID, - headerImportsSourceFilesArrayID, isFramework, + headerImportsSourceFilesArrayID, isFramework, isStatic, moduleCacheKeyID; SwiftBinaryModuleDetailsLayout::readRecord( Scratch, compiledModulePathID, moduleDocPathID, moduleSourceInfoPathID, overlayDependencyIDArrayID, headerImportID, headerModuleDependenciesArrayID, - headerImportsSourceFilesArrayID, isFramework, moduleCacheKeyID); + headerImportsSourceFilesArrayID, isFramework, isStatic, + moduleCacheKeyID); auto compiledModulePath = getIdentifier(compiledModulePathID); if (!compiledModulePath) @@ -508,11 +513,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi if (!headerImport) llvm::report_fatal_error("Bad binary direct dependencies: no header import"); + // TODO: LinkLibraries // Form the dependencies storage object auto moduleDep = ModuleDependencyInfo::forSwiftBinaryModule( *compiledModulePath, *moduleDocPath, *moduleSourceInfoPath, - currentModuleImports, currentOptionalModuleImports, - *headerImport, isFramework, *moduleCacheKey); + currentModuleImports, currentOptionalModuleImports, {}, + *headerImport, isFramework, isStatic, *moduleCacheKey); auto headerModuleDependencies = getStringArray(headerModuleDependenciesArrayID); if (!headerModuleDependencies) @@ -619,10 +625,11 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi if (!moduleCacheKeyID) llvm::report_fatal_error("Bad moduleCacheKey"); + // TODO: LinkLibraries // Form the dependencies storage object auto moduleDep = ModuleDependencyInfo::forClangModule( *pcmOutputPath, *mappedPCMPath, *moduleMapPath, *contextHash, - *commandLineArgs, *fileDependencies, *capturedPCMArgs, + *commandLineArgs, *fileDependencies, *capturedPCMArgs, {}, *rootFileSystemID, *clangIncludeTreeRoot, *moduleCacheKey, isSystem); // Add dependencies of this module @@ -984,7 +991,8 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo( ModuleIdentifierArrayKind::CompiledModuleCandidates), getArrayID(moduleID, ModuleIdentifierArrayKind::BuildCommandLine), getArrayID(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs), - getIdentifier(swiftTextDeps->contextHash), swiftTextDeps->isFramework, + getIdentifier(swiftTextDeps->contextHash), + swiftTextDeps->isFramework, swiftTextDeps->isStatic, bridgingHeaderFileId, getArrayID(moduleID, ModuleIdentifierArrayKind::SourceFiles), getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles), @@ -1040,7 +1048,7 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo( getArrayID(moduleID, ModuleIdentifierArrayKind::DependencyHeaders), getArrayID(moduleID, ModuleIdentifierArrayKind::HeaderInputModuleDependencies), getArrayID(moduleID, ModuleIdentifierArrayKind::HeaderInputDependencySourceFiles), - swiftBinDeps->isFramework, + swiftBinDeps->isFramework, swiftBinDeps->isStatic, getIdentifier(swiftBinDeps->moduleCacheKey)); break; diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index d37c55d5c9ccf..667b8416f364a 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -714,6 +714,7 @@ generateFullDependencyGraph(const CompilerInstance &instance, create_set(swiftTextualDeps->textualModuleDetails.extraPCMArgs), create_clone(swiftTextualDeps->contextHash.c_str()), swiftTextualDeps->isFramework, + swiftTextualDeps->isStatic, create_clone(swiftTextualDeps->textualModuleDetails .CASFileSystemRootID.c_str()), create_clone(swiftTextualDeps->textualModuleDetails @@ -746,6 +747,7 @@ generateFullDependencyGraph(const CompilerInstance &instance, create_clone( instance.getInvocation().getModuleScanningHash().c_str()), /*isFramework*/ false, + /*isStatic*/ false, /*CASFS*/ create_clone(swiftSourceDeps->textualModuleDetails .CASFileSystemRootID.c_str()), @@ -774,6 +776,7 @@ generateFullDependencyGraph(const CompilerInstance &instance, create_set(swiftBinaryDeps->headerModuleDependencies), create_set(swiftBinaryDeps->headerSourceFiles), swiftBinaryDeps->isFramework, + swiftBinaryDeps->isStatic, create_clone(swiftBinaryDeps->moduleCacheKey.c_str())}; } else { // Clang module details @@ -804,6 +807,23 @@ generateFullDependencyGraph(const CompilerInstance &instance, bridgeDependencyIDs(directDependencies, bridgedDependencyNames); moduleInfo->direct_dependencies = create_set(bridgedDependencyNames); moduleInfo->details = getModuleDetails(); + + // Create a link libraries set for this module + auto &linkLibraries = depInfo.getLinkLibraries(); + swiftscan_link_library_set_t *linkLibrarySet = + new swiftscan_link_library_set_t; + linkLibrarySet->count = linkLibraries.size(); + linkLibrarySet->link_libraries = + new swiftscan_link_library_info_t[linkLibrarySet->count]; + for (size_t i = 0; i < linkLibraries.size(); ++i) { + const auto &ll = linkLibraries[i]; + swiftscan_link_library_info_s *llInfo = new swiftscan_link_library_info_s; + llInfo->name = create_clone(ll.getName().str().c_str()); + llInfo->isFramework = ll.getKind() == LibraryKind::Framework; + llInfo->forceLoad = ll.shouldForceLoad(); + linkLibrarySet->link_libraries[i] = llInfo; + } + moduleInfo->link_libraries = linkLibrarySet; } swiftscan_dependency_graph_t result = new swiftscan_dependency_graph_s; @@ -1406,10 +1426,46 @@ updateDependencyTracker(CompilerInstance &instance, } } +static void resolveImplicitLinkLibraries(const CompilerInstance &instance, + ModuleDependenciesCache &cache) { + auto langOpts = instance.getInvocation().getLangOptions(); + auto irGenOpts = instance.getInvocation().getIRGenOptions(); + auto mainModuleName = instance.getMainModule()->getNameStr(); + auto mainModuleID = ModuleDependencyID{mainModuleName.str(), + ModuleDependencyKind::SwiftSource}; + auto mainModuleDepInfo = cache.findKnownDependency(mainModuleID); + + std::vector linkLibraries; + auto addLinkLibrary = [&linkLibraries](const LinkLibrary &ll) { + linkLibraries.push_back(ll); + }; + + if (langOpts.EnableObjCInterop) + addLinkLibrary({"objc", LibraryKind::Library}); + + if (langOpts.EnableCXXInterop) { + auto OptionalCxxDep = cache.findDependency("Cxx"); + auto OptionalCxxStdLibDep = cache.findDependency("CxxStdlib"); + bool hasStaticCxx = + OptionalCxxDep.has_value() && OptionalCxxDep.value()->isStaticLibrary(); + bool hasStaticCxxStdlib = OptionalCxxStdLibDep.has_value() && + OptionalCxxStdLibDep.value()->isStaticLibrary(); + registerCxxInteropLibraries(langOpts.Target, mainModuleName, hasStaticCxx, + hasStaticCxxStdlib, addLinkLibrary); + } + + if (!irGenOpts.UseJIT && !langOpts.hasFeature(Feature::Embedded)) + registerBackDeployLibraries(irGenOpts, addLinkLibrary); + + mainModuleDepInfo.setLinkLibraries(linkLibraries); + cache.updateDependency(mainModuleID, mainModuleDepInfo); +} + llvm::ErrorOr -swift::dependencies::performModuleScan(CompilerInstance &instance, - DependencyScanDiagnosticCollector *diagnosticCollector, - ModuleDependenciesCache &cache) { +swift::dependencies::performModuleScan( + CompilerInstance &instance, + DependencyScanDiagnosticCollector *diagnosticCollector, + ModuleDependenciesCache &cache) { auto scanner = ModuleDependencyScanner( cache.getScanService(), instance.getInvocation(), instance.getSILOptions(), instance.getASTContext(), @@ -1425,10 +1481,8 @@ swift::dependencies::performModuleScan(CompilerInstance &instance, ModuleDependencyKind::SwiftSource}; // We may be re-using an instance of the cache which already contains // an entry for this module. - if (cache.findDependency(mainModuleName, ModuleDependencyKind::SwiftSource)) - cache.updateDependency( - ModuleDependencyID{mainModuleName.str(), ModuleDependencyKind::SwiftSource}, - std::move(*mainModuleDepInfo)); + if (cache.findDependency(mainModuleID)) + cache.updateDependency(mainModuleID, std::move(*mainModuleDepInfo)); else cache.recordDependency(mainModuleName, std::move(*mainModuleDepInfo)); @@ -1451,7 +1505,7 @@ swift::dependencies::performModuleScan(CompilerInstance &instance, computeTopologicalSortOfExplicitDependencies(allModules, cache); resolveDependencyCommandLineArguments(instance, cache, topologicallySortedModuleList); - + resolveImplicitLinkLibraries(instance, cache); updateDependencyTracker(instance, cache, allModules); return generateFullDependencyGraph(instance, diagnosticCollector, cache, topologicallySortedModuleList); @@ -1542,8 +1596,8 @@ swift::dependencies::performBatchModuleScan( : ModuleDependencyKind::SwiftInterface}; auto allDependencies = scanner.getModuleDependencies(moduleID, cache); batchScanResult.push_back( - generateFullDependencyGraph(instance, diagnosticCollector, - cache, allDependencies)); + generateFullDependencyGraph(instance, diagnosticCollector, cache, + allDependencies)); if (diagnosticCollector) diagnosticCollector->reset(); }); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d7872e3d3acaa..26e5f319e9407 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2995,6 +2995,7 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, } Opts.DisableFrameworkAutolinking = Args.hasArg(OPT_disable_autolink_frameworks); Opts.DisableAllAutolinking = Args.hasArg(OPT_disable_all_autolinking); + Opts.DisableForceLoadSymbols = Args.hasArg(OPT_disable_force_load_symbols); Opts.GenerateProfile |= Args.hasArg(OPT_profile_generate); const Arg *ProfileUse = Args.getLastArg(OPT_profile_use); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 51ac5e3e754ba..f549411e4965f 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -22,6 +22,7 @@ #include "swift/AST/GenericSignature.h" #include "swift/AST/IRGenOptions.h" #include "swift/AST/Module.h" +#include "swift/AST/ModuleDependencies.h" #include "swift/AST/NameLookup.h" #include "swift/AST/Pattern.h" #include "swift/AST/ProtocolConformance.h" @@ -475,61 +476,33 @@ void IRGenModule::emitSourceFile(SourceFile &SF) { for (auto *opaqueDecl : SF.getOpaqueReturnTypeDecls()) maybeEmitOpaqueTypeDecl(opaqueDecl); - SF.collectLinkLibraries([this](LinkLibrary linkLib) { - this->addLinkLibrary(linkLib); + auto registerLinkLibrary = [this](const LinkLibrary &ll) { + this->addLinkLibrary(ll); + }; + + SF.collectLinkLibraries([registerLinkLibrary](LinkLibrary linkLib) { + registerLinkLibrary(linkLib); }); if (ObjCInterop) - this->addLinkLibrary(LinkLibrary("objc", LibraryKind::Library)); + registerLinkLibrary(LinkLibrary("objc", LibraryKind::Library)); // If C++ interop is enabled, add -lc++ on Darwin and -lstdc++ on linux. // Also link with C++ bridging utility module (Cxx) and C++ stdlib overlay // (std) if available. if (Context.LangOpts.EnableCXXInterop) { - const llvm::Triple &target = Context.LangOpts.Target; - if (target.isOSDarwin()) - this->addLinkLibrary(LinkLibrary("c++", LibraryKind::Library)); - else if (target.isOSLinux()) - this->addLinkLibrary(LinkLibrary("stdc++", LibraryKind::Library)); - - // Do not try to link Cxx with itself. - if (!getSwiftModule()->getName().is("Cxx")) { - bool isStatic = false; - if (const auto *M = Context.getModuleByName("Cxx")) - isStatic = M->isStaticLibrary(); - this->addLinkLibrary(LinkLibrary(target.isOSWindows() && isStatic - ? "libswiftCxx" - : "swiftCxx", - LibraryKind::Library)); - } - - // Do not try to link CxxStdlib with the C++ standard library, Cxx or - // itself. - if (llvm::none_of(llvm::ArrayRef{"Cxx", "CxxStdlib", "std"}, - [M = getSwiftModule()->getName().str()](StringRef Name) { - return M == Name; - })) { - // Only link with CxxStdlib on platforms where the overlay is available. - switch (target.getOS()) { - case llvm::Triple::Linux: - if (!target.isAndroid()) - this->addLinkLibrary(LinkLibrary("swiftCxxStdlib", - LibraryKind::Library)); - break; - case llvm::Triple::Win32: { - bool isStatic = Context.getModuleByName("CxxStdlib")->isStaticLibrary(); - this->addLinkLibrary( - LinkLibrary(isStatic ? "libswiftCxxStdlib" : "swiftCxxStdlib", - LibraryKind::Library)); - break; - } - default: - if (target.isOSDarwin()) - this->addLinkLibrary(LinkLibrary("swiftCxxStdlib", - LibraryKind::Library)); - break; - } - } + bool hasStaticCxx = false; + bool hasStaticCxxStdlib = false; + if (const auto *M = Context.getModuleByName("Cxx")) + hasStaticCxx = M->isStaticLibrary(); + if (Context.LangOpts.Target.getOS() == llvm::Triple::Win32) + if (const auto *M = Context.getModuleByName("CxxStdlib")) + hasStaticCxxStdlib = M->isStaticLibrary(); + dependencies::registerCxxInteropLibraries(Context.LangOpts.Target, + getSwiftModule()->getName().str(), + hasStaticCxx, + hasStaticCxxStdlib, + registerLinkLibrary); } // FIXME: It'd be better to have the driver invocation or build system that @@ -541,36 +514,8 @@ void IRGenModule::emitSourceFile(SourceFile &SF) { // libraries. This may however cause the library to get pulled in in // situations where it isn't useful, such as for dylibs, though this is // harmless aside from code size. - if (!IRGen.Opts.UseJIT && !Context.LangOpts.hasFeature(Feature::Embedded)) { - auto addBackDeployLib = [&](llvm::VersionTuple version, - StringRef libraryName, bool forceLoad) { - std::optional compatibilityVersion; - if (libraryName == "swiftCompatibilityDynamicReplacements") { - compatibilityVersion = IRGen.Opts. - AutolinkRuntimeCompatibilityDynamicReplacementLibraryVersion; - } else if (libraryName == "swiftCompatibilityConcurrency") { - compatibilityVersion = - IRGen.Opts.AutolinkRuntimeCompatibilityConcurrencyLibraryVersion; - } else { - compatibilityVersion = IRGen.Opts. - AutolinkRuntimeCompatibilityLibraryVersion; - } - - if (!compatibilityVersion) - return; - - if (*compatibilityVersion > version) - return; - - this->addLinkLibrary(LinkLibrary(libraryName, - LibraryKind::Library, - forceLoad)); - }; - -#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \ - addBackDeployLib(llvm::VersionTuple Version, LibraryName, ForceLoad); - #include "swift/Frontend/BackDeploymentLibs.def" - } + if (!IRGen.Opts.UseJIT && !Context.LangOpts.hasFeature(Feature::Embedded)) + dependencies::registerBackDeployLibraries(IRGen.Opts, registerLinkLibrary); } /// Emit all the top-level code in the synthesized file unit. diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index 4158847a6bf6b..0d9b66255f1ea 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1583,7 +1583,7 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { } } - if (linkLib.shouldForceLoad()) { + if (!IRGen.Opts.DisableForceLoadSymbols && linkLib.shouldForceLoad()) { llvm::SmallString<64> buf; encodeForceLoadSymbolName(buf, linkLib.getName()); auto ForceImportThunk = cast( diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 8ffd8dadd5649..00e0a513f85ba 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -574,6 +574,10 @@ UnboundImport::UnboundImport(AttributedImport implicit) // MARK: Import validation (except for scoped imports) //===----------------------------------------------------------------------===// +ImportOptions getImportOptions(ImportDecl *ID) { + return ImportOptions(); +} + /// Create an UnboundImport for a user-written import declaration. UnboundImport::UnboundImport(ImportDecl *ID) : import(UnloadedImportedModule(ID->getImportPath(), ID->getImportKind()), diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h index 5acf1b58a2441..015ec374f6e10 100644 --- a/lib/Serialization/ModuleFileSharedCore.h +++ b/lib/Serialization/ModuleFileSharedCore.h @@ -608,6 +608,21 @@ class ModuleFileSharedCore { return Dependencies; } + /// Returns the list of modules this module depends on. + ArrayRef getLinkLibraries() const { + return LinkLibraries; + } + + /// Does this module correspond to a framework. + bool isFramework() const { + return Bits.IsFramework; + } + + /// Does this module correspond to a static archive. + bool isStaticLibrary() const { + return Bits.IsStaticLibrary; + } + /// Returns \c true if this module file contains a section with incremental /// information. bool hasIncrementalInfo() const { return HasIncrementalInfo; } diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 543f0b558ce32..be657331dfecf 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -225,11 +225,28 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, auto sourceFile = new (Ctx) SourceFile( *moduleDecl, SourceFileKind::Interface, bufferID, parsingOpts); moduleDecl->addAuxiliaryFile(*sourceFile); - std::vector ArgsRefs(Args.begin(), Args.end()); + std::vector compiledCandidatesRefs(compiledCandidates.begin(), + compiledCandidates.end()); + + // If this interface specified '-autolink-force-load', add it to the + // set of linked libraries for this module. + std::vector linkLibraries; + if (llvm::find(ArgsRefs, "-autolink-force-load") != ArgsRefs.end()) { + std::string linkName = realModuleName.str().str(); + auto linkNameArgIt = llvm::find(ArgsRefs, "-module-link-name"); + if (linkNameArgIt != ArgsRefs.end()) + linkName = *(linkNameArgIt+1); + linkLibraries.push_back({linkName, + isFramework ? LibraryKind::Framework : LibraryKind::Library, + true}); + } + bool isStatic = llvm::find(ArgsRefs, "-static") != ArgsRefs.end(); + Result = ModuleDependencyInfo::forSwiftInterfaceModule( - outputPathBase.str().str(), InPath, compiledCandidates, ArgsRefs, - PCMArgs, Hash, isFramework, {}, /*module-cache-key*/ ""); + outputPathBase.str().str(), InPath, compiledCandidatesRefs, + ArgsRefs, linkLibraries, PCMArgs, Hash, isFramework, isStatic, {}, + /*module-cache-key*/ ""); if (Ctx.CASOpts.EnableCaching) { std::vector clangDependencyFiles; diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 3bd010593d598..006fb055bd70c 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -499,11 +499,21 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework, optionalModuleImports.push_back( ScannerImportStatementInfo(optionalImportedModule.str())); + std::vector linkLibraries; + { + linkLibraries.reserve(loadedModuleFile->getLinkLibraries().size()); + llvm::copy(loadedModuleFile->getLinkLibraries(), + std::back_inserter(linkLibraries)); + if (loadedModuleFile->isFramework()) + linkLibraries.push_back(LinkLibrary(loadedModuleFile->getName(), + LibraryKind::Framework)); + } + // Map the set of dependencies over to the "module dependencies". auto dependencies = ModuleDependencyInfo::forSwiftBinaryModule( modulePath.str(), moduleDocPath, sourceInfoPath, moduleImports, - optionalModuleImports, importedHeader, isFramework, - /*module-cache-key*/ ""); + optionalModuleImports, linkLibraries, importedHeader, isFramework, + loadedModuleFile->isStaticLibrary(), /*module-cache-key*/ ""); return std::move(dependencies); } diff --git a/test/CAS/module_deps.swift b/test/CAS/module_deps.swift index fd2957394c6df..7dab6878cf021 100644 --- a/test/CAS/module_deps.swift +++ b/test/CAS/module_deps.swift @@ -131,7 +131,8 @@ import SubE // CHECK-DAG: "swift": "Swift" // CHECK-DAG: "swift": "SwiftOnoneSupport" // CHECK: ], -// CHECK-NEXT: "details": { +// CHECK-NEXT: "linkLibraries": [ +// CHECK: "details": { // CHECK: "commandLine": [ // CHECK: "-compile-module-from-interface" diff --git a/test/CAS/module_deps_include_tree.swift b/test/CAS/module_deps_include_tree.swift index 813dd8a1a7782..ef5c38284ef20 100644 --- a/test/CAS/module_deps_include_tree.swift +++ b/test/CAS/module_deps_include_tree.swift @@ -130,7 +130,8 @@ import SubE // CHECK-DAG: "swift": "Swift" // CHECK-DAG: "swift": "SwiftOnoneSupport" // CHECK: ], -// CHECK-NEXT: "details": { +// CHECK-NEXT: "linkLibraries": [ +// CHECK: "details": { // CHECK: "commandLine": [ // CHECK: "-compile-module-from-interface" diff --git a/test/CAS/plugin_cas.swift b/test/CAS/plugin_cas.swift index a31f66b071f6f..78a592863cb6c 100644 --- a/test/CAS/plugin_cas.swift +++ b/test/CAS/plugin_cas.swift @@ -113,7 +113,8 @@ import SubE // CHECK-DAG: "swift": "Swift" // CHECK-DAG: "swift": "SwiftOnoneSupport" // CHECK: ], -// CHECK-NEXT: "details": { +// CHECK-NEXT: "linkLibraries": [ +// CHECK: "details": { // CHECK: "commandLine": [ // CHECK: "-compile-module-from-interface" diff --git a/test/ModuleInterface/clang-args-transitive-availability.swift b/test/ModuleInterface/clang-args-transitive-availability.swift index dfc4df497cb38..61b5fa4c5d6ed 100644 --- a/test/ModuleInterface/clang-args-transitive-availability.swift +++ b/test/ModuleInterface/clang-args-transitive-availability.swift @@ -49,7 +49,8 @@ import ImportsMacroSpecificClangModule // CHECK-NEXT: ], // CHECK-NEXT: "directDependencies": [ // CHECK-NEXT: ], -// CHECK-NEXT: "details": { +// CHECK-NEXT: "linkLibraries": [ +// CHECK: "details": { // CHECK-NEXT: "clang": { // CHECK-NEXT: "moduleMapPath": "{{.*}}module.modulemap", // CHECK-NEXT: "contextHash": "{{.*}}", diff --git a/test/ModuleInterface/clang-session-transitive.swift b/test/ModuleInterface/clang-session-transitive.swift index 8bf1cd8314245..a1f2f27640aea 100644 --- a/test/ModuleInterface/clang-session-transitive.swift +++ b/test/ModuleInterface/clang-session-transitive.swift @@ -30,7 +30,8 @@ import TestModule // CHECK-NEXT: "swift": "SwiftOnoneSupport" // CHECK-NEXT: } // CHECK-NEXT: ], - // CHECK-NEXT: "details": { + // CHECK-NEXT: "linkLibraries": [ + // CHECK: "details": { // CHECK-NEXT: "swift": { // CHECK-NEXT: "moduleInterfacePath": // CHECK-NEXT: "compiledModuleCandidates": [ diff --git a/test/ModuleInterface/extension-transitive-availability.swift b/test/ModuleInterface/extension-transitive-availability.swift index a677fc4d6292c..201a74dafb6cf 100644 --- a/test/ModuleInterface/extension-transitive-availability.swift +++ b/test/ModuleInterface/extension-transitive-availability.swift @@ -31,7 +31,8 @@ func foo() { // CHECK-NEXT: "swift": "SwiftOnoneSupport" // CHECK-NEXT: } // CHECK-NEXT: ], -// CHECK-NEXT: "details": { +// CHECK-NEXT: "linkLibraries": [ +// CHECK: "details": { // CHECK-NEXT: "swift": { // CHECK-NEXT: "moduleInterfacePath": // CHECK-NEXT: "compiledModuleCandidates": [ diff --git a/test/ScanDependencies/Inputs/CHeaders/module.modulemap b/test/ScanDependencies/Inputs/CHeaders/module.modulemap index c02240190d4e8..fb4fdf315dc9c 100644 --- a/test/ScanDependencies/Inputs/CHeaders/module.modulemap +++ b/test/ScanDependencies/Inputs/CHeaders/module.modulemap @@ -11,6 +11,7 @@ module B { module C [system] { header "C.h" export * + link framework "nonSwiftyLibC" } module D { diff --git a/test/ScanDependencies/Inputs/Swift/E.swiftinterface b/test/ScanDependencies/Inputs/Swift/E.swiftinterface index 824fe883f6b8d..d1fb4b2cb0a5f 100644 --- a/test/ScanDependencies/Inputs/Swift/E.swiftinterface +++ b/test/ScanDependencies/Inputs/Swift/E.swiftinterface @@ -1,4 +1,4 @@ // swift-interface-format-version: 1.0 -// swift-module-flags: -module-name E +// swift-module-flags: -module-name E -autolink-force-load -module-link-name swiftyLibE import Swift -public func funcE() { } \ No newline at end of file +public func funcE() { } diff --git a/test/ScanDependencies/module_deps_cache_reuse.swift b/test/ScanDependencies/module_deps_cache_reuse.swift index 51718ede38662..e8f3ebaa92cf2 100644 --- a/test/ScanDependencies/module_deps_cache_reuse.swift +++ b/test/ScanDependencies/module_deps_cache_reuse.swift @@ -94,6 +94,8 @@ import SubE // CHECK-DAG: "swift": "Swift" // CHECK-DAG: "swift": "SwiftOnoneSupport" // CHECK: ], +// CHECK-NEXT: "linkLibraries": [ +// CHECK-NEXT: ], // CHECK-NEXT: "details": { // CHECK: "commandLine": [ diff --git a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift index 0afa3bab97918..f0d76411b46d0 100644 --- a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift +++ b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift @@ -27,6 +27,8 @@ import A // CHECK-INITIAL-SCAN-DAG: "swift": "Swift" // CHECK-INITIAL-SCAN-DAG: "swift": "SwiftOnoneSupport" // CHECK-INITIAL-SCAN: ], +// CHECK-INITIAL-SCAN-NEXT: "linkLibraries": [ +// CHECK-INITIAL-SCAN-NEXT: ], // CHECK-INITIAL-SCAN-NEXT: "details": { // CHECK-INITIAL-SCAN-NEXT: "swift": { // CHECK-INITIAL-SCAN-NEXT: "moduleInterfacePath": "{{.*}}/Swift/A.swiftinterface", @@ -39,6 +41,8 @@ import A // CHECK-DIFFERENT-DAG: "swift": "Swift" // CHECK-DIFFERENT-DAG: "swift": "SwiftOnoneSupport" // CHECK-DIFFERENT: ], +// CHECK-DIFFERENT-NEXT: "linkLibraries": [ +// CHECK-DIFFERENT-NEXT: ], // CHECK-DIFFERENT-NEXT: "details": { // CHECK-DIFFERENT-NEXT: "swift": { // CHECK-DIFFERENT-NEXT: "moduleInterfacePath": "{{.*}}/SwiftDifferent/A.swiftinterface", diff --git a/test/ScanDependencies/module_deps_link_libs.swift b/test/ScanDependencies/module_deps_link_libs.swift new file mode 100644 index 0000000000000..6b27388bc54cd --- /dev/null +++ b/test/ScanDependencies/module_deps_link_libs.swift @@ -0,0 +1,38 @@ +// RUN: %empty-directory(%t) +// REQUIRES: objc_interop + +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift +// Check the contents of the JSON output +// RUN: %validate-json %t/deps.json | %FileCheck %s + +import C +import E +import G +import SubE + +// CHECK: "mainModuleName": "deps" + +// CHECK: "linkLibraries": [ +// CHECK-DAG: "linkName": "objc", +// CHECK-NEXT: "isFramework": false, +// CHECK-NEXT: "shouldForceLoad": false + +// CHECK-DAG: "linkName": "swiftCompatibilityConcurrency", +// CHECK-NEXT: "isFramework": false, +// CHECK-NEXT: "shouldForceLoad": true + +// CHECK-DAG: "linkName": "swiftCompatibility56", +// CHECK-NEXT: "isFramework": false, +// CHECK-NEXT: "shouldForceLoad": true + +// CHECK-DAG: "linkName": "swiftCompatibilityPacks", +// CHECK-NEXT: "isFramework": false, +// CHECK-NEXT: "shouldForceLoad": false + +// CHECK-DAG: "linkName": "swiftyLibE", +// CHECK-NEXT: "isFramework": false, +// CHECK-NEXT: "shouldForceLoad": true + +// CHECK-DAG: "linkName": "nonSwiftyLibC", +// CHECK-NEXT: "isFramework": true, +// CHECK-NEXT: "shouldForceLoad": false diff --git a/tools/libSwiftScan/libSwiftScan.cpp b/tools/libSwiftScan/libSwiftScan.cpp index a334772ef6345..7575a2b6a14a1 100644 --- a/tools/libSwiftScan/libSwiftScan.cpp +++ b/tools/libSwiftScan/libSwiftScan.cpp @@ -93,11 +93,22 @@ void swiftscan_dependency_info_details_dispose( delete details_impl; } +void swiftscan_link_library_set_dispose(swiftscan_link_library_set_t *set) { + for (size_t i = 0; i < set->count; ++i) { + auto info = set->link_libraries[i]; + swiftscan_string_dispose(info->name); + delete info; + } + delete[] set->link_libraries; + delete set; +} + void swiftscan_dependency_info_dispose(swiftscan_dependency_info_t info) { swiftscan_string_dispose(info->module_name); swiftscan_string_dispose(info->module_path); swiftscan_string_set_dispose(info->source_files); swiftscan_string_set_dispose(info->direct_dependencies); + swiftscan_link_library_set_dispose(info->link_libraries); swiftscan_dependency_info_details_dispose(info->details); delete info; } @@ -260,11 +271,32 @@ swiftscan_string_set_t *swiftscan_module_info_get_direct_dependencies( return info->direct_dependencies; } + +swiftscan_link_library_set_t *swiftscan_module_info_get_link_libraries( + swiftscan_dependency_info_t info) { + return info->link_libraries; +} + swiftscan_module_details_t swiftscan_module_info_get_details(swiftscan_dependency_info_t info) { return info->details; } +//=== Link Library Info query APIs -----------------------------------===// + +swiftscan_string_ref_t +swiftscan_link_library_info_get_link_name(swiftscan_link_library_info_t info) { + return info->name; +} +bool +swiftscan_link_library_info_get_is_framework(swiftscan_link_library_info_t info) { + return info->isFramework; +} +bool +swiftscan_link_library_info_get_should_force_load(swiftscan_link_library_info_t info) { + return info->forceLoad; +} + //=== Swift Textual Module Details query APIs -----------------------------===// swiftscan_dependency_info_kind_t diff --git a/tools/libSwiftScan/libSwiftScan.exports b/tools/libSwiftScan/libSwiftScan.exports index 2232eb027a6c8..6d804a9a0632c 100644 --- a/tools/libSwiftScan/libSwiftScan.exports +++ b/tools/libSwiftScan/libSwiftScan.exports @@ -1,10 +1,14 @@ swiftscan_dependency_graph_get_main_module_name swiftscan_dependency_graph_get_dependencies swiftscan_dependency_graph_get_diagnostics +swiftscan_link_library_info_get_link_name +swiftscan_link_library_info_get_is_framework +swiftscan_link_library_info_get_should_force_load swiftscan_module_info_get_module_name swiftscan_module_info_get_module_path swiftscan_module_info_get_source_files swiftscan_module_info_get_direct_dependencies +swiftscan_module_info_get_link_libraries swiftscan_module_info_get_details swiftscan_module_detail_get_kind swiftscan_swift_textual_detail_get_module_interface_path