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,
50 DiagnosticConsumer &DiagConsumer);
51
52 /// Collect the module dependency in P1689 format for C++20 named modules.
53 ///
54 /// \param MakeformatOutput The output parameter for dependency information
55 /// in make format if the command line requires to generate make-format
56 /// dependency information by `-MD -MF <dep_file>`.
57 ///
58 /// \param MakeformatOutputPath The output parameter for the path to
59 /// \param MakeformatOutput.
60 ///
61 /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
62 /// P1689 dependency format rules otherwise.
63 std::optional<P1689Rule>
64 getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
65 std::string &MakeformatOutput,
66 std::string &MakeformatOutputPath,
67 DiagnosticConsumer &DiagConsumer);
68 std::optional<P1689Rule>
69 getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD,
70 DiagnosticConsumer &DiagConsumer) {
71 std::string MakeformatOutput;
72 std::string MakeformatOutputPath;
73
74 return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput,
75 MakeformatOutputPath, DiagConsumer);
76 }
77
78 /// Given a Clang driver command-line for a translation unit, gather the
79 /// modular dependencies and return the information needed for explicit build.
80 ///
81 /// \param AlreadySeen This stores modules which have previously been
82 /// reported. Use the same instance for all calls to this
83 /// function for a single \c DependencyScanningTool in a
84 /// single build. Use a different one for different tools,
85 /// and clear it between builds.
86 /// \param LookupModuleOutput This function is called to fill in
87 /// "-fmodule-file=", "-o" and other output
88 /// arguments for dependencies.
89 /// \param TUBuffer Optional memory buffer for translation unit input. If
90 /// TUBuffer is nullopt, the input should be included in the
91 /// Commandline already.
92 ///
93 /// \returns std::nullopt if errors occurred (reported to the DiagConsumer),
94 /// translation unit dependencies otherwise.
95 std::optional<dependencies::TranslationUnitDeps>
97 ArrayRef<std::string> CommandLine, StringRef CWD,
98 DiagnosticConsumer &DiagConsumer,
99 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
101 std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
102
103 /// Given a compilation context specified via the Clang driver command-line,
104 /// gather modular dependencies of module with the given name, and return the
105 /// information needed for explicit build.
106 /// TODO: this method should be removed as soon as Swift and our C-APIs adopt
107 /// CompilerInstanceWithContext. We are keeping it here so that it is easier
108 /// to coordinate with Swift and C-API changes.
110 StringRef ModuleName, ArrayRef<std::string> CommandLine, StringRef CWD,
111 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
113
114 llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
115
116private:
118
120};
121
122/// Run the dependency scanning worker for the given driver or frontend
123/// command-line, and report the discovered dependencies to the provided
124/// consumer.
125///
126/// OverlayFS should be based on the Worker's dependency scanning file-system
127/// and can be used to provide any input specified on the command-line as
128/// in-memory file. If no overlay file-system is provided, the Worker's
129/// dependency scanning file-system is used instead.
130///
131/// \returns false if any errors occurred (with diagnostics reported to
132/// \c DiagConsumer), true otherwise.
134 dependencies::DependencyScanningWorker &Worker, StringRef WorkingDirectory,
135 ArrayRef<std::string> CommandLine,
138 DiagnosticConsumer &DiagConsumer,
140
141class CompilerInstanceWithContext {
142 // Context
144 llvm::StringRef CWD;
145 std::vector<std::string> CommandLine;
146
147 // Context - Diagnostics engine.
148 DiagnosticConsumer *DiagConsumer = nullptr;
149 std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
150 DiagEngineWithCmdAndOpts;
151 std::unique_ptr<dependencies::TextDiagnosticsPrinterWithOutput>
152 DiagPrinterWithOS;
153
154 // Context - compiler invocation
155 std::unique_ptr<CompilerInvocation> OriginalInvocation;
156
157 // Context - output options
158 std::unique_ptr<DependencyOutputOptions> OutputOpts;
159
160 // Context - stable directory handling
162 dependencies::PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
163
164 // Compiler Instance
165 std::unique_ptr<CompilerInstance> CIPtr;
166
167 // Source location offset.
168 int32_t SrcLocOffset = 0;
169
170 CompilerInstanceWithContext(dependencies::DependencyScanningWorker &Worker,
171 StringRef CWD,
172 const std::vector<std::string> &CMD)
173 : Worker(Worker), CWD(CWD), CommandLine(CMD) {};
174
175 bool initialize(dependencies::DependencyActionController &Controller,
176 std::unique_ptr<dependencies::DiagnosticsEngineWithDiagOpts>
177 DiagEngineWithDiagOpts,
179
180public:
181 /// @brief Initialize the tool's compiler instance from the commandline.
182 /// The compiler instance only takes a `-cc1` job, so this method
183 /// builds the `-cc1` job from the CommandLine input.
184 /// @param Tool The dependency scanning tool whose compiler instance
185 /// with context is initialized.
186 /// @param CWD The current working directory.
187 /// @param CommandLine This command line may be a driver command or a cc1
188 /// command.
189 /// @param DC A diagnostics consumer to report error if the initialization
190 /// fails.
191 static std::optional<CompilerInstanceWithContext> initializeFromCommandline(
192 DependencyScanningTool &Tool, StringRef CWD,
193 ArrayRef<std::string> CommandLine,
196
197 /// @brief Initializing the context and the compiler instance.
198 /// This method must be called before calling
199 /// computeDependenciesByNameWithContext.
200 /// @param CWD The current working directory used during the scan.
201 /// @param CommandLine The commandline used for the scan.
202 /// @return Error if the initializaiton fails.
204 DependencyScanningTool &Tool, StringRef CWD,
205 ArrayRef<std::string> CommandLine,
207
208 bool
209 computeDependencies(StringRef ModuleName,
212
213 /// @brief Computes the dependeny for the module named ModuleName.
214 /// @param ModuleName The name of the module for which this method computes
215 ///. dependencies.
216 /// @param AlreadySeen This stores modules which have previously been
217 /// reported. Use the same instance for all calls to this
218 /// function for a single \c DependencyScanningTool in a
219 /// single build. Note that this parameter is not part of
220 /// the context because it can be shared across different
221 /// worker threads and each worker thread may update it.
222 /// @param LookupModuleOutput This function is called to fill in
223 /// "-fmodule-file=", "-o" and other output
224 /// arguments for dependencies.
225 /// @return An instance of \c TranslationUnitDeps if the scan is successful.
226 /// Otherwise it returns an error.
229 StringRef ModuleName,
230 const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
232
233 // MaxNumOfQueries is the upper limit of the number of names the by-name
234 // scanning API (computeDependencies) can support after a
235 // CompilerInstanceWithContext is initialized. At the time of this commit, the
236 // estimated number of total unique importable names is around 3000 from
237 // Apple's SDKs. We usually import them in parallel, so it is unlikely that
238 // all names are all scanned by the same dependency scanning worker. Therefore
239 // the 64k (20x bigger than our estimate) size is sufficient to hold the
240 // unique source locations to report diagnostics per worker.
241 static const int32_t MaxNumOfQueries = 1 << 16;
242};
243
244} // end namespace tooling
245} // end namespace clang
246
247#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::LookupModuleOutputCallback LookupModuleOutput)
Initializing the context and the compiler instance.
llvm::Expected< dependencies::TranslationUnitDeps > computeDependenciesByNameOrError(StringRef ModuleName, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::LookupModuleOutputCallback LookupModuleOutput)
Computes the dependeny for the module named ModuleName.
bool computeDependencies(StringRef ModuleName, dependencies::DependencyConsumer &Consumer, dependencies::DependencyActionController &Controller)
The high-level implementation of the dependency discovery tool that runs on an individual worker thre...
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 ...
std::optional< P1689Rule > getP1689ModuleDependencyFile(const CompileCommand &Command, StringRef CWD, DiagnosticConsumer &DiagConsumer)
llvm::Expected< dependencies::TranslationUnitDeps > getModuleDependencies(StringRef ModuleName, ArrayRef< std::string > CommandLine, StringRef CWD, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::LookupModuleOutputCallback LookupModuleOutput)
Given a compilation context specified via the Clang driver command-line, gather modular dependencies ...
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::vfs::FileSystem & getWorkerVFS() const
DependencyScanningTool(dependencies::DependencyScanningService &Service)
Construct a dependency scanning tool.
std::optional< std::string > getDependencyFile(ArrayRef< std::string > CommandLine, StringRef CWD, DiagnosticConsumer &DiagConsumer)
Print out the dependency information into a string using the dependency file format that is specified...
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