clang 22.0.0git
DependencyScanningTool.h
Go to the documentation of this file.
1//===- DependencyScanningTool.h - clang-scan-deps service -----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
10#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
11
16#include "llvm/ADT/DenseSet.h"
17#include "llvm/ADT/MapVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include <functional>
20#include <optional>
21#include <string>
22#include <vector>
23
24namespace clang {
25namespace tooling {
26namespace dependencies {
27
28/// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
30 llvm::function_ref<std::string(const ModuleDeps &, ModuleOutputKind)>;
31
32/// Graph of modular dependencies.
33using ModuleDepsGraph = std::vector<ModuleDeps>;
34
35/// The full dependencies and module graph for a specific input.
37 /// The graph of direct and transitive modular dependencies.
39
40 /// The identifier of the C++20 module this translation unit exports.
41 ///
42 /// If the translation unit is not a module then \c ID.ModuleName is empty.
44
45 /// A collection of absolute paths to files that this translation unit
46 /// directly depends on, not including transitive dependencies.
47 std::vector<std::string> FileDeps;
48
49 /// A collection of prebuilt modules this translation unit directly depends
50 /// on, not including transitive dependencies.
51 std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
52
53 /// A list of modules this translation unit directly depends on, not including
54 /// transitive dependencies.
55 ///
56 /// This may include modules with a different context hash when it can be
57 /// determined that the differences are benign for this compilation.
58 std::vector<ModuleID> ClangModuleDeps;
59
60 /// A list of module names that are visible to this translation unit. This
61 /// includes both direct and transitive module dependencies.
62 std::vector<std::string> VisibleModules;
63
64 /// A list of the C++20 named modules this translation unit depends on.
65 std::vector<std::string> NamedModuleDeps;
66
67 /// The sequence of commands required to build the translation unit. Commands
68 /// should be executed in order.
69 ///
70 /// FIXME: If we add support for multi-arch builds in clang-scan-deps, we
71 /// should make the dependencies between commands explicit to enable parallel
72 /// builds of each architecture.
73 std::vector<Command> Commands;
74
75 /// Deprecated driver command-line. This will be removed in a future version.
76 std::vector<std::string> DriverCommandLine;
77};
78
79struct P1689Rule {
80 std::string PrimaryOutput;
81 std::optional<P1689ModuleInfo> Provides;
82 std::vector<P1689ModuleInfo> Requires;
83};
84
85/// The high-level implementation of the dependency discovery tool that runs on
86/// an individual worker thread.
88public:
89 /// Construct a dependency scanning tool.
90 ///
91 /// @param Service The parent service. Must outlive the tool.
92 /// @param FS The filesystem for the tool to use. Defaults to the physical FS.
95 llvm::vfs::createPhysicalFileSystem());
96
97 /// Print out the dependency information into a string using the dependency
98 /// file format that is specified in the options (-MD is the default) and
99 /// return it.
100 ///
101 /// \returns A \c StringError with the diagnostic output if clang errors
102 /// occurred, dependency file contents otherwise.
104 getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD);
105
106 /// Collect the module dependency in P1689 format for C++20 named modules.
107 ///
108 /// \param MakeformatOutput The output parameter for dependency information
109 /// in make format if the command line requires to generate make-format
110 /// dependency information by `-MD -MF <dep_file>`.
111 ///
112 /// \param MakeformatOutputPath The output parameter for the path to
113 /// \param MakeformatOutput.
114 ///
115 /// \returns A \c StringError with the diagnostic output if clang errors
116 /// occurred, P1689 dependency format rules otherwise.
119 StringRef CWD, std::string &MakeformatOutput,
120 std::string &MakeformatOutputPath);
123 StringRef CWD) {
124 std::string MakeformatOutput;
125 std::string MakeformatOutputPath;
126
127 return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput,
128 MakeformatOutputPath);
129 }
130
131 /// Given a Clang driver command-line for a translation unit, gather the
132 /// modular dependencies and return the information needed for explicit build.
133 ///
134 /// \param AlreadySeen This stores modules which have previously been
135 /// reported. Use the same instance for all calls to this
136 /// function for a single \c DependencyScanningTool in a
137 /// single build. Use a different one for different tools,
138 /// and clear it between builds.
139 /// \param LookupModuleOutput This function is called to fill in
140 /// "-fmodule-file=", "-o" and other output
141 /// arguments for dependencies.
142 /// \param TUBuffer Optional memory buffer for translation unit input. If
143 /// TUBuffer is nullopt, the input should be included in the
144 /// Commandline already.
145 ///
146 /// \returns a \c StringError with the diagnostic output if clang errors
147 /// occurred, \c TranslationUnitDeps otherwise.
149 const std::vector<std::string> &CommandLine, StringRef CWD,
150 const llvm::DenseSet<ModuleID> &AlreadySeen,
151 LookupModuleOutputCallback LookupModuleOutput,
152 std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
153
154 /// Given a compilation context specified via the Clang driver command-line,
155 /// gather modular dependencies of module with the given name, and return the
156 /// information needed for explicit build.
157 /// TODO: this method should be removed as soon as Swift and our C-APIs adopt
158 /// CompilerInstanceWithContext. We are keeping it here so that it is easier
159 /// to coordinate with Swift and C-API changes.
161 StringRef ModuleName, const std::vector<std::string> &CommandLine,
162 StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
163 LookupModuleOutputCallback LookupModuleOutput);
164
165 /// The following three methods provide a new interface to perform
166 /// by name dependency scan. The new interface's intention is to improve
167 /// dependency scanning performance when a sequence of name is looked up
168 /// with the same current working directory and the command line.
169
170 /// @brief Initializing the context and the compiler instance.
171 /// This method must be called before calling
172 /// computeDependenciesByNameWithContext.
173 /// @param CWD The current working directory used during the scan.
174 /// @param CommandLine The commandline used for the scan.
175 /// @return Error if the initializaiton fails.
177 StringRef CWD, const std::vector<std::string> &CommandLine);
178
179 /// @brief Computes the dependeny for the module named ModuleName.
180 /// @param ModuleName The name of the module for which this method computes
181 ///. dependencies.
182 /// @param AlreadySeen This stores modules which have previously been
183 /// reported. Use the same instance for all calls to this
184 /// function for a single \c DependencyScanningTool in a
185 /// single build. Note that this parameter is not part of
186 /// the context because it can be shared across different
187 /// worker threads and each worker thread may update it.
188 /// @param LookupModuleOutput This function is called to fill in
189 /// "-fmodule-file=", "-o" and other output
190 /// arguments for dependencies.
191 /// @return An instance of \c TranslationUnitDeps if the scan is successful.
192 /// Otherwise it returns an error.
194 StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,
195 LookupModuleOutputCallback LookupModuleOutput);
196
197 /// @brief This method finializes the compiler instance. It finalizes the
198 /// diagnostics and deletes the compiler instance. Call this method
199 /// once all names for a same commandline are scanned.
200 /// @return Error if an error occured during finalization.
202
203 llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
204
205private:
207};
208
210public:
211 FullDependencyConsumer(const llvm::DenseSet<ModuleID> &AlreadySeen)
212 : AlreadySeen(AlreadySeen) {}
213
214 void handleBuildCommand(Command Cmd) override {
215 Commands.push_back(std::move(Cmd));
216 }
217
219
220 void handleFileDependency(StringRef File) override {
221 Dependencies.push_back(std::string(File));
222 }
223
225 PrebuiltModuleDeps.emplace_back(std::move(PMD));
226 }
227
229 ClangModuleDeps[MD.ID] = std::move(MD);
230 }
231
233 DirectModuleDeps.push_back(ID);
234 }
235
236 void handleVisibleModule(std::string ModuleName) override {
237 VisibleModules.push_back(ModuleName);
238 }
239
240 void handleContextHash(std::string Hash) override {
241 ContextHash = std::move(Hash);
242 }
243
245 std::optional<P1689ModuleInfo> Provided,
246 std::vector<P1689ModuleInfo> Requires) override {
247 ModuleName = Provided ? Provided->ModuleName : "";
248 llvm::transform(Requires, std::back_inserter(NamedModuleDeps),
249 [](const auto &Module) { return Module.ModuleName; });
250 }
251
253
254private:
255 std::vector<std::string> Dependencies;
256 std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
257 llvm::MapVector<ModuleID, ModuleDeps> ClangModuleDeps;
258 std::string ModuleName;
259 std::vector<std::string> NamedModuleDeps;
260 std::vector<ModuleID> DirectModuleDeps;
261 std::vector<std::string> VisibleModules;
262 std::vector<Command> Commands;
263 std::string ContextHash;
264 const llvm::DenseSet<ModuleID> &AlreadySeen;
265};
266
267/// A simple dependency action controller that uses a callback. If no callback
268/// is provided, it is assumed that looking up module outputs is unreachable.
270public:
272
273 static std::string lookupUnreachableModuleOutput(const ModuleDeps &MD,
274 ModuleOutputKind Kind) {
275 llvm::report_fatal_error("unexpected call to lookupModuleOutput");
276 };
277
279 : LookupModuleOutput(std::move(LMO)) {
280 if (!LookupModuleOutput) {
281 LookupModuleOutput = lookupUnreachableModuleOutput;
282 }
283 }
284
285 std::string lookupModuleOutput(const ModuleDeps &MD,
286 ModuleOutputKind Kind) override {
287 return LookupModuleOutput(MD, Kind);
288 }
289
290private:
291 LookupModuleOutputCallback LookupModuleOutput;
292};
293
294} // end namespace dependencies
295} // end namespace tooling
296} // end namespace clang
297
298#endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
Describes a module or submodule.
Definition Module.h:144
static std::string lookupUnreachableModuleOutput(const ModuleDeps &MD, ModuleOutputKind Kind)
std::string lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind Kind) override
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
The dependency scanning service contains shared configuration and state that is used by the individua...
llvm::Expected< TranslationUnitDeps > getTranslationUnitDependencies(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::DenseSet< ModuleID > &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput, std::optional< llvm::MemoryBufferRef > TUBuffer=std::nullopt)
Given a Clang driver command-line for a translation unit, gather the modular dependencies and return ...
llvm::Expected< P1689Rule > getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput, std::string &MakeformatOutputPath)
Collect the module dependency in P1689 format for C++20 named modules.
llvm::Expected< std::string > getDependencyFile(const std::vector< std::string > &CommandLine, StringRef CWD)
Print out the dependency information into a string using the dependency file format that is specified...
llvm::Error finalizeCompilerInstanceWithContext()
This method finializes the compiler instance.
llvm::Expected< TranslationUnitDeps > getModuleDependencies(StringRef ModuleName, const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::DenseSet< ModuleID > &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput)
Given a compilation context specified via the Clang driver command-line, gather modular dependencies ...
llvm::Error initializeCompilerInstanceWithContext(StringRef CWD, const std::vector< std::string > &CommandLine)
The following three methods provide a new interface to perform by name dependency scan.
llvm::Expected< TranslationUnitDeps > computeDependenciesByNameWithContext(StringRef ModuleName, const llvm::DenseSet< ModuleID > &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput)
Computes the dependeny for the module named ModuleName.
DependencyScanningTool(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=llvm::vfs::createPhysicalFileSystem())
Construct a dependency scanning tool.
llvm::Expected< P1689Rule > getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, StringRef CWD)
An individual dependency scanning worker that is able to run on its own thread.
void handleVisibleModule(std::string ModuleName) override
void handleProvidedAndRequiredStdCXXModules(std::optional< P1689ModuleInfo > Provided, std::vector< P1689ModuleInfo > Requires) override
FullDependencyConsumer(const llvm::DenseSet< ModuleID > &AlreadySeen)
void handleDependencyOutputOpts(const DependencyOutputOptions &) override
void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
std::vector< ModuleDeps > ModuleDepsGraph
Graph of modular dependencies.
llvm::function_ref< std::string(const ModuleDeps &, ModuleOutputKind)> LookupModuleOutputCallback
A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
The JSON file list parser is used to communicate input to InstallAPI.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
Specifies the working directory and command of a compilation.
A command-line tool invocation that is part of building a TU.
ModuleID ID
The identifier of the module.
This is used to identify a specific module.
std::optional< P1689ModuleInfo > Provides
Modular dependency that has already been built prior to the dependency scan.
The full dependencies and module graph for a specific input.
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modules this translation unit directly depends on, not including transitive ...
std::vector< std::string > VisibleModules
A list of module names that are visible to this translation unit.
std::vector< Command > Commands
The sequence of commands required to build the translation unit.
std::vector< std::string > FileDeps
A collection of absolute paths to files that this translation unit directly depends on,...
std::vector< std::string > NamedModuleDeps
A list of the C++20 named modules this translation unit depends on.
ModuleDepsGraph ModuleGraph
The graph of direct and transitive modular dependencies.
ModuleID ID
The identifier of the C++20 module this translation unit exports.
std::vector< ModuleID > ClangModuleDeps
A list of modules this translation unit directly depends on, not including transitive dependencies.
std::vector< std::string > DriverCommandLine
Deprecated driver command-line. This will be removed in a future version.