clang 22.0.0git
DependencyScanningTool.cpp
Go to the documentation of this file.
1//===- DependencyScanningTool.cpp - 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
11#include <optional>
12
13using namespace clang;
14using namespace tooling;
15using namespace dependencies;
16
21
22namespace {
23/// Prints out all of the gathered dependencies into a string.
24class MakeDependencyPrinterConsumer : public DependencyConsumer {
25public:
26 void handleBuildCommand(Command) override {}
27
28 void
29 handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
30 this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
31 }
32
33 void handleFileDependency(StringRef File) override {
34 Dependencies.push_back(std::string(File));
35 }
36
37 // These are ignored for the make format as it can't support the full
38 // set of deps, and handleFileDependency handles enough for implicitly
39 // built modules to work.
40 void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}
41 void handleModuleDependency(ModuleDeps MD) override {}
42 void handleDirectModuleDependency(ModuleID ID) override {}
43 void handleVisibleModule(std::string ModuleName) override {}
44 void handleContextHash(std::string Hash) override {}
45
46 void printDependencies(std::string &S) {
47 assert(Opts && "Handled dependency output options.");
48
49 class DependencyPrinter : public DependencyFileGenerator {
50 public:
51 DependencyPrinter(DependencyOutputOptions &Opts,
52 ArrayRef<std::string> Dependencies)
53 : DependencyFileGenerator(Opts) {
54 for (const auto &Dep : Dependencies)
55 addDependency(Dep);
56 }
57
58 void printDependencies(std::string &S) {
59 llvm::raw_string_ostream OS(S);
60 outputDependencyFile(OS);
61 }
62 };
63
64 DependencyPrinter Generator(*Opts, Dependencies);
65 Generator.printDependencies(S);
66 }
67
68protected:
69 std::unique_ptr<DependencyOutputOptions> Opts;
70 std::vector<std::string> Dependencies;
71};
72} // anonymous namespace
73
76 StringRef CWD) {
77 MakeDependencyPrinterConsumer Consumer;
78 CallbackActionController Controller(nullptr);
79 auto Result =
80 Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
81 if (Result)
82 return std::move(Result);
83 std::string Output;
84 Consumer.printDependencies(Output);
85 return Output;
86}
87
89 const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,
90 std::string &MakeformatOutputPath) {
91 class P1689ModuleDependencyPrinterConsumer
92 : public MakeDependencyPrinterConsumer {
93 public:
94 P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
96 : Filename(Command.Filename), Rule(Rule) {
97 Rule.PrimaryOutput = Command.Output;
98 }
99
100 void handleProvidedAndRequiredStdCXXModules(
101 std::optional<P1689ModuleInfo> Provided,
102 std::vector<P1689ModuleInfo> Requires) override {
103 Rule.Provides = Provided;
104 if (Rule.Provides)
105 Rule.Provides->SourcePath = Filename.str();
106 Rule.Requires = Requires;
107 }
108
109 StringRef getMakeFormatDependencyOutputPath() {
110 if (Opts->OutputFormat != DependencyOutputFormat::Make)
111 return {};
112 return Opts->OutputFile;
113 }
114
115 private:
116 StringRef Filename;
117 P1689Rule &Rule;
118 };
119
120 class P1689ActionController : public DependencyActionController {
121 public:
122 // The lookupModuleOutput is for clang modules. P1689 format don't need it.
123 std::string lookupModuleOutput(const ModuleDeps &,
124 ModuleOutputKind Kind) override {
125 return "";
126 }
127 };
128
129 P1689Rule Rule;
130 P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
131 P1689ActionController Controller;
132 auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
133 Controller);
134 if (Result)
135 return std::move(Result);
136
137 MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
138 if (!MakeformatOutputPath.empty())
139 Consumer.printDependencies(MakeformatOutput);
140 return Rule;
141}
142
145 ArrayRef<std::string> CommandLine, StringRef CWD,
146 const llvm::DenseSet<ModuleID> &AlreadySeen,
147 LookupModuleOutputCallback LookupModuleOutput,
148 std::optional<llvm::MemoryBufferRef> TUBuffer) {
149 FullDependencyConsumer Consumer(AlreadySeen);
150 CallbackActionController Controller(LookupModuleOutput);
151 llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
152 Controller, TUBuffer);
153
154 if (Result)
155 return std::move(Result);
156 return Consumer.takeTranslationUnitDeps();
157}
158
161 StringRef ModuleName, ArrayRef<std::string> CommandLine, StringRef CWD,
162 const llvm::DenseSet<ModuleID> &AlreadySeen,
163 LookupModuleOutputCallback LookupModuleOutput) {
164 FullDependencyConsumer Consumer(AlreadySeen);
165 CallbackActionController Controller(LookupModuleOutput);
166 if (auto Error =
167 Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine))
168 return std::move(Error);
169
170 auto Result = Worker.computeDependenciesByNameWithContextOrError(
171 ModuleName, Consumer, Controller);
172
173 if (auto Error = Worker.finalizeCompilerInstanceWithContextOrError())
174 return std::move(Error);
175
176 if (Result)
177 return std::move(Result);
178
179 return Consumer.takeTranslationUnitDeps();
180}
181
183 StringRef CWD, ArrayRef<std::string> CommandLine) {
184 return Worker.initializeCompilerInstanceWithContextOrError(CWD, CommandLine);
185}
186
189 StringRef ModuleName, const llvm::DenseSet<ModuleID> &AlreadySeen,
190 LookupModuleOutputCallback LookupModuleOutput) {
191 FullDependencyConsumer Consumer(AlreadySeen);
192 CallbackActionController Controller(LookupModuleOutput);
193 llvm::Error Result = Worker.computeDependenciesByNameWithContextOrError(
194 ModuleName, Consumer, Controller);
195 if (Result)
196 return std::move(Result);
197
198 return Consumer.takeTranslationUnitDeps();
199}
200
202 return Worker.finalizeCompilerInstanceWithContextOrError();
203}
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
A simple dependency action controller that uses a callback.
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::Error initializeCompilerInstanceWithContext(StringRef CWD, ArrayRef< std::string > CommandLine)
The following three methods provide a new interface to perform by name dependency scan.
DependencyScanningTool(dependencies::DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=llvm::vfs::createPhysicalFileSystem())
Construct a dependency scanning tool.
llvm::Expected< dependencies::TranslationUnitDeps > getTranslationUnitDependencies(ArrayRef< std::string > CommandLine, StringRef CWD, 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::Error finalizeCompilerInstanceWithContext()
This method finializes the compiler instance.
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 ...
llvm::Expected< dependencies::TranslationUnitDeps > computeDependenciesByNameWithContext(StringRef ModuleName, const llvm::DenseSet< dependencies::ModuleID > &AlreadySeen, dependencies::LookupModuleOutputCallback LookupModuleOutput)
Computes the dependeny for the module named ModuleName.
llvm::Expected< P1689Rule > getP1689ModuleDependencyFile(const 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(ArrayRef< std::string > CommandLine, StringRef CWD)
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.
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::shared_ptr< MatchComputation< T > > Generator
Definition RewriteRule.h:65
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
A command-line tool invocation that is part of building a TU.
Specifies the working directory and command of a compilation.