From e579ba994bf991fb328f64c7c956ecc945d2af94 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 11 May 2023 13:21:59 -0700 Subject: [PATCH 1/2] [Explicit Module Builds] Add 'ClangImporter' setting for explicitly-built modules This will mean that '-disable-implicit-swift-modules' also automatically implies two things: 1. Clang modules must also be explicit, and the importer's clang instance will get '-fno-implicit-modules' and '-fno-implicit-module-maps' 2. The importer's clang instance will no longer get a '-fmodules-cache-path=', since it is not needed in explicit builds --- include/swift/Basic/LangOptions.h | 4 ++++ include/swift/Frontend/FrontendOptions.h | 4 ++-- lib/ClangImporter/ClangImporter.cpp | 7 ++++++- lib/Frontend/CompilerInvocation.cpp | 3 +++ .../fail_implicit_concurrency_load.swift | 15 +++++++++++++++ test/Frontend/module-alias-explicit-build.swift | 16 +++++++++++++++- test/ScanDependencies/can_import_with_map.swift | 17 ++++++++++++++++- .../explicit-framework-irgen.swift | 14 ++++++++++++++ .../explicit-module-map-clang-and-swift.swift | 15 +++++++++++++++ 9 files changed, 90 insertions(+), 5 deletions(-) diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index eb134cc63433d..7724a92562b2f 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -879,6 +879,10 @@ namespace swift { /// and completely bypass the Clang driver. bool DirectClangCC1ModuleBuild = false; + /// Disable implicitly-built Clang modules because they are explicitly + /// built and provided to the compiler invocation. + bool DisableImplicitClangModules = false; + /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 0ae98619e8a95..a8cf1e3a670f2 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -313,8 +313,8 @@ class FrontendOptions { /// By default, we include ImplicitObjCHeaderPath directly. llvm::Optional BridgingHeaderDirForPrint; - /// Disable implicitly built Swift modules because they are explicitly - /// built and given to the compiler invocation. + /// Disable implicitly-built Swift modules because they are explicitly + /// built and provided to the compiler invocation. bool DisableImplicitModules = false; /// Disable building Swift modules from textual interfaces. This should be diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 112d8ebdef55d..94cfd774918f1 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -668,11 +668,16 @@ importer::getNormalInvocationArguments( } const std::string &moduleCachePath = importerOpts.ModuleCachePath; - if (!moduleCachePath.empty()) { + if (!moduleCachePath.empty() && !importerOpts.DisableImplicitClangModules) { invocationArgStrs.push_back("-fmodules-cache-path="); invocationArgStrs.back().append(moduleCachePath); } + if (importerOpts.DisableImplicitClangModules) { + invocationArgStrs.push_back("-fno-implicit-modules"); + invocationArgStrs.push_back("-fno-implicit-module-maps"); + } + if (ctx.SearchPathOpts.DisableModulesValidateSystemDependencies) { invocationArgStrs.push_back("-fno-modules-validate-system-headers"); } else { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index d7c90d26500e7..3deae5d98a021 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1472,6 +1472,9 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation); } + if (FrontendOpts.DisableImplicitModules) + Opts.DisableImplicitClangModules = true; + Opts.ValidateModulesOnce |= Args.hasArg(OPT_validate_clang_modules_once); if (auto *A = Args.getLastArg(OPT_clang_build_session_file)) Opts.BuildSessionFilePath = A->getValue(); diff --git a/test/Concurrency/fail_implicit_concurrency_load.swift b/test/Concurrency/fail_implicit_concurrency_load.swift index 1b3f99418e298..7b51f8c6969c6 100644 --- a/test/Concurrency/fail_implicit_concurrency_load.swift +++ b/test/Concurrency/fail_implicit_concurrency_load.swift @@ -1,9 +1,12 @@ // This test ensures that if implicit import of the Concurrency module is enabled, // but no such module can be located (here verified by forcing explicit modules), // a warning diagnostic is emitted. +// UNSUPPORTED: OS=windows-msvc // REQUIRES: concurrency // RUN: %empty-directory(%t) // RUN: mkdir -p %t/inputs +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm +// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm // RUN: echo "[{" > %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json @@ -11,6 +14,18 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json diff --git a/test/Frontend/module-alias-explicit-build.swift b/test/Frontend/module-alias-explicit-build.swift index fcfca550f1e59..eb2dedef5bd8a 100644 --- a/test/Frontend/module-alias-explicit-build.swift +++ b/test/Frontend/module-alias-explicit-build.swift @@ -1,5 +1,5 @@ /// Test the -module-alias flag with an explicit module loader. - +// UNSUPPORTED: OS=windows-msvc // RUN: %empty-directory(%t) // RUN: mkdir -p %t/inputs // RUN: mkdir -p %t/outputs @@ -7,6 +7,8 @@ /// Create a module Bar // RUN: echo 'public func bar() {}' > %t/inputs/FileBar.swift // RUN: %target-swift-frontend -module-name Bar %t/inputs/FileBar.swift -emit-module -emit-module-path %t/inputs/Bar.swiftmodule +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm +// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm /// Check Bar.swiftmodule is created // RUN: test -f %t/inputs/Bar.swiftmodule @@ -35,6 +37,18 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"_StringProcessing\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/string_processing_module\"," >> %/t/inputs/map.json // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json diff --git a/test/ScanDependencies/can_import_with_map.swift b/test/ScanDependencies/can_import_with_map.swift index 7f1a42b047800..992175768a763 100644 --- a/test/ScanDependencies/can_import_with_map.swift +++ b/test/ScanDependencies/can_import_with_map.swift @@ -1,8 +1,11 @@ +// UNSUPPORTED: OS=windows-msvc // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache // RUN: mkdir -p %t/inputs // RUN: echo "public func foo() {}" >> %t/foo.swift // RUN: %target-swift-frontend -emit-module -emit-module-path %t/inputs/Foo.swiftmodule -emit-module-doc-path %t/inputs/Foo.swiftdoc -emit-module-source-info -emit-module-source-info-path %t/inputs/Foo.swiftsourceinfo -module-cache-path %t.module-cache %t/foo.swift -module-name Foo +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm +// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm // RUN: echo "[{" > %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json @@ -32,12 +35,24 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Distributed\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/distributed_module\"," >> %/t/inputs/map.json // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json -// RUN: %target-swift-frontend -typecheck %s -explicit-swift-module-map-file %t/inputs/map.json -disable-implicit-swift-modules +// RUN: %target-swift-frontend -typecheck %s -explicit-swift-module-map-file %t/inputs/map.json -disable-implicit-swift-modules -disable-implicit-concurrency-module-import #if canImport(Foo) import Foo #endif diff --git a/test/ScanDependencies/explicit-framework-irgen.swift b/test/ScanDependencies/explicit-framework-irgen.swift index 3f62fb8fb0e06..dc77f3c8aaae4 100644 --- a/test/ScanDependencies/explicit-framework-irgen.swift +++ b/test/ScanDependencies/explicit-framework-irgen.swift @@ -4,6 +4,8 @@ // RUN: echo "/// Some cool comments" > %t/foo.swift // RUN: echo "public func foo() {}" >> %t/foo.swift // RUN: %target-swift-frontend -emit-module -emit-module-path %t/inputs/Foo.swiftmodule -emit-module-doc-path %t/inputs/Foo.swiftdoc -emit-module-source-info -emit-module-source-info-path %t/inputs/Foo.swiftsourceinfo -module-cache-path %t.module-cache %t/foo.swift -module-name Foo +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm +// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm // RUN: echo "[{" > %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Foo\"," >> %/t/inputs/map.json @@ -33,6 +35,18 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"Distributed\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/distributed_module\"," >> %/t/inputs/map.json // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json diff --git a/test/ScanDependencies/explicit-module-map-clang-and-swift.swift b/test/ScanDependencies/explicit-module-map-clang-and-swift.swift index 061a8c0306789..4adf2dd7fddf9 100644 --- a/test/ScanDependencies/explicit-module-map-clang-and-swift.swift +++ b/test/ScanDependencies/explicit-module-map-clang-and-swift.swift @@ -1,9 +1,12 @@ +// UNSUPPORTED: OS=windows-msvc // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache // RUN: mkdir -p %t/inputs // RUN: echo "public func anotherFuncA() {}" > %t/A.swift // RUN: %target-swift-frontend -emit-module -emit-module-path %t/inputs/A.swiftmodule -emit-module-doc-path %t/inputs/A.swiftdoc -emit-module-source-info -emit-module-source-info-path %t/inputs/A.swiftsourceinfo -import-underlying-module -I%S/Inputs/CHeaders -module-cache-path %t.module-cache %t/A.swift -module-name A // RUN: %target-swift-emit-pcm -module-name A -o %t/inputs/A.pcm %S/Inputs/CHeaders/module.modulemap +// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm +// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift_obj_root/lib/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm // RUN: echo "[{" > %/t/inputs/map.json // RUN: echo "\"moduleName\": \"A\"," >> %/t/inputs/map.json @@ -33,6 +36,18 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}," >> %/t/inputs/map.json // RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json +// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json +// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json +// RUN: echo "\"clangModuleMapPath\": \"%swift_obj_root/lib/swift/shims/module.modulemap\"," >> %/t/inputs/map.json +// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json +// RUN: echo "}," >> %/t/inputs/map.json +// RUN: echo "{" >> %/t/inputs/map.json // RUN: echo "\"moduleName\": \"_StringProcessing\"," >> %/t/inputs/map.json // RUN: echo "\"modulePath\": \"%/string_processing_module\"," >> %/t/inputs/map.json // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json From 112d6c4e3e39c4bb6eb7bc1cfa6deebbc971a07e Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Fri, 19 May 2023 12:02:14 -0700 Subject: [PATCH 2/2] [Dependency Scanning] Break out Swift overlay dependencies into separate output category Instead of being a part of 'directDependencies' on a module dependency info, make them a separate array of dependency IDs for Swift Source and Textual modules. This will allow clients to still distinguish direct module dependencies imported from a given module, versus dependencies added because direct/transitive Clang module dependencies have Swift overlays. This change does *not* remove overlay dependencies from 'directDependencies' yet, just adds them as a separate field on the module details info. A followup change will remove overlay and bridging header dependencies from 'directDependencies' once the clients have had a chance to adopt to this change. --- .../swift-c/DependencyScan/DependencyScan.h | 4 + include/swift/AST/ModuleDependencies.h | 27 ++- .../swift/DependencyScan/DependencyScanImpl.h | 4 + .../SerializedModuleDependencyCacheFormat.h | 8 +- include/swift/Option/Options.td | 4 + lib/AST/ModuleDependencies.cpp | 12 +- .../ModuleDependencyCacheSerialization.cpp | 194 ++++++++++-------- lib/DependencyScan/ScanDependencies.cpp | 126 ++++++++---- .../Inputs/ModuleDependencyGraph.swift | 12 +- .../module_deps_swift_overlay.swift | 20 ++ tools/libSwiftScan/libSwiftScan.cpp | 5 + tools/libSwiftScan/libSwiftScan.exports | 1 + 12 files changed, 277 insertions(+), 140 deletions(-) create mode 100644 test/ScanDependencies/module_deps_swift_overlay.swift diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index 4de2a6ea95104..c08a6fb7482c3 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -150,6 +150,10 @@ swiftscan_swift_textual_detail_get_context_hash( SWIFTSCAN_PUBLIC bool swiftscan_swift_textual_detail_get_is_framework( swiftscan_module_details_t details); +SWIFTSCAN_PUBLIC swiftscan_string_set_t * +swiftscan_swift_textual_detail_get_swift_overlay_dependencies( + swiftscan_module_details_t details); + //=== Swift Binary Module Details query APIs ------------------------------===// SWIFTSCAN_PUBLIC swiftscan_string_ref_t diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index e7584b8eca7ef..8fb3c39faa1da 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -137,6 +137,10 @@ struct CommonSwiftTextualModuleDependencyDetails { /// (Clang) modules on which the bridging header depends. std::vector bridgingModuleDependencies; + + /// Dependencies comprised of Swift overlay modules of direct and + /// transitive Clang dependencies. + std::vector swiftOverlayDependencies; }; /// Describes the dependencies of a Swift module described by an Swift interface file. @@ -450,12 +454,26 @@ class ModuleDependencyInfo { } /// Resolve a dependency's set of `imports` with qualified Module IDs - void resolveDependencies(const std::vector &dependencyIDs) { + void resolveDependencies(const ArrayRef dependencyIDs) { assert(!storage->resolved && "Resolving an already-resolved dependency"); storage->resolved = true; storage->resolvedModuleDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); } + /// Set this module's set of Swift Overlay dependencies + void setOverlayDependencies(const ArrayRef dependencyIDs) { + assert(isSwiftSourceModule() || isSwiftInterfaceModule()); + CommonSwiftTextualModuleDependencyDetails *textualModuleDetails; + if (auto sourceDetailsStorage = dyn_cast(storage.get())) { + textualModuleDetails = &sourceDetailsStorage->textualModuleDetails; + } else if (auto interfaceDetailsStorage = dyn_cast(storage.get())) { + textualModuleDetails = &interfaceDetailsStorage->textualModuleDetails; + } else { + llvm_unreachable("Unknown kind of dependency module info."); + } + textualModuleDetails->swiftOverlayDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); + } + void updateCommandLine(const std::vector &newCommandLine) { assert(isSwiftInterfaceModule() && "Can only update command line on Swift interface dependency"); cast(storage.get())->updateCommandLine(newCommandLine); @@ -773,7 +791,12 @@ class ModuleDependenciesCache { /// Resolve a dependency module's set of imports /// to a kind-qualified set of module IDs. void resolveDependencyImports(ModuleDependencyID moduleID, - const std::vector &dependencyIDs); + const ArrayRef dependencyIDs); + + /// Resolve a dependency module's set of Swift module dependencies + /// that are Swift overlays of Clang module dependencies. + void setSwiftOverlayDependencues(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs); StringRef getMainModuleName() const { return mainScanModuleName; diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index 2f9046a09d80f..dd0463e502e44 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -79,6 +79,10 @@ typedef struct { /// (Clang) modules on which the bridging header depends. swiftscan_string_set_t *bridging_module_dependencies; + /// (Swift) module dependencies by means of being overlays of + /// Clang module dependencies + swiftscan_string_set_t *swift_overlay_module_dependencies; + /// Options to the compile command required to build this module interface swiftscan_string_set_t *command_line; diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index a8fa5a316140b..f68f5222d253f 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -38,7 +38,7 @@ using llvm::BCVBR; const unsigned char MODULE_DEPENDENCY_CACHE_FORMAT_SIGNATURE[] = {'I', 'M', 'D','C'}; const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR = 4; /// Increment this on every change. -const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 0; +const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 1; /// Various identifiers in this format will rely on having their strings mapped /// using this ID. @@ -136,7 +136,8 @@ using SwiftInterfaceModuleDetailsLayout = FileIDField, // bridgingHeaderFile FileIDArrayIDField, // sourceFiles FileIDArrayIDField, // bridgingSourceFiles - FileIDArrayIDField // bridgingModuleDependencies + FileIDArrayIDField, // bridgingModuleDependencies + DependencyIDArrayIDField // swiftOverlayDependencies >; using SwiftSourceModuleDetailsLayout = @@ -145,7 +146,8 @@ using SwiftSourceModuleDetailsLayout = FileIDField, // bridgingHeaderFile FileIDArrayIDField, // sourceFiles FileIDArrayIDField, // bridgingSourceFiles - FileIDArrayIDField // bridgingModuleDependencies + FileIDArrayIDField, // bridgingModuleDependencies + DependencyIDArrayIDField // swiftOverlayDependencies >; using SwiftBinaryModuleDetailsLayout = diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index f8b9ed474bfea..dcaeec6876b06 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1272,6 +1272,10 @@ def disable_clang_target : Flag<["-"], "disable-clang-target">, Flags<[NewDriverOnlyOption]>, HelpText<"Disable a separately specified target triple for Clang instance to use">; +def explain_module_dependency : Separate<["-"], "explain-module-dependency">, + Flags<[NewDriverOnlyOption]>, + HelpText<"Emit remark/notes describing why compilaiton may depend on a module with a given name.">; + def min_inlining_target_version : Separate<["-"], "target-min-inlining-version">, Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>, HelpText<"Require inlinable code with no '@available' attribute to back-deploy " diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 55485c38320e3..a9f5435d05d34 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -447,7 +447,7 @@ void ModuleDependenciesCache::updateDependency( } void ModuleDependenciesCache::resolveDependencyImports(ModuleDependencyID moduleID, - const std::vector &dependencyIDs) { + const ArrayRef dependencyIDs) { auto optionalDependencyInfo = findDependency(moduleID.first, moduleID.second); assert(optionalDependencyInfo.has_value() && "Resolving unknown dependency"); // Copy the existing info to a mutable one we can then replace it with, after resolving its dependencies. @@ -455,3 +455,13 @@ void ModuleDependenciesCache::resolveDependencyImports(ModuleDependencyID module dependencyInfo.resolveDependencies(dependencyIDs); updateDependency(moduleID, dependencyInfo); } + +void ModuleDependenciesCache::setSwiftOverlayDependencues(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs) { + auto optionalDependencyInfo = findDependency(moduleID.first, moduleID.second); + assert(optionalDependencyInfo.has_value() && "Resolving unknown dependency"); + // Copy the existing info to a mutable one we can then replace it with, after setting its overlay dependencies. + auto dependencyInfo = *(optionalDependencyInfo.value()); + dependencyInfo.setOverlayDependencies(dependencyIDs); + updateDependency(moduleID, dependencyInfo); +} diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index e69b3ae5f2462..ca0bec3958962 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -237,12 +237,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi unsigned outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID; + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID; SwiftInterfaceModuleDetailsLayout::readRecord( Scratch, outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID); + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID); auto outputModulePath = getIdentifier(outputPathFileID); if (!outputModulePath) @@ -319,6 +321,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi for (const auto &mod : *bridgingModuleDeps) moduleDep.addBridgingModuleDependency(mod, alreadyAdded); + // Add Swift overlay dependencies + auto overlayModuleDependencyIDs = getModuleDependencyIDArray(overlayDependencyIDArrayID); + if (!overlayModuleDependencyIDs.has_value()) + llvm::report_fatal_error("Bad overlay dependencies: no qualified dependencies"); + moduleDep.setOverlayDependencies(overlayModuleDependencyIDs.value()); + cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); hasCurrentModule = false; @@ -335,11 +343,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi "Unexpected context hash on MODULE_NODE corresponding to a " "SWIFT_SOURCE_MODULE_DETAILS_NODE record"); unsigned extraPCMArgsArrayID, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID; + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID; SwiftSourceModuleDetailsLayout::readRecord( Scratch, extraPCMArgsArrayID, bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, - bridgingModuleDependenciesArrayID); + bridgingModuleDependenciesArrayID, overlayDependencyIDArrayID); auto extraPCMArgs = getStringArray(extraPCMArgsArrayID); if (!extraPCMArgs) @@ -386,6 +395,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi for (const auto &mod : *bridgingModuleDeps) moduleDep.addBridgingModuleDependency(mod, alreadyAdded); + // Add Swift overlay dependencies + auto overlayModuleDependencyIDs = getModuleDependencyIDArray(overlayDependencyIDArrayID); + if (!overlayModuleDependencyIDs.has_value()) + llvm::report_fatal_error("Bad overlay dependencies: no qualified dependencies"); + moduleDep.setOverlayDependencies(overlayModuleDependencyIDs.value()); + cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); hasCurrentModule = false; @@ -630,6 +645,7 @@ enum ModuleIdentifierArrayKind : uint8_t { SourceFiles, BridgingSourceFiles, BridgingModuleDependencies, + SwiftOverlayDependencyIDs, NonPathCommandLine, FileDependencies, CapturedPCMArgs, @@ -845,7 +861,8 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(ModuleDependencyID modul bridgingHeaderFileId, getArrayID(moduleID, ModuleIdentifierArrayKind::SourceFiles), getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles), - getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies)); + getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies), + getArrayID(moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs)); break; } case swift::ModuleDependencyKind::SwiftSource: { @@ -864,7 +881,8 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(ModuleDependencyID modul bridgingHeaderFileId, getArrayID(moduleID, ModuleIdentifierArrayKind::SourceFiles), getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles), - getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies)); + getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies), + getArrayID(moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs)); break; } case swift::ModuleDependencyKind::SwiftBinary: { @@ -995,9 +1013,8 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( for (auto &contextHash : cache.getAllContextHashes()) { addIdentifier(contextHash); for (auto &moduleID : cache.getAllModules(contextHash)) { - auto optionalDependencyInfo = cache.findDependency(moduleID.first, - moduleID.second, - contextHash); + auto optionalDependencyInfo = + cache.findDependency(moduleID.first, moduleID.second, contextHash); assert(optionalDependencyInfo.has_value() && "Expected dependency info."); auto dependencyInfo = optionalDependencyInfo.value(); // Add the module's name @@ -1005,83 +1022,94 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( // Add the module's dependencies addStringArray(moduleID, ModuleIdentifierArrayKind::DependencyImports, dependencyInfo->getModuleImports()); - addDependencyIDArray(moduleID, ModuleIdentifierArrayKind::QualifiedModuleDependencyIDs, - dependencyInfo->getModuleDependencies()); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::QualifiedModuleDependencyIDs, + dependencyInfo->getModuleDependencies()); // Add the dependency-kind-specific data switch (dependencyInfo->getKind()) { - case swift::ModuleDependencyKind::SwiftInterface: { - auto swiftTextDeps = dependencyInfo->getAsSwiftInterfaceModule(); - assert(swiftTextDeps); - addIdentifier(swiftTextDeps->moduleOutputPath); - addIdentifier(swiftTextDeps->swiftInterfaceFile); - addStringArray(moduleID, - ModuleIdentifierArrayKind::CompiledModuleCandidates, - swiftTextDeps->compiledModuleCandidates); - addStringArray(moduleID, ModuleIdentifierArrayKind::BuildCommandLine, - swiftTextDeps->buildCommandLine); - addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, - swiftTextDeps->textualModuleDetails.extraPCMArgs); - addIdentifier(swiftTextDeps->contextHash); - if (swiftTextDeps->textualModuleDetails.bridgingHeaderFile.has_value()) - addIdentifier(swiftTextDeps->textualModuleDetails.bridgingHeaderFile - .value()); - addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, - std::vector()); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, - swiftTextDeps->textualModuleDetails.bridgingSourceFiles); - addStringArray( - moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, - swiftTextDeps->textualModuleDetails.bridgingModuleDependencies); - break; - } - case swift::ModuleDependencyKind::SwiftBinary: { - auto swiftBinDeps = dependencyInfo->getAsSwiftBinaryModule(); - assert(swiftBinDeps); - addIdentifier(swiftBinDeps->compiledModulePath); - addIdentifier(swiftBinDeps->moduleDocPath); - addIdentifier(swiftBinDeps->sourceInfoPath); - break; - } - case swift::ModuleDependencyKind::SwiftPlaceholder: { - auto swiftPHDeps = dependencyInfo->getAsPlaceholderDependencyModule(); - assert(swiftPHDeps); - addIdentifier(swiftPHDeps->compiledModulePath); - addIdentifier(swiftPHDeps->moduleDocPath); - addIdentifier(swiftPHDeps->sourceInfoPath); - break; - } - case swift::ModuleDependencyKind::SwiftSource: { - auto swiftSourceDeps = dependencyInfo->getAsSwiftSourceModule(); - assert(swiftSourceDeps); - addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, - swiftSourceDeps->textualModuleDetails.extraPCMArgs); - if (swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.has_value()) - addIdentifier(swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value()); - addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, - swiftSourceDeps->sourceFiles); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, - swiftSourceDeps->textualModuleDetails.bridgingSourceFiles); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, - swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies); - break; - } - case swift::ModuleDependencyKind::Clang: { - auto clangDeps = dependencyInfo->getAsClangModule(); - assert(clangDeps); - addIdentifier(clangDeps->pcmOutputPath); - addIdentifier(clangDeps->moduleMapFile); - addIdentifier(clangDeps->contextHash); - addStringArray(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine, - clangDeps->nonPathCommandLine); - addStringArray(moduleID, ModuleIdentifierArrayKind::FileDependencies, - clangDeps->fileDependencies); - addStringArray(moduleID, ModuleIdentifierArrayKind::CapturedPCMArgs, - clangDeps->capturedPCMArgs); - break; - } - default: - llvm_unreachable("Unhandled dependency kind."); + case swift::ModuleDependencyKind::SwiftInterface: { + auto swiftTextDeps = dependencyInfo->getAsSwiftInterfaceModule(); + assert(swiftTextDeps); + addIdentifier(swiftTextDeps->moduleOutputPath); + addIdentifier(swiftTextDeps->swiftInterfaceFile); + addStringArray(moduleID, + ModuleIdentifierArrayKind::CompiledModuleCandidates, + swiftTextDeps->compiledModuleCandidates); + addStringArray(moduleID, ModuleIdentifierArrayKind::BuildCommandLine, + swiftTextDeps->buildCommandLine); + addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, + swiftTextDeps->textualModuleDetails.extraPCMArgs); + addIdentifier(swiftTextDeps->contextHash); + if (swiftTextDeps->textualModuleDetails.bridgingHeaderFile.has_value()) + addIdentifier( + swiftTextDeps->textualModuleDetails.bridgingHeaderFile.value()); + addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, + std::vector()); + addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, + swiftTextDeps->textualModuleDetails.bridgingSourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, + swiftTextDeps->textualModuleDetails.bridgingModuleDependencies); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs, + swiftTextDeps->textualModuleDetails.swiftOverlayDependencies); + break; + } + case swift::ModuleDependencyKind::SwiftBinary: { + auto swiftBinDeps = dependencyInfo->getAsSwiftBinaryModule(); + assert(swiftBinDeps); + addIdentifier(swiftBinDeps->compiledModulePath); + addIdentifier(swiftBinDeps->moduleDocPath); + addIdentifier(swiftBinDeps->sourceInfoPath); + break; + } + case swift::ModuleDependencyKind::SwiftPlaceholder: { + auto swiftPHDeps = dependencyInfo->getAsPlaceholderDependencyModule(); + assert(swiftPHDeps); + addIdentifier(swiftPHDeps->compiledModulePath); + addIdentifier(swiftPHDeps->moduleDocPath); + addIdentifier(swiftPHDeps->sourceInfoPath); + break; + } + case swift::ModuleDependencyKind::SwiftSource: { + auto swiftSourceDeps = dependencyInfo->getAsSwiftSourceModule(); + assert(swiftSourceDeps); + addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, + swiftSourceDeps->textualModuleDetails.extraPCMArgs); + if (swiftSourceDeps->textualModuleDetails.bridgingHeaderFile + .has_value()) + addIdentifier( + swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value()); + addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, + swiftSourceDeps->sourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, + swiftSourceDeps->textualModuleDetails.bridgingSourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, + swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs, + swiftSourceDeps->textualModuleDetails.swiftOverlayDependencies); + break; + } + case swift::ModuleDependencyKind::Clang: { + auto clangDeps = dependencyInfo->getAsClangModule(); + assert(clangDeps); + addIdentifier(clangDeps->pcmOutputPath); + addIdentifier(clangDeps->moduleMapFile); + addIdentifier(clangDeps->contextHash); + addStringArray(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine, + clangDeps->nonPathCommandLine); + addStringArray(moduleID, ModuleIdentifierArrayKind::FileDependencies, + clangDeps->fileDependencies); + addStringArray(moduleID, ModuleIdentifierArrayKind::CapturedPCMArgs, + clangDeps->capturedPCMArgs); + break; + } + default: + llvm_unreachable("Unhandled dependency kind."); } } } diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 45e1402693901..f89d8c1f87245 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -303,7 +303,7 @@ resolveExplicitModuleInputs(ModuleDependencyID moduleID, } /// Resolve the direct dependencies of the given module. -static ArrayRef +static std::vector resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleID, ModuleDependenciesCache &cache, InterfaceSubContextDelegate &ASTDelegate) { @@ -323,7 +323,8 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI auto isSwift = isSwiftInterfaceOrSource || knownDependencies->isSwiftBinaryModule(); // Find the dependencies of every module this module directly depends on. - ModuleDependencyIDSetVector result; + ModuleDependencyIDSetVector directDependencies; + ModuleDependencyIDSetVector swiftOverlayDependencies; for (auto dependsOn : knownDependencies->getModuleImports()) { // Figure out what kind of module we need. bool onlyClangModule = !isSwift || moduleID.first == dependsOn; @@ -332,14 +333,14 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI if (onlyClangModule) { if (auto found = ctx.getClangModuleDependencies(dependsOn, cache, ASTDelegate)) - result.insert({dependsOn, ModuleDependencyKind::Clang}); + directDependencies.insert({dependsOn, ModuleDependencyKind::Clang}); } else { if (auto found = ctx.getModuleDependencies(dependsOn, cache, ASTDelegate, /* optionalDependencyLookup */ false, isTestable, moduleID)) - result.insert({dependsOn, found.value()->getKind()}); + directDependencies.insert({dependsOn, found.value()->getKind()}); } } @@ -352,7 +353,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI /* optionalDependencyLookup */ true, /* isTestableDependency */ false, moduleID)) - result.insert({optionallyDependsOn, found.value()->getKind()}); + directDependencies.insert({optionallyDependsOn, found.value()->getKind()}); } if (isSwiftInterfaceOrSource) { @@ -382,7 +383,9 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI assert(bridgingModuleDependencies); for (const auto &clangDep : *bridgingModuleDependencies) { - result.insert({clangDep, ModuleDependencyKind::Clang}); + /// TODO: separate this out of here as well into a separate entry in + /// `CommonSwiftTextualModuleDependencyDetails` + directDependencies.insert({clangDep, ModuleDependencyKind::Clang}); findAllImportedClangModules(ctx, clangDep, cache, allClangModules, knownModules); } @@ -390,7 +393,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI } // Find all of the Clang modules this Swift module depends on. - for (const auto &dep : result) { + for (const auto &dep : directDependencies) { if (dep.second != ModuleDependencyKind::Clang) continue; @@ -403,15 +406,26 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI for (const auto &clangDep : allClangModules) { if (auto found = ctx.getSwiftModuleDependencies(clangDep, cache, ASTDelegate)) { - if (clangDep != moduleID.first) - result.insert({clangDep, found.value()->getKind()}); + if (clangDep != moduleID.first) { + swiftOverlayDependencies.insert({clangDep, found.value()->getKind()}); + // FIXME: Once all clients know to fetch these dependencies from + // `swiftOverlayDependencies`, the goal is to no longer have them in + // `directDependencies` so the following will need to go away. + directDependencies.insert({clangDep, found.value()->getKind()}); + } } } } // Resolve the dependnecy info - cache.resolveDependencyImports(moduleID, result.takeVector()); - return cache.findDependency(moduleID.first, moduleID.second).value()->getModuleDependencies(); + cache.resolveDependencyImports(moduleID, directDependencies.getArrayRef()); + // Resolve swift Overlay dependencies + if (!swiftOverlayDependencies.empty()) + cache.setSwiftOverlayDependencues(moduleID, swiftOverlayDependencies.getArrayRef()); + + ModuleDependencyIDSetVector result = directDependencies; + result.insert(swiftOverlayDependencies.begin(), swiftOverlayDependencies.end()); + return result.takeVector(); } static void discoverCrossImportOverlayDependencies( @@ -662,11 +676,12 @@ void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName, out << "\n"; } -void writeDirectDependencies(llvm::raw_ostream &out, - const swiftscan_string_set_t *dependencies, - unsigned indentLevel, bool trailingComma) { +void writeDependencies(llvm::raw_ostream &out, + const swiftscan_string_set_t *dependencies, + std::string dependenciesKind, + unsigned indentLevel, bool trailingComma) { out.indent(indentLevel * 2); - out << "\"directDependencies\": "; + out << "\"" + dependenciesKind + "\": "; out << "[\n"; for (size_t i = 0; i < dependencies->count; ++i) { @@ -780,8 +795,9 @@ static void writeJSON(llvm::raw_ostream &out, // Direct dependencies. if (swiftTextualDeps || swiftBinaryDeps || clangDeps) - writeDirectDependencies(out, directDependencies, 3, - /*trailingComma=*/true); + writeDependencies(out, directDependencies, + "directDependencies", 3, + /*trailingComma=*/true); // Swift and Clang-specific details. out.indent(3 * 2); out << "\"details\": {\n"; @@ -833,6 +849,9 @@ static void writeJSON(llvm::raw_ostream &out, bool hasBridgingHeaderPath = swiftTextualDeps->bridging_header_path.data && get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0'; + bool hasOverlayDependencies = + swiftTextualDeps->swift_overlay_module_dependencies && + swiftTextualDeps->swift_overlay_module_dependencies->count > 0; bool commaAfterFramework = swiftTextualDeps->extra_pcm_args->count != 0 || hasBridgingHeaderPath; @@ -868,7 +887,12 @@ static void writeJSON(llvm::raw_ostream &out, swiftTextualDeps->bridging_module_dependencies, 6, /*trailingComma=*/false); out.indent(5 * 2); - out << "}\n"; + out << (hasOverlayDependencies ? "},\n" : "}\n"); + } + if (hasOverlayDependencies) { + writeDependencies(out, swiftTextualDeps->swift_overlay_module_dependencies, + "swiftOverlayDependencies", 5, + /*trailingComma=*/true); } } else if (swiftPlaceholderDeps) { out << "\"swiftPlaceholder\": {\n"; @@ -950,6 +974,33 @@ static void writeJSON(llvm::raw_ostream &out, } } +static void bridgeDependencyIDs(const ArrayRef dependencies, + std::vector &bridgedDependencyNames) { + for (const auto &dep : dependencies) { + std::string dependencyKindAndName; + switch (dep.second) { + case ModuleDependencyKind::SwiftInterface: + case ModuleDependencyKind::SwiftSource: + dependencyKindAndName = "swiftTextual"; + break; + case ModuleDependencyKind::SwiftBinary: + dependencyKindAndName = "swiftBinary"; + break; + case ModuleDependencyKind::SwiftPlaceholder: + dependencyKindAndName = "swiftPlaceholder"; + break; + case ModuleDependencyKind::Clang: + dependencyKindAndName = "clang"; + break; + default: + llvm_unreachable("Unhandled dependency kind."); + } + dependencyKindAndName += ":"; + dependencyKindAndName += dep.first; + bridgedDependencyNames.push_back(dependencyKindAndName); + } +} + static swiftscan_dependency_graph_t generateFullDependencyGraph(CompilerInstance &instance, ModuleDependenciesCache &cache, @@ -1021,8 +1072,11 @@ generateFullDependencyGraph(CompilerInstance &instance, ? create_clone( swiftTextualDeps->textualModuleDetails.bridgingHeaderFile.value().c_str()) : create_null(); - details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL; + // Create an overlay dependencies set according to the output format + std::vector bridgedOverlayDependencyNames; + bridgeDependencyIDs(swiftTextualDeps->textualModuleDetails.swiftOverlayDependencies, + bridgedOverlayDependencyNames); details->swift_textual_details = { moduleInterfacePath, @@ -1030,6 +1084,7 @@ generateFullDependencyGraph(CompilerInstance &instance, bridgingHeaderPath, create_set(swiftTextualDeps->textualModuleDetails.bridgingSourceFiles), create_set(swiftTextualDeps->textualModuleDetails.bridgingModuleDependencies), + create_set(bridgedOverlayDependencyNames), create_set(swiftTextualDeps->buildCommandLine), create_set(swiftTextualDeps->textualModuleDetails.extraPCMArgs), create_clone(swiftTextualDeps->contextHash.c_str()), @@ -1041,15 +1096,19 @@ generateFullDependencyGraph(CompilerInstance &instance, ? create_clone( swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value().c_str()) : create_null(); - // TODO: Once the clients are taught about the new dependency kind, - // switch to using a bespoke kind here. details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL; + // Create an overlay dependencies set according to the output format + std::vector bridgedOverlayDependencyNames; + bridgeDependencyIDs(swiftSourceDeps->textualModuleDetails.swiftOverlayDependencies, + bridgedOverlayDependencyNames); + details->swift_textual_details = { moduleInterfacePath, create_empty_set(), bridgingHeaderPath, create_set(swiftSourceDeps->textualModuleDetails.bridgingSourceFiles), create_set(swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies), + create_set(bridgedOverlayDependencyNames), create_empty_set(), create_set(swiftSourceDeps->textualModuleDetails.extraPCMArgs), /*contextHash*/create_null(), @@ -1091,30 +1150,7 @@ generateFullDependencyGraph(CompilerInstance &instance, // Create a direct dependencies set according to the output format std::vector bridgedDependencyNames; - for (const auto &dep : directDependencies) { - std::string dependencyKindAndName; - switch (dep.second) { - case ModuleDependencyKind::SwiftInterface: - case ModuleDependencyKind::SwiftSource: - dependencyKindAndName = "swiftTextual"; - break; - case ModuleDependencyKind::SwiftBinary: - dependencyKindAndName = "swiftBinary"; - break; - case ModuleDependencyKind::SwiftPlaceholder: - dependencyKindAndName = "swiftPlaceholder"; - break; - case ModuleDependencyKind::Clang: - dependencyKindAndName = "clang"; - break; - default: - llvm_unreachable("Unhandled dependency kind."); - } - dependencyKindAndName += ":"; - dependencyKindAndName += dep.first; - bridgedDependencyNames.push_back(dependencyKindAndName); - } - + bridgeDependencyIDs(directDependencies, bridgedDependencyNames); moduleInfo->direct_dependencies = create_set(bridgedDependencyNames); moduleInfo->details = getModuleDetails(); } diff --git a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift index 4ac30644f59e8..faf8912f7507b 100644 --- a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift +++ b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift @@ -86,12 +86,6 @@ struct SwiftModuleDetails: Codable { /// The paths of potentially ready-to-use compiled modules for the interface. var compiledModuleCandidates: [String]? - /// The bridging header, if any. - var bridgingHeaderPath: String? - - /// The source files referenced by the bridging header. - var bridgingSourceFiles: [String]? = [] - /// Options to the compile command var commandLine: [String]? = [] @@ -102,6 +96,12 @@ struct SwiftModuleDetails: Codable { /// A flag to indicate whether or not this module is a framework. var isFramework: Bool + + /// The bridging header info, if any. + var bridgingHeader: BridgingHeader? + + /// A set of Swift Overlays of Clang Module Dependencies + var swiftOverlayDependencies: [ModuleDependencyId]? } /// Details specific to Swift placeholder dependencies. diff --git a/test/ScanDependencies/module_deps_swift_overlay.swift b/test/ScanDependencies/module_deps_swift_overlay.swift new file mode 100644 index 0000000000000..dc80bf07c7fbd --- /dev/null +++ b/test/ScanDependencies/module_deps_swift_overlay.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// 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 -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json + +// Ensure that round-trip serialization does not affect result +// RUN: %target-swift-frontend -scan-dependencies -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %FileCheck %s < %t/deps.json + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +import E + +// CHECK: "swiftOverlayDependencies": [ +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "F" +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/tools/libSwiftScan/libSwiftScan.cpp b/tools/libSwiftScan/libSwiftScan.cpp index c8bc786fd9085..23c5b697ef26c 100644 --- a/tools/libSwiftScan/libSwiftScan.cpp +++ b/tools/libSwiftScan/libSwiftScan.cpp @@ -291,6 +291,11 @@ bool swiftscan_swift_textual_detail_get_is_framework( return details->swift_textual_details.is_framework; } +swiftscan_string_set_t *swiftscan_swift_textual_detail_get_swift_overlay_dependencies( + swiftscan_module_details_t details) { + return details->swift_textual_details.swift_overlay_module_dependencies; +} + //=== Swift Binary Module Details query APIs ------------------------------===// swiftscan_string_ref_t swiftscan_swift_binary_detail_get_compiled_module_path( diff --git a/tools/libSwiftScan/libSwiftScan.exports b/tools/libSwiftScan/libSwiftScan.exports index abfcc6c820607..4b940c96ea5f2 100644 --- a/tools/libSwiftScan/libSwiftScan.exports +++ b/tools/libSwiftScan/libSwiftScan.exports @@ -15,6 +15,7 @@ swiftscan_swift_textual_detail_get_command_line swiftscan_swift_textual_detail_get_extra_pcm_args swiftscan_swift_textual_detail_get_context_hash swiftscan_swift_textual_detail_get_is_framework +swiftscan_swift_textual_detail_get_swift_overlay_dependencies swiftscan_swift_binary_detail_get_compiled_module_path swiftscan_swift_binary_detail_get_module_doc_path swiftscan_swift_binary_detail_get_module_source_info_path