Skip to content

Commit 0b4be90

Browse files
committed
[clang][deps] Store common, partially-formed invocation
1 parent e1cc299 commit 0b4be90

File tree

2 files changed

+85
-56
lines changed

2 files changed

+85
-56
lines changed

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,11 @@ class ModuleDepCollector final : public DependencyCollector {
241241
llvm::SetVector<const Module *> DirectModularDeps;
242242
/// Options that control the dependency output generation.
243243
std::unique_ptr<DependencyOutputOptions> Opts;
244-
/// The original Clang invocation passed to dependency scanner.
245-
CompilerInvocation OriginalInvocation;
244+
/// A Clang invocation that's based on the original TU invocation and that has
245+
/// been partially transformed into one that can perform explicit build of
246+
/// a discovered modular dependency. Note that this still needs to be adjusted
247+
/// for each individual module.
248+
CowCompilerInvocation CommonInvocation;
246249
/// Whether to optimize the modules' command-line arguments.
247250
bool OptimizeArgs;
248251
/// Whether to set up command-lines to load PCM files eagerly.
@@ -262,12 +265,11 @@ class ModuleDepCollector final : public DependencyCollector {
262265
/// Adds \p Path to \c MD.FileDeps, making it absolute if necessary.
263266
void addFileDep(ModuleDeps &MD, StringRef Path);
264267

265-
/// Constructs a CompilerInvocation that can be used to build the given
266-
/// module, excluding paths to discovered modular dependencies that are yet to
267-
/// be built.
268-
CompilerInvocation makeInvocationForModuleBuildWithoutOutputs(
268+
/// Get a Clang invocation adjusted to build the given modular dependency.
269+
/// This excludes paths that are yet-to-be-provided by the build system.
270+
CowCompilerInvocation getInvocationAdjustedForModuleBuildWithoutOutputs(
269271
const ModuleDeps &Deps,
270-
llvm::function_ref<void(CompilerInvocation &)> Optimize) const;
272+
llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const;
271273

272274
/// Collect module map files for given modules.
273275
llvm::DenseSet<const FileEntry *>
@@ -279,13 +281,16 @@ class ModuleDepCollector final : public DependencyCollector {
279281
/// Add module files (pcm) to the invocation, if needed.
280282
void addModuleFiles(CompilerInvocation &CI,
281283
ArrayRef<ModuleID> ClangModuleDeps) const;
284+
void addModuleFiles(CowCompilerInvocation &CI,
285+
ArrayRef<ModuleID> ClangModuleDeps) const;
282286

283287
/// Add paths that require looking up outputs to the given dependencies.
284-
void addOutputPaths(CompilerInvocation &CI, ModuleDeps &Deps);
288+
void addOutputPaths(CowCompilerInvocation &CI, ModuleDeps &Deps);
285289

286290
/// Compute the context hash for \p Deps, and create the mapping
287291
/// \c ModuleDepsByID[Deps.ID] = &Deps.
288-
void associateWithContextHash(const CompilerInvocation &CI, ModuleDeps &Deps);
292+
void associateWithContextHash(const CowCompilerInvocation &CI,
293+
ModuleDeps &Deps);
289294
};
290295

291296
} // end namespace dependencies

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,18 @@ static std::vector<std::string> splitString(std::string S, char Separator) {
5454
return Result;
5555
}
5656

57-
void ModuleDepCollector::addOutputPaths(CompilerInvocation &CI,
57+
void ModuleDepCollector::addOutputPaths(CowCompilerInvocation &CI,
5858
ModuleDeps &Deps) {
59-
CI.getFrontendOpts().OutputFile =
59+
CI.getMutFrontendOpts().OutputFile =
6060
Controller.lookupModuleOutput(Deps.ID, ModuleOutputKind::ModuleFile);
6161
if (!CI.getDiagnosticOpts().DiagnosticSerializationFile.empty())
62-
CI.getDiagnosticOpts().DiagnosticSerializationFile =
62+
CI.getMutDiagnosticOpts().DiagnosticSerializationFile =
6363
Controller.lookupModuleOutput(
6464
Deps.ID, ModuleOutputKind::DiagnosticSerializationFile);
6565
if (!CI.getDependencyOutputOpts().OutputFile.empty()) {
66-
CI.getDependencyOutputOpts().OutputFile = Controller.lookupModuleOutput(
66+
CI.getMutDependencyOutputOpts().OutputFile = Controller.lookupModuleOutput(
6767
Deps.ID, ModuleOutputKind::DependencyFile);
68-
CI.getDependencyOutputOpts().Targets =
68+
CI.getMutDependencyOutputOpts().Targets =
6969
splitString(Controller.lookupModuleOutput(
7070
Deps.ID, ModuleOutputKind::DependencyTargets),
7171
'\0');
@@ -74,18 +74,13 @@ void ModuleDepCollector::addOutputPaths(CompilerInvocation &CI,
7474
// Fallback to -o as dependency target, as in the driver.
7575
SmallString<128> Target;
7676
quoteMakeTarget(CI.getFrontendOpts().OutputFile, Target);
77-
CI.getDependencyOutputOpts().Targets.push_back(std::string(Target));
77+
CI.getMutDependencyOutputOpts().Targets.push_back(std::string(Target));
7878
}
7979
}
8080
}
8181

82-
CompilerInvocation
83-
ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
84-
const ModuleDeps &Deps,
85-
llvm::function_ref<void(CompilerInvocation &)> Optimize) const {
86-
// Make a deep copy of the original Clang invocation.
87-
CompilerInvocation CI(OriginalInvocation);
88-
82+
static CowCompilerInvocation
83+
makeCommonInvocationForModuleBuild(CompilerInvocation CI) {
8984
CI.resetNonModularOptions();
9085
CI.clearImplicitModuleBuildOptions();
9186

@@ -117,14 +112,38 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
117112
CI.getFrontendOpts().ARCMTAction = FrontendOptions::ARCMT_None;
118113
CI.getFrontendOpts().ObjCMTAction = FrontendOptions::ObjCMT_None;
119114
CI.getFrontendOpts().MTMigrateDir.clear();
120-
CI.getLangOpts().ModuleName = Deps.ID.ModuleName;
121-
CI.getFrontendOpts().IsSystemModule = Deps.IsSystem;
115+
CI.getLangOpts().ModuleName.clear();
116+
117+
// Remove any macro definitions that are explicitly ignored.
118+
if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
119+
llvm::erase_if(
120+
CI.getPreprocessorOpts().Macros,
121+
[&CI](const std::pair<std::string, bool> &Def) {
122+
StringRef MacroDef = Def.first;
123+
return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
124+
llvm::CachedHashString(MacroDef.split('=').first));
125+
});
126+
// Remove the now unused option.
127+
CI.getHeaderSearchOpts().ModulesIgnoreMacros.clear();
128+
}
129+
130+
return CI;
131+
}
132+
133+
CowCompilerInvocation
134+
ModuleDepCollector::getInvocationAdjustedForModuleBuildWithoutOutputs(
135+
const ModuleDeps &Deps,
136+
llvm::function_ref<void(CowCompilerInvocation &)> Optimize) const {
137+
CowCompilerInvocation CI = CommonInvocation;
138+
139+
CI.getMutLangOpts().ModuleName = Deps.ID.ModuleName;
140+
CI.getMutFrontendOpts().IsSystemModule = Deps.IsSystem;
122141

123142
// Inputs
124143
InputKind ModuleMapInputKind(CI.getFrontendOpts().DashX.getLanguage(),
125144
InputKind::Format::ModuleMap);
126-
CI.getFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
127-
ModuleMapInputKind);
145+
CI.getMutFrontendOpts().Inputs.emplace_back(Deps.ClangModuleMapFile,
146+
ModuleMapInputKind);
128147

129148
auto CurrentModuleMapEntry =
130149
ScanInstance.getFileManager().getFile(Deps.ClangModuleMapFile);
@@ -150,36 +169,25 @@ ModuleDepCollector::makeInvocationForModuleBuildWithoutOutputs(
150169
!DepModuleMapFiles.contains(*ModuleMapEntry))
151170
continue;
152171

153-
CI.getFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
172+
CI.getMutFrontendOpts().ModuleMapFiles.emplace_back(ModuleMapFile);
154173
}
155174

156175
// Report the prebuilt modules this module uses.
157176
for (const auto &PrebuiltModule : Deps.PrebuiltModuleDeps)
158-
CI.getFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
177+
CI.getMutFrontendOpts().ModuleFiles.push_back(PrebuiltModule.PCMFile);
159178

160179
// Add module file inputs from dependencies.
161180
addModuleFiles(CI, Deps.ClangModuleDeps);
162181

163-
// Remove any macro definitions that are explicitly ignored.
164-
if (!CI.getHeaderSearchOpts().ModulesIgnoreMacros.empty()) {
165-
llvm::erase_if(
166-
CI.getPreprocessorOpts().Macros,
167-
[&CI](const std::pair<std::string, bool> &Def) {
168-
StringRef MacroDef = Def.first;
169-
return CI.getHeaderSearchOpts().ModulesIgnoreMacros.contains(
170-
llvm::CachedHashString(MacroDef.split('=').first));
171-
});
172-
// Remove the now unused option.
173-
CI.getHeaderSearchOpts().ModulesIgnoreMacros.clear();
182+
if (!CI.getDiagnosticOpts().SystemHeaderWarningsModules.empty()) {
183+
// Apply -Wsystem-headers-in-module for the current module.
184+
if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
185+
Deps.ID.ModuleName))
186+
CI.getMutDiagnosticOpts().Warnings.push_back("system-headers");
187+
// Remove the now unused option(s).
188+
CI.getMutDiagnosticOpts().SystemHeaderWarningsModules.clear();
174189
}
175190

176-
// Apply -Wsystem-headers-in-module for the current module.
177-
if (llvm::is_contained(CI.getDiagnosticOpts().SystemHeaderWarningsModules,
178-
Deps.ID.ModuleName))
179-
CI.getDiagnosticOpts().Warnings.push_back("system-headers");
180-
// Remove the now unused option(s).
181-
CI.getDiagnosticOpts().SystemHeaderWarningsModules.clear();
182-
183191
Optimize(CI);
184192

185193
return CI;
@@ -224,6 +232,19 @@ void ModuleDepCollector::addModuleFiles(
224232
}
225233
}
226234

235+
void ModuleDepCollector::addModuleFiles(
236+
CowCompilerInvocation &CI, ArrayRef<ModuleID> ClangModuleDeps) const {
237+
for (const ModuleID &MID : ClangModuleDeps) {
238+
std::string PCMPath =
239+
Controller.lookupModuleOutput(MID, ModuleOutputKind::ModuleFile);
240+
if (EagerLoadModules)
241+
CI.getMutFrontendOpts().ModuleFiles.push_back(std::move(PCMPath));
242+
else
243+
CI.getMutHeaderSearchOpts().PrebuiltModuleFiles.insert(
244+
{MID.ModuleName, std::move(PCMPath)});
245+
}
246+
}
247+
227248
static bool needsModules(FrontendInputFile FIF) {
228249
switch (FIF.getKind().getLanguage()) {
229250
case Language::Unknown:
@@ -264,7 +285,7 @@ void ModuleDepCollector::applyDiscoveredDependencies(CompilerInvocation &CI) {
264285
}
265286

266287
static std::string getModuleContextHash(const ModuleDeps &MD,
267-
const CompilerInvocation &CI,
288+
const CowCompilerInvocation &CI,
268289
bool EagerLoadModules) {
269290
llvm::HashBuilder<llvm::TruncatedBLAKE3<16>,
270291
llvm::support::endianness::native>
@@ -304,8 +325,8 @@ static std::string getModuleContextHash(const ModuleDeps &MD,
304325
return toString(llvm::APInt(sizeof(Words) * 8, Words), 36, /*Signed=*/false);
305326
}
306327

307-
void ModuleDepCollector::associateWithContextHash(const CompilerInvocation &CI,
308-
ModuleDeps &Deps) {
328+
void ModuleDepCollector::associateWithContextHash(
329+
const CowCompilerInvocation &CI, ModuleDeps &Deps) {
309330
Deps.ID.ContextHash = getModuleContextHash(Deps, CI, EagerLoadModules);
310331
bool Inserted = ModuleDepsByID.insert({Deps.ID, &Deps}).second;
311332
(void)Inserted;
@@ -498,12 +519,13 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
498519
MD.ModuleMapFileDeps.emplace_back(IFI.FilenameAsRequested);
499520
});
500521

501-
CompilerInvocation CI = MDC.makeInvocationForModuleBuildWithoutOutputs(
502-
MD, [&](CompilerInvocation &BuildInvocation) {
503-
if (MDC.OptimizeArgs)
504-
optimizeHeaderSearchOpts(BuildInvocation.getHeaderSearchOpts(),
505-
*MDC.ScanInstance.getASTReader(), *MF);
506-
});
522+
CowCompilerInvocation CI =
523+
MDC.getInvocationAdjustedForModuleBuildWithoutOutputs(
524+
MD, [&](CowCompilerInvocation &BuildInvocation) {
525+
if (MDC.OptimizeArgs)
526+
optimizeHeaderSearchOpts(BuildInvocation.getMutHeaderSearchOpts(),
527+
*MDC.ScanInstance.getASTReader(), *MF);
528+
});
507529

508530
MDC.associateWithContextHash(CI, MD);
509531

@@ -601,7 +623,9 @@ ModuleDepCollector::ModuleDepCollector(
601623
DependencyActionController &Controller, CompilerInvocation OriginalCI,
602624
bool OptimizeArgs, bool EagerLoadModules, bool IsStdModuleP1689Format)
603625
: ScanInstance(ScanInstance), Consumer(C), Controller(Controller),
604-
Opts(std::move(Opts)), OriginalInvocation(std::move(OriginalCI)),
626+
Opts(std::move(Opts)),
627+
CommonInvocation(
628+
makeCommonInvocationForModuleBuild(std::move(OriginalCI))),
605629
OptimizeArgs(OptimizeArgs), EagerLoadModules(EagerLoadModules),
606630
IsStdModuleP1689Format(IsStdModuleP1689Format) {}
607631

0 commit comments

Comments
 (0)