clang 17.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
20 : Worker(Service, std::move(FS)) {}
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 void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
38 // Same as `handleModuleDependency`.
39 }
40
41 void handleModuleDependency(ModuleDeps MD) override {
42 // These are ignored for the make format as it can't support the full
43 // set of deps, and handleFileDependency handles enough for implicitly
44 // built modules to work.
45 }
46
47 void handleContextHash(std::string Hash) override {}
48
49 void printDependencies(std::string &S) {
50 assert(Opts && "Handled dependency output options.");
51
52 class DependencyPrinter : public DependencyFileGenerator {
53 public:
54 DependencyPrinter(DependencyOutputOptions &Opts,
55 ArrayRef<std::string> Dependencies)
57 for (const auto &Dep : Dependencies)
58 addDependency(Dep);
59 }
60
61 void printDependencies(std::string &S) {
62 llvm::raw_string_ostream OS(S);
63 outputDependencyFile(OS);
64 }
65 };
66
67 DependencyPrinter Generator(*Opts, Dependencies);
68 Generator.printDependencies(S);
69 }
70
71protected:
72 std::unique_ptr<DependencyOutputOptions> Opts;
73 std::vector<std::string> Dependencies;
74};
75} // anonymous namespace
76
78 const std::vector<std::string> &CommandLine, StringRef CWD) {
79 MakeDependencyPrinterConsumer Consumer;
80 CallbackActionController Controller(nullptr);
81 auto Result =
82 Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
83 if (Result)
84 return std::move(Result);
85 std::string Output;
86 Consumer.printDependencies(Output);
87 return Output;
88}
89
91 const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,
92 std::string &MakeformatOutputPath) {
93 class P1689ModuleDependencyPrinterConsumer
94 : public MakeDependencyPrinterConsumer {
95 public:
96 P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
98 : Filename(Command.Filename), Rule(Rule) {
99 Rule.PrimaryOutput = Command.Output;
100 }
101
102 void handleProvidedAndRequiredStdCXXModules(
103 std::optional<P1689ModuleInfo> Provided,
104 std::vector<P1689ModuleInfo> Requires) override {
105 Rule.Provides = Provided;
106 if (Rule.Provides)
107 Rule.Provides->SourcePath = Filename.str();
108 Rule.Requires = Requires;
109 }
110
111 StringRef getMakeFormatDependencyOutputPath() {
112 if (Opts->OutputFormat != DependencyOutputFormat::Make)
113 return {};
114 return Opts->OutputFile;
115 }
116
117 private:
118 StringRef Filename;
119 P1689Rule &Rule;
120 };
121
122 class P1689ActionController : public DependencyActionController {
123 public:
124 // The lookupModuleOutput is for clang modules. P1689 format don't need it.
125 std::string lookupModuleOutput(const ModuleID &,
126 ModuleOutputKind Kind) override {
127 return "";
128 }
129 };
130
131 P1689Rule Rule;
132 P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
133 P1689ActionController Controller;
134 auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
135 Controller);
136 if (Result)
137 return std::move(Result);
138
139 MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
140 if (!MakeformatOutputPath.empty())
141 Consumer.printDependencies(MakeformatOutput);
142 return Rule;
143}
144
147 const std::vector<std::string> &CommandLine, StringRef CWD,
148 const llvm::StringSet<> &AlreadySeen,
149 LookupModuleOutputCallback LookupModuleOutput) {
150 FullDependencyConsumer Consumer(AlreadySeen);
151 CallbackActionController Controller(LookupModuleOutput);
152 llvm::Error Result =
153 Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
154 if (Result)
155 return std::move(Result);
156 return Consumer.takeTranslationUnitDeps();
157}
158
160 StringRef ModuleName, const std::vector<std::string> &CommandLine,
161 StringRef CWD, const llvm::StringSet<> &AlreadySeen,
162 LookupModuleOutputCallback LookupModuleOutput) {
163 FullDependencyConsumer Consumer(AlreadySeen);
164 CallbackActionController Controller(LookupModuleOutput);
165 llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
166 Controller, ModuleName);
167 if (Result)
168 return std::move(Result);
169 return Consumer.takeModuleGraphDeps();
170}
171
174
175 TU.ID.ContextHash = std::move(ContextHash);
176 TU.FileDeps = std::move(Dependencies);
177 TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
178 TU.Commands = std::move(Commands);
179
180 for (auto &&M : ClangModuleDeps) {
181 auto &MD = M.second;
182 if (MD.ImportedByMainFile)
183 TU.ClangModuleDeps.push_back(MD.ID);
184 // TODO: Avoid handleModuleDependency even being called for modules
185 // we've already seen.
186 if (AlreadySeen.count(M.first))
187 continue;
188 TU.ModuleGraph.push_back(std::move(MD));
189 }
190
191 return TU;
192}
193
195 ModuleDepsGraph ModuleGraph;
196
197 for (auto &&M : ClangModuleDeps) {
198 auto &MD = M.second;
199 // TODO: Avoid handleModuleDependency even being called for modules
200 // we've already seen.
201 if (AlreadySeen.count(M.first))
202 continue;
203 ModuleGraph.push_back(std::move(MD));
204 }
205
206 return ModuleGraph;
207}
208
StringRef Filename
Definition: Format.cpp:2774
llvm::raw_ostream & OS
Definition: Logger.cpp:24
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
Definition: Utils.h:102
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::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< TranslationUnitDeps > getTranslationUnitDependencies(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::StringSet<> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput)
Given a Clang driver command-line for a translation unit, gather the modular dependencies and return ...
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::Expected< ModuleDepsGraph > getModuleDependencies(StringRef ModuleName, const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::StringSet<> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput)
Given a compilation context specified via the Clang driver command-line, gather modular dependencies ...
DependencyScanningTool(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=llvm::vfs::createPhysicalFileSystem())
Construct a dependency scanning tool.
bool computeDependencies(StringRef WorkingDirectory, const std::vector< std::string > &CommandLine, DependencyConsumer &DepConsumer, DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, std::optional< StringRef > ModuleName=std::nullopt)
Run the dependency scanning tool for a given clang driver command-line, and report the discovered dep...
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 ModuleID &, ModuleOutputKind)> LookupModuleOutputCallback
A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
std::shared_ptr< MatchComputation< T > > Generator
Definition: RewriteRule.h:65
@ Result
The result type of a method or function.
Definition: Format.h:4664
Specifies the working directory and command of a compilation.
A command-line tool invocation that is part of building a TU.
This is used to identify a specific module.
std::string ContextHash
The context hash of a module represents the compiler options that affect the resulting command-line i...
std::vector< P1689ModuleInfo > Requires
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< 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,...
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.