Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp
35294 views
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
9
#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"
10
#include "clang/Frontend/Utils.h"
11
#include <optional>
12
13
using namespace clang;
14
using namespace tooling;
15
using namespace dependencies;
16
17
DependencyScanningTool::DependencyScanningTool(
18
DependencyScanningService &Service,
19
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
20
: Worker(Service, std::move(FS)) {}
21
22
namespace {
23
/// Prints out all of the gathered dependencies into a string.
24
class MakeDependencyPrinterConsumer : public DependencyConsumer {
25
public:
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 handleContextHash(std::string Hash) override {}
44
45
void printDependencies(std::string &S) {
46
assert(Opts && "Handled dependency output options.");
47
48
class DependencyPrinter : public DependencyFileGenerator {
49
public:
50
DependencyPrinter(DependencyOutputOptions &Opts,
51
ArrayRef<std::string> Dependencies)
52
: DependencyFileGenerator(Opts) {
53
for (const auto &Dep : Dependencies)
54
addDependency(Dep);
55
}
56
57
void printDependencies(std::string &S) {
58
llvm::raw_string_ostream OS(S);
59
outputDependencyFile(OS);
60
}
61
};
62
63
DependencyPrinter Generator(*Opts, Dependencies);
64
Generator.printDependencies(S);
65
}
66
67
protected:
68
std::unique_ptr<DependencyOutputOptions> Opts;
69
std::vector<std::string> Dependencies;
70
};
71
} // anonymous namespace
72
73
llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
74
const std::vector<std::string> &CommandLine, StringRef CWD) {
75
MakeDependencyPrinterConsumer Consumer;
76
CallbackActionController Controller(nullptr);
77
auto Result =
78
Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
79
if (Result)
80
return std::move(Result);
81
std::string Output;
82
Consumer.printDependencies(Output);
83
return Output;
84
}
85
86
llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
87
const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,
88
std::string &MakeformatOutputPath) {
89
class P1689ModuleDependencyPrinterConsumer
90
: public MakeDependencyPrinterConsumer {
91
public:
92
P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
93
const CompileCommand &Command)
94
: Filename(Command.Filename), Rule(Rule) {
95
Rule.PrimaryOutput = Command.Output;
96
}
97
98
void handleProvidedAndRequiredStdCXXModules(
99
std::optional<P1689ModuleInfo> Provided,
100
std::vector<P1689ModuleInfo> Requires) override {
101
Rule.Provides = Provided;
102
if (Rule.Provides)
103
Rule.Provides->SourcePath = Filename.str();
104
Rule.Requires = Requires;
105
}
106
107
StringRef getMakeFormatDependencyOutputPath() {
108
if (Opts->OutputFormat != DependencyOutputFormat::Make)
109
return {};
110
return Opts->OutputFile;
111
}
112
113
private:
114
StringRef Filename;
115
P1689Rule &Rule;
116
};
117
118
class P1689ActionController : public DependencyActionController {
119
public:
120
// The lookupModuleOutput is for clang modules. P1689 format don't need it.
121
std::string lookupModuleOutput(const ModuleID &,
122
ModuleOutputKind Kind) override {
123
return "";
124
}
125
};
126
127
P1689Rule Rule;
128
P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
129
P1689ActionController Controller;
130
auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
131
Controller);
132
if (Result)
133
return std::move(Result);
134
135
MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
136
if (!MakeformatOutputPath.empty())
137
Consumer.printDependencies(MakeformatOutput);
138
return Rule;
139
}
140
141
llvm::Expected<TranslationUnitDeps>
142
DependencyScanningTool::getTranslationUnitDependencies(
143
const std::vector<std::string> &CommandLine, StringRef CWD,
144
const llvm::DenseSet<ModuleID> &AlreadySeen,
145
LookupModuleOutputCallback LookupModuleOutput) {
146
FullDependencyConsumer Consumer(AlreadySeen);
147
CallbackActionController Controller(LookupModuleOutput);
148
llvm::Error Result =
149
Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
150
if (Result)
151
return std::move(Result);
152
return Consumer.takeTranslationUnitDeps();
153
}
154
155
llvm::Expected<ModuleDepsGraph> DependencyScanningTool::getModuleDependencies(
156
StringRef ModuleName, const std::vector<std::string> &CommandLine,
157
StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
158
LookupModuleOutputCallback LookupModuleOutput) {
159
FullDependencyConsumer Consumer(AlreadySeen);
160
CallbackActionController Controller(LookupModuleOutput);
161
llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
162
Controller, ModuleName);
163
if (Result)
164
return std::move(Result);
165
return Consumer.takeModuleGraphDeps();
166
}
167
168
TranslationUnitDeps FullDependencyConsumer::takeTranslationUnitDeps() {
169
TranslationUnitDeps TU;
170
171
TU.ID.ContextHash = std::move(ContextHash);
172
TU.FileDeps = std::move(Dependencies);
173
TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
174
TU.Commands = std::move(Commands);
175
176
for (auto &&M : ClangModuleDeps) {
177
auto &MD = M.second;
178
// TODO: Avoid handleModuleDependency even being called for modules
179
// we've already seen.
180
if (AlreadySeen.count(M.first))
181
continue;
182
TU.ModuleGraph.push_back(std::move(MD));
183
}
184
TU.ClangModuleDeps = std::move(DirectModuleDeps);
185
186
return TU;
187
}
188
189
ModuleDepsGraph FullDependencyConsumer::takeModuleGraphDeps() {
190
ModuleDepsGraph ModuleGraph;
191
192
for (auto &&M : ClangModuleDeps) {
193
auto &MD = M.second;
194
// TODO: Avoid handleModuleDependency even being called for modules
195
// we've already seen.
196
if (AlreadySeen.count(M.first))
197
continue;
198
ModuleGraph.push_back(std::move(MD));
199
}
200
201
return ModuleGraph;
202
}
203
204
CallbackActionController::~CallbackActionController() {}
205
206