Skip to content

Commit 5482432

Browse files
committed
[clang][deps] Compute command-lines for dependencies immediately
Instead of delaying the generation of command-lines to after all dependencies are reported, compute them immediately. This is partly in preparation for splitting the TU driver command into its constituent cc1 and other jobs, but it also just simplifies working with the compiler invocation for modules if they are not "without paths". Also change the computation of the default output path in clang-scan-deps to scrape the implicit module cache from the command-line rather than get it from the dependency, since that is now unavailable at the time we make the callback. Differential Revision: https://reviews.llvm.org/D131934
1 parent de6fd16 commit 5482432

File tree

6 files changed

+164
-156
lines changed

6 files changed

+164
-156
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ namespace clang {
2323
namespace tooling {
2424
namespace dependencies {
2525

26+
/// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
27+
using LookupModuleOutputCallback =
28+
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>;
29+
2630
/// The full dependencies and module graph for a specific input.
2731
struct FullDependencies {
2832
/// The identifier of the C++20 module this translation unit exports.
@@ -45,17 +49,8 @@ struct FullDependencies {
4549
/// determined that the differences are benign for this compilation.
4650
std::vector<ModuleID> ClangModuleDeps;
4751

48-
/// The original command line of the TU (excluding the compiler executable).
49-
std::vector<std::string> OriginalCommandLine;
50-
51-
/// Get the full command line.
52-
///
53-
/// \param LookupModuleOutput This function is called to fill in
54-
/// "-fmodule-file=", "-o" and other output
55-
/// arguments for dependencies.
56-
std::vector<std::string> getCommandLine(
57-
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>
58-
LookupModuleOutput) const;
52+
/// The command line of the TU (excluding the compiler executable).
53+
std::vector<std::string> CommandLine;
5954
};
6055

6156
struct FullDependenciesResult {
@@ -92,12 +87,16 @@ class DependencyScanningTool {
9287
/// function for a single \c DependencyScanningTool in a
9388
/// single build. Use a different one for different tools,
9489
/// and clear it between builds.
90+
/// \param LookupModuleOutput This function is called to fill in
91+
/// "-fmodule-file=", "-o" and other output
92+
/// arguments for dependencies.
9593
///
9694
/// \returns a \c StringError with the diagnostic output if clang errors
9795
/// occurred, \c FullDependencies otherwise.
9896
llvm::Expected<FullDependenciesResult>
9997
getFullDependencies(const std::vector<std::string> &CommandLine,
10098
StringRef CWD, const llvm::StringSet<> &AlreadySeen,
99+
LookupModuleOutputCallback LookupModuleOutput,
101100
llvm::Optional<StringRef> ModuleName = None);
102101

103102
private:
@@ -106,8 +105,9 @@ class DependencyScanningTool {
106105

107106
class FullDependencyConsumer : public DependencyConsumer {
108107
public:
109-
FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen)
110-
: AlreadySeen(AlreadySeen) {}
108+
FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen,
109+
LookupModuleOutputCallback LookupModuleOutput)
110+
: AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput) {}
111111

112112
void handleDependencyOutputOpts(const DependencyOutputOptions &) override {}
113113

@@ -127,6 +127,11 @@ class FullDependencyConsumer : public DependencyConsumer {
127127
ContextHash = std::move(Hash);
128128
}
129129

130+
std::string lookupModuleOutput(const ModuleID &ID,
131+
ModuleOutputKind Kind) override {
132+
return LookupModuleOutput(ID, Kind);
133+
}
134+
130135
FullDependenciesResult getFullDependencies(
131136
const std::vector<std::string> &OriginalCommandLine) const;
132137

@@ -138,6 +143,7 @@ class FullDependencyConsumer : public DependencyConsumer {
138143
std::string ContextHash;
139144
std::vector<std::string> OutputPaths;
140145
const llvm::StringSet<> &AlreadySeen;
146+
LookupModuleOutputCallback LookupModuleOutput;
141147
};
142148

143149
} // end namespace dependencies

clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ class DependencyConsumer {
4242
virtual void handleModuleDependency(ModuleDeps MD) = 0;
4343

4444
virtual void handleContextHash(std::string Hash) = 0;
45+
46+
virtual std::string lookupModuleOutput(const ModuleID &ID,
47+
ModuleOutputKind Kind) = 0;
4548
};
4649

4750
/// An individual dependency scanning worker that is able to run on its own

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

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -119,25 +119,11 @@ struct ModuleDeps {
119119
// the primary TU.
120120
bool ImportedByMainFile = false;
121121

122-
/// Whether the TU had a dependency file. The path in \c BuildInvocation is
123-
/// cleared to avoid leaking the specific path from the TU into the module.
124-
bool HadDependencyFile = false;
125-
126-
/// Whether the TU had serialized diagnostics. The path in \c BuildInvocation
127-
/// is cleared to avoid leaking the specific path from the TU into the module.
128-
bool HadSerializedDiagnostics = false;
129-
130122
/// Compiler invocation that can be used to build this module (without paths).
131123
CompilerInvocation BuildInvocation;
132124

133125
/// Gets the canonical command line suitable for passing to clang.
134-
///
135-
/// \param LookupModuleOutput This function is called to fill in
136-
/// "-fmodule-file=", "-o" and other output
137-
/// arguments.
138-
std::vector<std::string> getCanonicalCommandLine(
139-
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>
140-
LookupModuleOutput) const;
126+
std::vector<std::string> getCanonicalCommandLine() const;
141127
};
142128

143129
class ModuleDepCollector;
@@ -237,9 +223,12 @@ class ModuleDepCollector final : public DependencyCollector {
237223
/// Constructs a CompilerInvocation that can be used to build the given
238224
/// module, excluding paths to discovered modular dependencies that are yet to
239225
/// be built.
240-
CompilerInvocation makeInvocationForModuleBuildWithoutPaths(
226+
CompilerInvocation makeInvocationForModuleBuildWithoutOutputs(
241227
const ModuleDeps &Deps,
242228
llvm::function_ref<void(CompilerInvocation &)> Optimize) const;
229+
230+
/// Add paths that require looking up outputs to the given dependencies.
231+
void addOutputPaths(ModuleDeps &Deps);
243232
};
244233

245234
} // end namespace dependencies

clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,12 @@ using namespace clang;
1313
using namespace tooling;
1414
using namespace dependencies;
1515

16-
std::vector<std::string> FullDependencies::getCommandLine(
17-
llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>
18-
LookupModuleOutput) const {
16+
static std::vector<std::string>
17+
makeTUCommandLineWithoutPaths(ArrayRef<std::string> OriginalCommandLine) {
1918
std::vector<std::string> Args = OriginalCommandLine;
2019

2120
Args.push_back("-fno-implicit-modules");
2221
Args.push_back("-fno-implicit-module-maps");
23-
for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps)
24-
Args.push_back("-fmodule-file=" + PMD.PCMFile);
25-
for (ModuleID MID : ClangModuleDeps)
26-
Args.push_back("-fmodule-file=" +
27-
LookupModuleOutput(MID, ModuleOutputKind::ModuleFile));
2822

2923
// These arguments are unused in explicit compiles.
3024
llvm::erase_if(Args, [](StringRef Arg) {
@@ -72,6 +66,11 @@ llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
7266

7367
void handleContextHash(std::string Hash) override {}
7468

69+
std::string lookupModuleOutput(const ModuleID &ID,
70+
ModuleOutputKind Kind) override {
71+
llvm::report_fatal_error("unexpected call to lookupModuleOutput");
72+
}
73+
7574
void printDependencies(std::string &S) {
7675
assert(Opts && "Handled dependency output options.");
7776

@@ -113,8 +112,9 @@ llvm::Expected<FullDependenciesResult>
113112
DependencyScanningTool::getFullDependencies(
114113
const std::vector<std::string> &CommandLine, StringRef CWD,
115114
const llvm::StringSet<> &AlreadySeen,
115+
LookupModuleOutputCallback LookupModuleOutput,
116116
llvm::Optional<StringRef> ModuleName) {
117-
FullDependencyConsumer Consumer(AlreadySeen);
117+
FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput);
118118
llvm::Error Result =
119119
Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
120120
if (Result)
@@ -126,16 +126,24 @@ FullDependenciesResult FullDependencyConsumer::getFullDependencies(
126126
const std::vector<std::string> &OriginalCommandLine) const {
127127
FullDependencies FD;
128128

129-
FD.OriginalCommandLine = ArrayRef<std::string>(OriginalCommandLine).slice(1);
129+
FD.CommandLine = makeTUCommandLineWithoutPaths(
130+
ArrayRef<std::string>(OriginalCommandLine).slice(1));
130131

131132
FD.ID.ContextHash = std::move(ContextHash);
132133

133134
FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
134135

136+
for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps)
137+
FD.CommandLine.push_back("-fmodule-file=" + PMD.PCMFile);
138+
135139
for (auto &&M : ClangModuleDeps) {
136140
auto &MD = M.second;
137-
if (MD.ImportedByMainFile)
141+
if (MD.ImportedByMainFile) {
138142
FD.ClangModuleDeps.push_back(MD.ID);
143+
FD.CommandLine.push_back(
144+
"-fmodule-file=" +
145+
LookupModuleOutput(MD.ID, ModuleOutputKind::ModuleFile));
146+
}
139147
}
140148

141149
FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);

0 commit comments

Comments
 (0)