diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h @@ -46,7 +46,8 @@ public: DependencyScanningService(ScanningMode Mode, ScanningOutputFormat Format, bool ReuseFileManager = true, - bool OptimizeArgs = false); + bool OptimizeArgs = false, + bool EagerLoadModules = false); ScanningMode getMode() const { return Mode; } @@ -56,6 +57,8 @@ bool canOptimizeArgs() const { return OptimizeArgs; } + bool shouldEagerLoadModules() const { return EagerLoadModules; } + DependencyScanningFilesystemSharedCache &getSharedCache() { return SharedCache; } @@ -66,6 +69,8 @@ const bool ReuseFileManager; /// Whether to optimize the modules' command-line arguments. const bool OptimizeArgs; + /// Whether to set up command-lines to load PCM files eagerly. + const bool EagerLoadModules; /// The global file system cache. DependencyScanningFilesystemSharedCache SharedCache; }; diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h @@ -106,8 +106,10 @@ class FullDependencyConsumer : public DependencyConsumer { public: FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen, - LookupModuleOutputCallback LookupModuleOutput) - : AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput) {} + LookupModuleOutputCallback LookupModuleOutput, + bool EagerLoadModules) + : AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput), + EagerLoadModules(EagerLoadModules) {} void handleDependencyOutputOpts(const DependencyOutputOptions &) override {} @@ -144,6 +146,7 @@ std::vector OutputPaths; const llvm::StringSet<> &AlreadySeen; LookupModuleOutputCallback LookupModuleOutput; + bool EagerLoadModules; }; } // end namespace dependencies diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h @@ -70,6 +70,8 @@ DependencyConsumer &Consumer, llvm::Optional ModuleName = None); + bool shouldEagerLoadModules() const { return EagerLoadModules; } + private: std::shared_ptr PCHContainerOps; @@ -87,6 +89,8 @@ ScanningOutputFormat Format; /// Whether to optimize the modules' command-line arguments. bool OptimizeArgs; + /// Whether to set up command-lines to load PCM files eagerly. + bool EagerLoadModules; }; } // end namespace dependencies diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h --- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h +++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h @@ -184,7 +184,8 @@ public: ModuleDepCollector(std::unique_ptr Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, - CompilerInvocation &&OriginalCI, bool OptimizeArgs); + CompilerInvocation &&OriginalCI, bool OptimizeArgs, + bool EagerLoadModules); void attachToPreprocessor(Preprocessor &PP) override; void attachToASTReader(ASTReader &R) override; @@ -211,6 +212,8 @@ CompilerInvocation OriginalInvocation; /// Whether to optimize the modules' command-line arguments. bool OptimizeArgs; + /// Whether to set up command-lines to load PCM files eagerly. + bool EagerLoadModules; /// Checks whether the module is known as being prebuilt. bool isPrebuiltModule(const Module *M); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningService.cpp @@ -15,9 +15,9 @@ DependencyScanningService::DependencyScanningService( ScanningMode Mode, ScanningOutputFormat Format, bool ReuseFileManager, - bool OptimizeArgs) + bool OptimizeArgs, bool EagerLoadModules) : Mode(Mode), Format(Format), ReuseFileManager(ReuseFileManager), - OptimizeArgs(OptimizeArgs) { + OptimizeArgs(OptimizeArgs), EagerLoadModules(EagerLoadModules) { // Initialize targets for object file support. llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @@ -114,7 +114,8 @@ const llvm::StringSet<> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput, llvm::Optional ModuleName) { - FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput); + FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput, + Worker.shouldEagerLoadModules()); llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName); if (Result) @@ -140,9 +141,14 @@ auto &MD = M.second; if (MD.ImportedByMainFile) { FD.ClangModuleDeps.push_back(MD.ID); - FD.CommandLine.push_back( - "-fmodule-file=" + - LookupModuleOutput(MD.ID, ModuleOutputKind::ModuleFile)); + auto PCMPath = LookupModuleOutput(MD.ID, ModuleOutputKind::ModuleFile); + if (EagerLoadModules) { + FD.CommandLine.push_back("-fmodule-file=" + PCMPath); + } else { + FD.CommandLine.push_back("-fmodule-map-file=" + MD.ClangModuleMapFile); + FD.CommandLine.push_back("-fmodule-file=" + MD.ID.ModuleName + "=" + + PCMPath); + } } } diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -140,11 +140,12 @@ DependencyScanningAction( StringRef WorkingDirectory, DependencyConsumer &Consumer, llvm::IntrusiveRefCntPtr DepFS, - ScanningOutputFormat Format, bool OptimizeArgs, bool DisableFree, - llvm::Optional ModuleName = None) + ScanningOutputFormat Format, bool OptimizeArgs, bool EagerLoadModules, + bool DisableFree, llvm::Optional ModuleName = None) : WorkingDirectory(WorkingDirectory), Consumer(Consumer), DepFS(std::move(DepFS)), Format(Format), OptimizeArgs(OptimizeArgs), - DisableFree(DisableFree), ModuleName(ModuleName) {} + EagerLoadModules(EagerLoadModules), DisableFree(DisableFree), + ModuleName(ModuleName) {} bool runInvocation(std::shared_ptr Invocation, FileManager *FileMgr, @@ -231,7 +232,7 @@ case ScanningOutputFormat::Full: ScanInstance.addDependencyCollector(std::make_shared( std::move(Opts), ScanInstance, Consumer, - std::move(OriginalInvocation), OptimizeArgs)); + std::move(OriginalInvocation), OptimizeArgs, EagerLoadModules)); break; } @@ -261,6 +262,7 @@ llvm::IntrusiveRefCntPtr DepFS; ScanningOutputFormat Format; bool OptimizeArgs; + bool EagerLoadModules; bool DisableFree; llvm::Optional ModuleName; }; @@ -270,7 +272,8 @@ DependencyScanningWorker::DependencyScanningWorker( DependencyScanningService &Service, llvm::IntrusiveRefCntPtr FS) - : Format(Service.getFormat()), OptimizeArgs(Service.canOptimizeArgs()) { + : Format(Service.getFormat()), OptimizeArgs(Service.canOptimizeArgs()), + EagerLoadModules(Service.shouldEagerLoadModules()) { PCHContainerOps = std::make_shared(); PCHContainerOps->registerReader( std::make_unique()); @@ -343,7 +346,8 @@ bool DisableFree = true; DependencyScanningAction Action( WorkingDirectory, Consumer, DepFS, Format, - OptimizeArgs, DisableFree, ModuleName); + OptimizeArgs, EagerLoadModules, DisableFree, + ModuleName); // Create an invocation that uses the underlying file // system to ensure that any file system requests that // are made by the driver do not go through the diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -54,9 +54,19 @@ void ModuleDepCollector::addOutputPaths(ModuleDeps &Deps) { CompilerInvocation &CI = Deps.BuildInvocation; - for (ModuleID MID : Deps.ClangModuleDeps) - CI.getFrontendOpts().ModuleFiles.push_back( - Consumer.lookupModuleOutput(MID, ModuleOutputKind::ModuleFile)); + + // These are technically *inputs* to the compilation, but we populate them + // here in order to make \c getModuleContextHash() independent of + // \c lookupModuleOutput(). + for (ModuleID MID : Deps.ClangModuleDeps) { + auto PCMPath = + Consumer.lookupModuleOutput(MID, ModuleOutputKind::ModuleFile); + if (EagerLoadModules) + CI.getFrontendOpts().ModuleFiles.push_back(PCMPath); + else + CI.getHeaderSearchOpts().PrebuiltModuleFiles.insert( + {MID.ModuleName, PCMPath}); + } CI.getFrontendOpts().OutputFile = Consumer.lookupModuleOutput(Deps.ID, ModuleOutputKind::ModuleFile); @@ -133,6 +143,19 @@ for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps) CI.getFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile); + if (!EagerLoadModules) { + ModuleMap &ModMap = + ScanInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + for (ModuleID MID : Deps.ClangModuleDeps) { + const Module *M = ModMap.findModule(MID.ModuleName); + assert(M && "Modular dependency not found"); + auto MDeps = ModularDeps.find(M); + assert(MDeps != ModularDeps.end() && "Inconsistent dependency info"); + CI.getFrontendOpts().ModuleMapFiles.push_back( + MDeps->second->ClangModuleMapFile); + } + } + // Remove any macro definitions that are explicitly ignored. if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) { llvm::erase_if( @@ -178,7 +201,8 @@ return serializeCompilerInvocation(BuildInvocation); } -static std::string getModuleContextHash(const ModuleDeps &MD) { +static std::string getModuleContextHash(const ModuleDeps &MD, + bool EagerLoadModules) { llvm::HashBuilder, llvm::support::endianness::native> HashBuilder; @@ -208,6 +232,8 @@ HashBuilder.add(ID.ContextHash); } + HashBuilder.add(EagerLoadModules); + llvm::BLAKE3Result<16> Hash = HashBuilder.final(); std::array Words; static_assert(sizeof(Hash) == sizeof(Words), "Hash must match Words"); @@ -385,8 +411,11 @@ // Add direct prebuilt module dependencies now, so that we can use them when // creating a CompilerInvocation and computing context hash for this // ModuleDeps instance. + // TODO: Squash these. llvm::DenseSet SeenModules; addAllSubmodulePrebuiltDeps(M, MD, SeenModules); + llvm::DenseSet AddedModules; + addAllSubmoduleDeps(M, MD, AddedModules); MD.BuildInvocation = MDC.makeInvocationForModuleBuildWithoutOutputs( MD, [&](CompilerInvocation &BuildInvocation) { @@ -395,11 +424,8 @@ *MDC.ScanInstance.getASTReader(), *MF); }); - llvm::DenseSet AddedModules; - addAllSubmoduleDeps(M, MD, AddedModules); - // Compute the context hash from the inputs. Requires dependencies. - MD.ID.ContextHash = getModuleContextHash(MD); + MD.ID.ContextHash = getModuleContextHash(MD, MDC.EagerLoadModules); // Finish the compiler invocation. Requires dependencies and the context hash. MDC.addOutputPaths(MD); return MD.ID; @@ -465,9 +491,10 @@ ModuleDepCollector::ModuleDepCollector( std::unique_ptr Opts, CompilerInstance &ScanInstance, DependencyConsumer &C, - CompilerInvocation &&OriginalCI, bool OptimizeArgs) + CompilerInvocation &&OriginalCI, bool OptimizeArgs, bool EagerLoadModules) : ScanInstance(ScanInstance), Consumer(C), Opts(std::move(Opts)), - OriginalInvocation(std::move(OriginalCI)), OptimizeArgs(OptimizeArgs) {} + OriginalInvocation(std::move(OriginalCI)), OptimizeArgs(OptimizeArgs), + EagerLoadModules(EagerLoadModules) {} void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) { PP.addPPCallbacks(std::make_unique(*this)); diff --git a/clang/test/ClangScanDeps/modules-dep-args.c b/clang/test/ClangScanDeps/modules-dep-args.c new file mode 100644 --- /dev/null +++ b/clang/test/ClangScanDeps/modules-dep-args.c @@ -0,0 +1,102 @@ +// This test exercises the different ways explicit modular dependencies are +// provided on the command-line. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- cdb.json.template +[{ + "file": "DIR/tu.c", + "directory": "DIR", + "command": "clang DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -o DIR/tu.o" +}] + +//--- module.modulemap +module Transitive { header "transitive.h" } +module Direct { header "direct.h" } +//--- transitive.h +//--- direct.h +#include "transitive.h" +//--- tu.c +#include "direct.h" + +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json + +// Check that the PCM path defaults to the modules cache from implicit build. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/result_cache.json +// RUN: cat %t/result_cache.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK,CHECK_CACHE + +// Check that the PCM path can be customized. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -module-files-dir %t/build > %t/result_build.json +// RUN: cat %t/result_build.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK,CHECK_BUILD + +// Check that the PCM file is loaded lazily by default. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/result_lazy.json +// RUN: cat %t/result_lazy.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK,CHECK_LAZY + +// Check that the PCM file can be loaded eagerly. +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full -eager-load-pcm > %t/result_eager.json +// RUN: cat %t/result_eager.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK,CHECK_EAGER + +// CHECK: { +// CHECK-NEXT: "modules": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "module-name": "Transitive" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK_CACHE: "-fmodule-file={{.*}}/cache/{{.*}}/Transitive-{{.*}}.pcm" +// CHECK_BUILD: "-fmodule-file={{.*}}/build/{{.*}}/Transitive-{{.*}}.pcm" +// CHECK_LAZY: "-fmodule-map-file=[[PREFIX]]/module.modulemap" +// CHECK_LAZY: "-fmodule-file=Transitive=[[PREFIX]]/{{.*}}/Transitive-{{.*}}.pcm" +// CHECK_EAGER-NOT: "-fmodule-map-file={{.*}}" +// CHECK_EAGER: "-fmodule-file=[[PREFIX]]/{{.*}}/Transitive-{{.*}}.pcm" +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/direct.h", +// CHECK-NEXT: "[[PREFIX]]/module.modulemap" +// CHECK-NEXT: ], +// CHECK-NEXT: "name": "Direct" +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "clang-module-deps": [], +// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "command-line": [ +// CHECK: ], +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/transitive.h" +// CHECK-NEXT: ], +// CHECK-NEXT: "name": "Transitive" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "translation-units": [ +// CHECK-NEXT: { +// CHECK-NEXT: "clang-context-hash": "{{.*}}", +// CHECK-NEXT: "clang-module-deps": [ +// CHECK-NEXT: { +// CHECK-NEXT: "context-hash": "{{.*}}", +// CHECK-NEXT: "module-name": "Direct" +// CHECK-NEXT: } +// CHECK-NEXT: ], +// CHECK-NEXT: "command-line": [ +// CHECK_CACHE: "-fmodule-file={{.*}}/cache/{{.*}}/Direct-{{.*}}.pcm" +// CHECK_BUILD: "-fmodule-file={{.*}}/build/{{.*}}/Direct-{{.*}}.pcm" +// CHECK_LAZY: "-fmodule-map-file=[[PREFIX]]/module.modulemap" +// CHECK_LAZY: "-fmodule-file=Direct=[[PREFIX]]/{{.*}}/Direct-{{.*}}.pcm" +// CHECK_EAGER-NOT: "-fmodule-map-file={{.*}}" +// CHECK_EAGER: "-fmodule-file=[[PREFIX]]/{{.*}}/Direct-{{.*}}.pcm" +// CHECK: ], +// CHECK-NEXT: "file-deps": [ +// CHECK-NEXT: "[[PREFIX]]/tu.c" +// CHECK-NEXT: ], +// CHECK-NEXT: "input-file": "[[PREFIX]]/tu.c" +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } \ No newline at end of file diff --git a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m --- a/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m +++ b/clang/test/ClangScanDeps/modules-fmodule-name-no-module-built.m @@ -41,10 +41,7 @@ // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ -// CHECK: "-fno-implicit-modules" -// CHECK-NEXT: "-fno-implicit-module-maps" -// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2]]/header2-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules-fmodule-name-no-module-built.m" // CHECK-NEXT: "[[PREFIX]]/Inputs/header3.h" diff --git a/clang/test/ClangScanDeps/modules-full.cpp b/clang/test/ClangScanDeps/modules-full.cpp --- a/clang/test/ClangScanDeps/modules-full.cpp +++ b/clang/test/ClangScanDeps/modules-full.cpp @@ -12,16 +12,11 @@ // // RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \ // RUN: -mode preprocess-dependency-directives > %t.result -// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-ABS %s -// -// RUN: clang-scan-deps -compilation-database %t.cdb -j 4 -format experimental-full \ -// RUN: -module-files-dir %t.dir/custom \ -// RUN: -mode preprocess-dependency-directives > %t.result -// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-CUSTOM %s +// RUN: cat %t.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir %s // // RUN: clang-scan-deps -compilation-database %t_clangcl.cdb -j 4 -format experimental-full \ // RUN: -mode preprocess-dependency-directives > %t_clangcl.result -// RUN: cat %t_clangcl.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir --check-prefixes=CHECK,CHECK-ABS %s +// RUN: cat %t_clangcl.result | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t.dir %s #include "header.h" @@ -38,8 +33,7 @@ // CHECK-NEXT: "command-line": [ // CHECK-NEXT: "-cc1" // CHECK: "-emit-module" -// CHECK-ABS: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2_DINCLUDE]]/header2-{{[A-Z0-9]+}}.pcm" -// CHECK-CUSTOM: "-fmodule-file=[[PREFIX]]/custom/[[HASH_H2_DINCLUDE]]/header2-{{[A-Z0-9]+}}.pcm" +// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H2_DINCLUDE]]/header2-{{[A-Z0-9]+}}.pcm" // CHECK-NOT: "-fimplicit-module-maps" // CHECK: "-fmodule-name=header1" // CHECK: "-fno-implicit-modules" @@ -97,10 +91,9 @@ // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ // CHECK: "-fno-implicit-modules" -// CHECK-NEXT: "-fno-implicit-module-maps" -// CHECK-ABS-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-CUSTOM-NEXT: "-fmodule-file=[[PREFIX]]/custom/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: "-fno-implicit-module-maps" +// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp" // CHECK-NEXT: ], @@ -116,10 +109,9 @@ // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ // CHECK: "-fno-implicit-modules" -// CHECK-NEXT: "-fno-implicit-module-maps" -// CHECK-ABS-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-CUSTOM-NEXT: "-fmodule-file=[[PREFIX]]/custom/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: "-fno-implicit-module-maps" +// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp" // CHECK-NEXT: ], @@ -135,10 +127,9 @@ // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ // CHECK: "-fno-implicit-modules" -// CHECK-NEXT: "-fno-implicit-module-maps" -// CHECK-ABS-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-CUSTOM-NEXT: "-fmodule-file=[[PREFIX]]/custom/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: "-fno-implicit-module-maps" +// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1]]/header1-{{[A-Z0-9]+}}.pcm" +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp" // CHECK-NEXT: ], @@ -154,10 +145,9 @@ // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ // CHECK: "-fno-implicit-modules" -// CHECK-NEXT: "-fno-implicit-module-maps" -// CHECK-ABS-NEXT: "-fmodule-file=[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1_DINCLUDE]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-CUSTOM-NEXT: "-fmodule-file=[[PREFIX]]/custom/[[HASH_H1_DINCLUDE]]/header1-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: "-fno-implicit-module-maps" +// CHECK: "-fmodule-file={{.*}}[[PREFIX]]/module-cache{{(_clangcl)?}}/[[HASH_H1_DINCLUDE]]/header1-{{[A-Z0-9]+}}.pcm" +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules_cdb_input2.cpp" // CHECK-NEXT: ], diff --git a/clang/test/ClangScanDeps/modules-inferred.m b/clang/test/ClangScanDeps/modules-inferred.m --- a/clang/test/ClangScanDeps/modules-inferred.m +++ b/clang/test/ClangScanDeps/modules-inferred.m @@ -19,11 +19,6 @@ // CHECK-NEXT: "clang-module-deps": [], // CHECK-NEXT: "clang-modulemap-file": "[[SOURCEDIR]]/Inputs/frameworks/module.modulemap", // CHECK-NEXT: "command-line": [ -// CHECK-NEXT: "-cc1", -// CHECK: "-emit-module", -// CHECK-NOT: "-fimplicit-module-maps", -// CHECK: "-fmodule-name=Inferred", -// CHECK: "-fno-implicit-modules", // CHECK: ], // CHECK-NEXT: "context-hash": "[[HASH_INFERRED:[A-Z0-9]+]]", // CHECK-NEXT: "file-deps": [ @@ -44,10 +39,7 @@ // CHECK-NEXT: } // CHECK-NEXT: ], // CHECK-NEXT: "command-line": [ -// CHECK: "-fno-implicit-modules", -// CHECK-NEXT: "-fno-implicit-module-maps", -// CHECK-NEXT: "-fmodule-file=[[PREFIX]]/module-cache/[[HASH_INFERRED]]/Inferred-{{[A-Z0-9]+}}.pcm" -// CHECK-NEXT: ], +// CHECK: ], // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/modules_cdb_input.cpp" // CHECK-NEXT: ], diff --git a/clang/test/ClangScanDeps/modules-pch-common-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-submodule.c --- a/clang/test/ClangScanDeps/modules-pch-common-submodule.c +++ b/clang/test/ClangScanDeps/modules-pch-common-submodule.c @@ -24,11 +24,6 @@ // CHECK-PCH-NEXT: "clang-module-deps": [], // CHECK-PCH-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH-NEXT: "-cc1" -// CHECK-PCH: "-emit-module" -// CHECK-PCH: "-fmodules" -// CHECK-PCH: "-fmodule-name=ModCommon" -// CHECK-PCH: "-fno-implicit-modules" // CHECK-PCH: ], // CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON:.*]]", // CHECK-PCH-NEXT: "file-deps": [ @@ -49,10 +44,7 @@ // CHECK-PCH-NEXT: } // CHECK-PCH-NEXT: ], // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH: "-fno-implicit-modules" -// CHECK-PCH-NEXT: "-fno-implicit-module-maps" -// CHECK-PCH-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON]]/ModCommon-{{.*}}.pcm" -// CHECK-PCH-NEXT: ], +// CHECK-PCH: ], // CHECK-PCH-NEXT: "file-deps": [ // CHECK-PCH-NEXT: "[[PREFIX]]/pch.h" // CHECK-PCH-NEXT: ], @@ -82,12 +74,6 @@ // CHECK-TU-NEXT: "clang-module-deps": [], // CHECK-TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU-NEXT: "-cc1" -// CHECK-TU: "-emit-module" -// CHECK-TU: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON:.*]]/ModCommon-{{.*}}.pcm" -// CHECK-TU: "-fmodules" -// CHECK-TU: "-fmodule-name=ModTU" -// CHECK-TU: "-fno-implicit-modules" // CHECK-TU: ], // CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU:.*]]", // CHECK-TU-NEXT: "file-deps": [ @@ -107,10 +93,7 @@ // CHECK-TU-NEXT: } // CHECK-TU-NEXT: ], // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU: "-fno-implicit-modules", -// CHECK-TU-NEXT: "-fno-implicit-module-maps", -// CHECK-TU-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU:.*]]/ModTU-{{.*}}.pcm" -// CHECK-TU-NEXT: ], +// CHECK-TU: ], // CHECK-TU-NEXT: "file-deps": [ // CHECK-TU-NEXT: "[[PREFIX]]/tu.c", // CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch" diff --git a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c --- a/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c +++ b/clang/test/ClangScanDeps/modules-pch-common-via-submodule.c @@ -2,9 +2,8 @@ // section in XCOFF yet. // UNSUPPORTED: aix -// Check that we discover dependency on a precompiled module (and generate the -// appropriate `-fmodule-file=` argument) when it's imported by a **submodule** -// instead of a top-level module. +// Check that we discover dependency on a precompiled module when it's imported +// by a **submodule** instead of a top-level module. // RUN: rm -rf %t && mkdir %t // RUN: cp %S/Inputs/modules-pch-common-via-submodule/* %t @@ -22,11 +21,6 @@ // CHECK-PCH-NEXT: "clang-module-deps": [], // CHECK-PCH-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH-NEXT: "-cc1" -// CHECK-PCH: "-emit-module" -// CHECK-PCH: "-fmodules" -// CHECK-PCH: "-fmodule-name=ModCommon" -// CHECK-PCH: "-fno-implicit-modules" // CHECK-PCH: ], // CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON:.*]]", // CHECK-PCH-NEXT: "file-deps": [ @@ -46,10 +40,7 @@ // CHECK-PCH-NEXT: } // CHECK-PCH-NEXT: ], // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH: "-fno-implicit-modules" -// CHECK-PCH-NEXT: "-fno-implicit-module-maps" -// CHECK-PCH-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON]]/ModCommon-{{.*}}.pcm" -// CHECK-PCH-NEXT: ], +// CHECK-PCH: ], // CHECK-PCH-NEXT: "file-deps": [ // CHECK-PCH-NEXT: "[[PREFIX]]/pch.h" // CHECK-PCH-NEXT: ], @@ -79,12 +70,6 @@ // CHECK-TU-NEXT: "clang-module-deps": [], // CHECK-TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU-NEXT: "-cc1" -// CHECK-TU: "-emit-module" -// CHECK-TU: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON:.*]]/ModCommon-{{.*}}.pcm" -// CHECK-TU: "-fmodules" -// CHECK-TU: "-fmodule-name=ModTU" -// CHECK-TU: "-fno-implicit-modules" // CHECK-TU: ], // CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU:.*]]", // CHECK-TU-NEXT: "file-deps": [ @@ -105,10 +90,7 @@ // CHECK-TU-NEXT: } // CHECK-TU-NEXT: ], // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU: "-fno-implicit-modules", -// CHECK-TU-NEXT: "-fno-implicit-module-maps", -// CHECK-TU-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU:.*]]/ModTU-{{.*}}.pcm" -// CHECK-TU-NEXT: ], +// CHECK-TU: ], // CHECK-TU-NEXT: "file-deps": [ // CHECK-TU-NEXT: "[[PREFIX]]/tu.c", // CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch" diff --git a/clang/test/ClangScanDeps/modules-pch.c b/clang/test/ClangScanDeps/modules-pch.c --- a/clang/test/ClangScanDeps/modules-pch.c +++ b/clang/test/ClangScanDeps/modules-pch.c @@ -21,12 +21,6 @@ // CHECK-PCH-NEXT: "clang-module-deps": [], // CHECK-PCH-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH-NEXT: "-cc1" -// CHECK-PCH: "-emit-module" -// CHECK-PCH: "-fmodules" -// CHECK-PCH-NOT: "-fimplicit-module-maps" -// CHECK-PCH: "-fmodule-name=ModCommon1" -// CHECK-PCH: "-fno-implicit-modules" // CHECK-PCH: ], // CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON_1:.*]]", // CHECK-PCH-NEXT: "file-deps": [ @@ -39,12 +33,6 @@ // CHECK-PCH-NEXT: "clang-module-deps": [], // CHECK-PCH-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH-NEXT: "-cc1" -// CHECK-PCH: "-emit-module" -// CHECK-PCH: "-fmodules" -// CHECK-PCH-NOT: "-fimplicit-module-maps" -// CHECK-PCH: "-fmodule-name=ModCommon2" -// CHECK-PCH: "-fno-implicit-modules" // CHECK-PCH: ], // CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_COMMON_2:.*]]", // CHECK-PCH-NEXT: "file-deps": [ @@ -62,13 +50,6 @@ // CHECK-PCH-NEXT: ], // CHECK-PCH-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH-NEXT: "-cc1" -// CHECK-PCH: "-emit-module" -// CHECK-PCH: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON_2]]/ModCommon2-{{.*}}.pcm" -// CHECK-PCH: "-fmodules" -// CHECK-PCH-NOT: "-fimplicit-module-maps" -// CHECK-PCH: "-fmodule-name=ModPCH" -// CHECK-PCH: "-fno-implicit-modules" // CHECK-PCH: ], // CHECK-PCH-NEXT: "context-hash": "[[HASH_MOD_PCH:.*]]", // CHECK-PCH-NEXT: "file-deps": [ @@ -92,11 +73,7 @@ // CHECK-PCH-NEXT: } // CHECK-PCH-NEXT: ], // CHECK-PCH-NEXT: "command-line": [ -// CHECK-PCH: "-fno-implicit-modules", -// CHECK-PCH-NEXT: "-fno-implicit-module-maps", -// CHECK-PCH-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_COMMON_1]]/ModCommon1-{{.*}}.pcm", -// CHECK-PCH-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_PCH]]/ModPCH-{{.*}}.pcm" -// CHECK-PCH-NEXT: ], +// CHECK-PCH: ], // CHECK-PCH-NEXT: "file-deps": [ // CHECK-PCH-NEXT: "[[PREFIX]]/pch.h" // CHECK-PCH-NEXT: ], @@ -130,11 +107,6 @@ // CHECK-TU-NEXT: "clang-module-deps": [], // CHECK-TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU-NEXT: "-cc1", -// CHECK-TU: "-emit-module", -// CHECK-TU-NOT: "-fimplicit-module-maps", -// CHECK-TU: "-fmodule-name=ModTU", -// CHECK-TU: "-fno-implicit-modules", // CHECK-TU: ], // CHECK-TU-NEXT: "context-hash": "[[HASH_MOD_TU:.*]]", // CHECK-TU-NEXT: "file-deps": [ @@ -154,10 +126,7 @@ // CHECK-TU-NEXT: } // CHECK-TU-NEXT: ], // CHECK-TU-NEXT: "command-line": [ -// CHECK-TU: "-fno-implicit-modules", -// CHECK-TU-NEXT: "-fno-implicit-module-maps", -// CHECK-TU-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU]]/ModTU-{{.*}}.pcm" -// CHECK-TU-NEXT: ], +// CHECK-TU: ], // CHECK-TU-NEXT: "file-deps": [ // CHECK-TU-NEXT: "[[PREFIX]]/tu.c", // CHECK-TU-NEXT: "[[PREFIX]]/pch.h.gch" @@ -188,12 +157,6 @@ // CHECK-TU-WITH-COMMON-NEXT: "clang-module-deps": [], // CHECK-TU-WITH-COMMON-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap", // CHECK-TU-WITH-COMMON-NEXT: "command-line": [ -// CHECK-TU-WITH-COMMON-NEXT: "-cc1", -// CHECK-TU-WITH-COMMON: "-emit-module", -// CHECK-TU-WITH-COMMON: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon1-{{.*}}.pcm", -// CHECK-TU-WITH-COMMON-NOT: "-fimplicit-module-maps", -// CHECK-TU-WITH-COMMON: "-fmodule-name=ModTUWithCommon", -// CHECK-TU-WITH-COMMON: "-fno-implicit-modules", // CHECK-TU-WITH-COMMON: ], // CHECK-TU-WITH-COMMON-NEXT: "context-hash": "[[HASH_MOD_TU_WITH_COMMON:.*]]", // CHECK-TU-WITH-COMMON-NEXT: "file-deps": [ @@ -213,11 +176,8 @@ // CHECK-TU-WITH-COMMON-NEXT: } // CHECK-TU-WITH-COMMON-NEXT: ], // CHECK-TU-WITH-COMMON-NEXT: "command-line": [ -// CHECK-TU-WITH-COMMON: "-fno-implicit-modules", -// CHECK-TU-WITH-COMMON-NEXT: "-fno-implicit-module-maps", -// CHECK-TU-WITH-COMMON-NEXT: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm", -// CHECK-TU-WITH-COMMON-NEXT: "-fmodule-file=[[PREFIX]]/build/[[HASH_MOD_TU_WITH_COMMON]]/ModTUWithCommon-{{.*}}.pcm" -// CHECK-TU-WITH-COMMON-NEXT: ], +// CHECK-TU-WITH-COMMON: "-fmodule-file=[[PREFIX]]/build/{{.*}}/ModCommon2-{{.*}}.pcm" +// CHECK-TU-WITH-COMMON: ], // CHECK-TU-WITH-COMMON-NEXT: "file-deps": [ // CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/tu_with_common.c", // CHECK-TU-WITH-COMMON-NEXT: "[[PREFIX]]/pch.h.gch" diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -151,6 +151,11 @@ llvm::cl::desc("Whether to optimize command-line arguments of modules."), llvm::cl::init(false), llvm::cl::cat(DependencyScannerCategory)); +static llvm::cl::opt EagerLoadModules( + "eager-load-pcm", + llvm::cl::desc("Load PCM files eagerly (instead of lazily on import)."), + llvm::cl::init(false), llvm::cl::cat(DependencyScannerCategory)); + llvm::cl::opt NumThreads("j", llvm::cl::Optional, llvm::cl::desc("Number of worker threads to use (default: use " @@ -499,7 +504,7 @@ SharedStream DependencyOS(llvm::outs()); DependencyScanningService Service(ScanMode, Format, ReuseFileManager, - OptimizeArgs); + OptimizeArgs, EagerLoadModules); llvm::ThreadPool Pool(llvm::hardware_concurrency(NumThreads)); std::vector> WorkerTools; for (unsigned I = 0; I < Pool.getThreadCount(); ++I)