diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 818e08400b8..e2960afc78b 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -969,6 +969,10 @@ namespace swift { /// Using ClangIncludeTreeRoot for compilation. bool HasClangIncludeTreeRoot = false; + /// Whether the dependency scanner should construct all swift-frontend + /// invocations directly from clang cc1 args. + bool ClangImporterDirectCC1Scan = 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/Option/Options.td b/include/swift/Option/Options.td index 14b5be52e24..2f0a2d05aa8 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1894,6 +1894,11 @@ def gcc_toolchain: Separate<["-"], "gcc-toolchain">, MetaVarName<"">, HelpText<"Specify a directory where the clang importer and clang linker can find headers and libraries">; +def experimental_clang_importer_direct_cc1_scan: + Flag<["-"], "experimental-clang-importer-direct-cc1-scan">, + Flags<[FrontendOption, NewDriverOnlyOption, HelpHidden]>, + HelpText<"Enables swift driver to construct swift-frontend invocations using -direct-clang-cc1-module-build">; + def cache_compile_job: Flag<["-"], "cache-compile-job">, Flags<[FrontendOption, NewDriverOnlyOption]>, HelpText<"Enable compiler caching">; diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 8a59384c14b..f320ed46c3f 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -347,6 +347,8 @@ ModuleDependencyScanner::getMainModuleDependencyInfo( std::string rootID; std::vector buildArgs; + auto clangImporter = + static_cast(ScanASTContext.getClangModuleLoader()); if (tracker) { tracker->startTracking(); for (auto fileUnit : mainModule->getFiles()) { @@ -359,8 +361,6 @@ ModuleDependencyScanner::getMainModuleDependencyInfo( ScanCompilerInvocation.getSearchPathOptions()); // Fetch some dependency files from clang importer. std::vector clangDependencyFiles; - auto clangImporter = - static_cast(ScanASTContext.getClangModuleLoader()); clangImporter->addClangInvovcationDependencies(clangDependencyFiles); llvm::for_each(clangDependencyFiles, [&](std::string &file) { tracker->trackFile(file); }); @@ -372,7 +372,9 @@ ModuleDependencyScanner::getMainModuleDependencyInfo( return std::make_error_code(std::errc::io_error); } rootID = root->getID().toString(); + } + if (ScanASTContext.ClangImporterOpts.ClangImporterDirectCC1Scan) { buildArgs.push_back("-direct-clang-cc1-module-build"); for (auto &arg : clangImporter->getSwiftExplicitModuleDirectCC1Args()) { buildArgs.push_back("-Xcc"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5968c640421..705d9216fdd 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1709,6 +1709,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args, Opts.DisableSourceImport |= Args.hasArg(OPT_disable_clangimporter_source_import); + Opts.ClangImporterDirectCC1Scan |= + Args.hasArg(OPT_experimental_clang_importer_direct_cc1_scan); // Forward the FrontendOptions to clang importer option so it can be // accessed when creating clang module compilation invocation. if (CASOpts.EnableCaching) { @@ -1716,6 +1718,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args, // useful in non-caching context. Opts.UseClangIncludeTree |= !Args.hasArg(OPT_no_clang_include_tree); Opts.HasClangIncludeTreeRoot |= Args.hasArg(OPT_clang_include_tree_root); + // Caching requires direct clang import cc1 scanning. + Opts.ClangImporterDirectCC1Scan = true; } // If in direct clang cc1 module build mode, return early. diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 7278dde764e..2b7d829ff5b 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1677,6 +1677,8 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface( genericSubInvocation.getClangImporterOptions().DirectClangCC1ModuleBuild = clangImporterOpts.DirectClangCC1ModuleBuild; + genericSubInvocation.getClangImporterOptions().ClangImporterDirectCC1Scan = + clangImporterOpts.ClangImporterDirectCC1Scan; // Validate Clang modules once per-build session flags must be consistent // across all module sub-invocations diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index eff95915152..a06452e3591 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -160,7 +160,7 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, // Handle clang arguments. For caching build, all arguments are passed // with `-direct-clang-cc1-module-build`. - if (Ctx.CASOpts.EnableCaching) { + if (Ctx.ClangImporterOpts.ClangImporterDirectCC1Scan) { Args.push_back("-direct-clang-cc1-module-build"); auto *importer = static_cast(Ctx.getClangModuleLoader()); diff --git a/test/ScanDependencies/direct_cc1_scan.swift b/test/ScanDependencies/direct_cc1_scan.swift new file mode 100644 index 00000000000..073d84836b9 --- /dev/null +++ b/test/ScanDependencies/direct_cc1_scan.swift @@ -0,0 +1,30 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module %t/A.swift -module-name A \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -enable-library-evolution -swift-version 5 \ +// RUN: -emit-module-interface-path %t/A.swiftinterface \ +// RUN: -o %t/A.swiftmodule + +// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json -I %t \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: %t/test.swift -module-name Test -swift-version 5 +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json A | %FileCheck %s --check-prefix CHECK-NO-DIRECT-CC1 +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json Test | %FileCheck %s --allow-empty --check-prefix CHECK-NO-DIRECT-CC1 + +// RUN: %target-swift-frontend -scan-dependencies -o %t/deps2.json -I %t \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: %t/test.swift -module-name Test -swift-version 5 -experimental-clang-importer-direct-cc1-scan +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps2.json A | %FileCheck %s --check-prefix CHECK-DIRECT-CC1-SCAN +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps2.json Test | %FileCheck %s --check-prefix CHECK-DIRECT-CC1-SCAN + +// CHECK-NO-DIRECT-CC1-NOT: -direct-clang-cc1-module-build +// CHECK-DIRECT-CC1-SCAN: -direct-clang-cc1-module-build + +//--- A.swift +func a() {} + +//--- test.swift +import A +func test() {}