clang 23.0.0git
DependencyScanningTool.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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_DEPENDENCYSCANNINGTOOL_H
10#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNINGTOOL_H
11
18#include "llvm/ADT/DenseSet.h"
19#include <optional>
20#include <string>
21#include <vector>
22
23namespace clang {
24namespace tooling {
25
26struct P1689Rule {
27 std::string PrimaryOutput;
28 std::optional<dependencies::P1689ModuleInfo> Provides;
29 std::vector<dependencies::P1689ModuleInfo> Requires;
30};
31
32/// The high-level implementation of the dependency discovery tool that runs on
33/// an individual worker thread.
35public:
36 /// Construct a dependency scanning tool.
37 ///
38 /// @param Service The parent service. Must outlive the tool.
41
42 /// Print out the dependency information into a string using the dependency
43 /// file format that is specified in the options (-MD is the default) and
44 /// return it.
45 ///
46 /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
47 /// dependency file contents otherwise.
48 std::optional<std::string>
49 getDependencyFile(ArrayRef<std::string> CommandLine, StringRef CWD,
51 DiagnosticConsumer &DiagConsumer);
52
53 /// Collect the module dependency in P1689 format for C++20 named modules.
54 ///
55 /// \param MakeformatOutput The output parameter for dependency information
56 /// in make format if the command line requires to generate make-format
57 /// dependency information by `-MD -MF <dep_file>`.
58 ///
59 /// \param MakeformatOutputPath The output parameter for the path to
60 /// \param MakeformatOutput.
61 ///
62 /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
63 /// P1689 dependency format rules otherwise.
64 std::optional<P1689Rule>
65 getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
66 std::string &MakeformatOutput,
67 std::string &MakeformatOutputPath,
68 DiagnosticConsumer &DiagConsumer);
69 std::optional<P1689Rule>
70 getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
71 DiagnosticConsumer &DiagConsumer) {
72 std::string MakeformatOutput;
73 std::string MakeformatOutputPath;
74
75 return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput,
76 MakeformatOutputPath, DiagConsumer);
77 }
78
79 /// Given a Clang driver command-line for a translation unit, gather the
80 /// modular dependencies and return the information needed for explicit build.
81 ///
82 /// \param AlreadySeen This stores modules which have previously been
83 /// reported. Use the same instance for all calls to this
84 /// function for a single \c DependencyScanningTool in a
85 /// single build. Use a different one for different tools,
86 /// and clear it between builds.
87 /// \param LookupModuleOutput This function is called to fill in
88 /// "-fmodule-file=", "-o" and other output
89 /// arguments for dependencies.
90 /// \param TUBuffer Optional memory buffer for translation unit input. If
91 /// TUBuffer is nullopt, the input should be included in the
92 /// Commandline already.
93 ///
94 /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
95 /// translation unit dependencies otherwise.
96 std::optional<dependencies::TranslationUnitDeps>
98 ArrayRef<std::string> CommandLine, StringRef CWD,
99 DiagnosticConsumer &DiagConsumer,
100 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
102 std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
103
104 /// Given a compilation context specified via the Clang driver command-line,
105 /// gather modular dependencies of module with the given name, and return the
106 /// information needed for explicit build.
107 /// TODO: this method should be removed as soon as Swift and our C-APIs adopt
108 /// CompilerInstanceWithContext. We are keeping it here so that it is easier
109 /// to coordinate with Swift and C-API changes.
111 StringRef ModuleName, ArrayRef<std::string> CommandLine, StringRef CWD,
112 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
114
115 /// Returns the worker tracing VFS, if it was requested via the service.
116 llvm::vfs::TracingFileSystem *getWorkerTracingVFS() const {
117 return Worker.getTracingVFS();
118 }
119
120private:
122
124};
125
126/// Run the dependency scanning worker for the given driver or frontend
127/// command-line, and report the discovered dependencies to the provided
128/// consumer.
129///
130/// OverlayFS should be based on the Worker's dependency scanning file-system
131/// and can be used to provide any input specified on the command-line as
132/// in-memory file. If no overlay file-system is provided, the Worker's
133/// dependency scanning file-system is used instead.
134///
135/// \returns false if any errors occurred (with diagnostics reported to
136/// \c DiagConsumer), true otherwise.
138 dependencies::DependencyScanningWorker &Worker, StringRef WorkingDirectory,
139 ArrayRef<std::string> CommandLine,
142 DiagnosticConsumer &DiagConsumer,
144
145class CompilerInstanceWithContext {
146 // Context
148 llvm::StringRef CWD;
149 std::vector<std::string> CommandLine;
150
151 // Context - Diagnostics engine.
152 DiagnosticConsumer *DiagConsumer = nullptr;
153 std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
154 DiagEngineWithCmdAndOpts;
155 std::unique_ptr<dependencies::TextDiagnosticsPrinterWithOutput>
156 DiagPrinterWithOS;
157
158 // Context - compiler invocation
159 std::unique_ptr<CompilerInvocation> OriginalInvocation;
160
161 // Context - output options
162 std::unique_ptr<DependencyOutputOptions> OutputOpts;
163
164 // Context - stable directory handling
166 dependencies::PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
167
168 // Compiler Instance
169 std::unique_ptr<CompilerInstance> CIPtr;
170
171 // Source location offset.
172 int32_t SrcLocOffset = 0;
173
174 CompilerInstanceWithContext(dependencies::DependencyScanningWorker &Worker,
175 StringRef CWD,
176 const std::vector<std::string> &CMD)
177 : Worker(Worker), CWD(CWD), CommandLine(CMD) {};
178
179 bool initialize(dependencies::DependencyActionController &Controller,
180 std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
181 DiagEngineWithDiagOpts,
183
184public:
185 /// @brief Initialize the tool's compiler instance from the commandline.
186 /// The compiler instance only takes a `-cc1` job, so this method
187 /// builds the `-cc1` job from the CommandLine input.
188 /// @param Tool The dependency scanning tool whose compiler instance
189 /// with context is initialized.
190 /// @param CWD The current working directory.
191 /// @param CommandLine This command line may be a driver command or a cc1
192 /// command.
193 /// @param DC A diagnostics consumer to report error if the initialization
194 /// fails.
195 static std::optional<CompilerInstanceWithContext> initializeFromCommandline(
196 DependencyScanningTool &Tool, StringRef CWD,
197 ArrayRef<std::string> CommandLine,
200
201 /// @brief Initializing the context and the compiler instance.
202 /// This method must be called before calling
203 /// computeDependenciesByNameWithContext.
204 /// @param CWD The current working directory used during the scan.
205 /// @param CommandLine The commandline used for the scan.
206 /// @return Error if the initializaiton fails.
208 initializeOrError(DependencyScanningTool &Tool, StringRef CWD,
209 ArrayRef<std::string> CommandLine,
211
212 bool
213 computeDependencies(StringRef ModuleName,
216
217 /// @brief Computes the dependeny for the module named ModuleName.
218 /// @param ModuleName The name of the module for which this method computes
219 ///. dependencies.
220 /// @param AlreadySeen This stores modules which have previously been
221 /// reported. Use the same instance for all calls to this
222 /// function for a single \c DependencyScanningTool in a
223 /// single build. Note that this parameter is not part of
224 /// the context because it can be shared across different
225 /// worker threads and each worker thread may update it.
226 /// @param LookupModuleOutput This function is called to fill in
227 /// "-fmodule-file=", "-o" and other output
228 /// arguments for dependencies.
229 /// @return An instance of \c TranslationUnitDeps if the scan is successful.
230 /// Otherwise it returns an error.
233 StringRef ModuleName,
234 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
236
237 // MaxNumOfQueries is the upper limit of the number of names the by-name
238 // scanning API (computeDependencies) can support after a
239 // CompilerInstanceWithContext is initialized. At the time of this commit, the
240 // estimated number of total unique importable names is around 3000 from
241 // Apple's SDKs. We usually import them in parallel, so it is unlikely that
242 // all names are all scanned by the same dependency scanning worker. Therefore
243 // the 64k (20x bigger than our estimate) size is sufficient to hold the
244 // unique source locations to report diagnostics per worker.
245 static const int32_t MaxNumOfQueries = 1 << 16;
246};
247
248} // end namespace tooling
249} // end namespace clang
250
251#endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNINGTOOL_H
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
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...
An individual dependency scanning worker that is able to run on its own thread.
static std::optional< CompilerInstanceWithContext > initializeFromCommandline(DependencyScanningTool &Tool, StringRef CWD, ArrayRef< std::string > CommandLine, dependencies::DependencyActionController &Controller, DiagnosticConsumer &DC)
Initialize the tool's compiler instance from the commandline.
static llvm::Expected< CompilerInstanceWithContext > initializeOrError(DependencyScanningTool &Tool, StringRef CWD, ArrayRef< std::string > CommandLine, dependencies::DependencyActionController &Controller)
Initializing the context and the compiler instance.
bool computeDependencies(StringRef ModuleName, dependencies::DependencyConsumer &Consumer, dependencies::DependencyActionController &Controller)
llvm::Expected< dependencies::TranslationUnitDeps > computeDependenciesByNameOrError(StringRef ModuleName, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::DependencyActionController &Controller)
Computes the dependeny for the module named ModuleName.
The high-level implementation of the dependency discovery tool that runs on an individual worker thre...
std::optional< std::string > getDependencyFile(ArrayRef< std::string > CommandLine, StringRef CWD, dependencies::LookupModuleOutputCallback LookupModuleOutput, DiagnosticConsumer &DiagConsumer)
Print out the dependency information into a string using the dependency file format that is specified...
std::optional< dependencies::TranslationUnitDeps > getTranslationUnitDependencies(ArrayRef< std::string > CommandLine, StringRef CWD, DiagnosticConsumer &DiagConsumer, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::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::vfs::TracingFileSystem * getWorkerTracingVFS() const
Returns the worker tracing VFS, if it was requested via the service.
std::optional< P1689Rule > getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD, DiagnosticConsumer &DiagConsumer)
std::optional< P1689Rule > getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput, std::string &MakeformatOutputPath, DiagnosticConsumer &DiagConsumer)
Collect the module dependency in P1689 format for C++20 named modules.
llvm::Expected< dependencies::TranslationUnitDeps > getModuleDependencies(StringRef ModuleName, ArrayRef< std::string > CommandLine, StringRef CWD, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::DependencyActionController &Controller)
Given a compilation context specified via the Clang driver command-line, gather modular dependencies ...
DependencyScanningTool(dependencies::DependencyScanningService &Service)
Construct a dependency scanning tool.
llvm::function_ref< std::string(const ModuleDeps &, ModuleOutputKind)> LookupModuleOutputCallback
A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
llvm::StringMap< PrebuiltModuleASTAttrs > PrebuiltModulesAttrsMap
Attributes loaded from AST files of prebuilt modules collected prior to ModuleDepCollector creation.
bool computeDependencies(dependencies::DependencyScanningWorker &Worker, StringRef WorkingDirectory, ArrayRef< std::string > CommandLine, dependencies::DependencyConsumer &Consumer, dependencies::DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, llvm::IntrusiveRefCntPtr< llvm::vfs::OverlayFileSystem > OverlayFS=nullptr)
Run the dependency scanning worker for the given driver or frontend command-line, and report the disc...
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.
std::vector< dependencies::P1689ModuleInfo > Requires
std::optional< dependencies::P1689ModuleInfo > Provides