17#include "llvm/ADT/SmallVectorExtras.h"
18#include "llvm/ADT/iterator.h"
19#include "llvm/TargetParser/Host.h"
30 void handleBuildCommand(Command)
override {}
33 handleDependencyOutputOpts(
const DependencyOutputOptions &Opts)
override {
34 this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
37 void handleFileDependency(StringRef
File)
override {
38 SmallString<128> NormalizedFile =
File;
39 llvm::sys::path::remove_dots(NormalizedFile,
true);
40 Dependencies.emplace_back(NormalizedFile.str());
46 void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD)
override {}
47 void handleModuleDependency(ModuleDeps MD)
override {
49 DependenciesFromModules.push_back(std::string(
File));
52 void handleDirectModuleDependency(ModuleID ID)
override {}
53 void handleVisibleModule(std::string ModuleName)
override {}
54 void handleContextHash(std::string Hash)
override {}
56 void printDependencies(std::string &S) {
57 assert(Opts &&
"Handled dependency output options.");
59 class DependencyPrinter :
public DependencyFileGenerator {
61 DependencyPrinter(DependencyOutputOptions &Opts,
62 ArrayRef<std::string> Dependencies,
63 ArrayRef<std::string> ModuleDependencies)
64 : DependencyFileGenerator(Opts) {
65 for (
const auto &Dep : Dependencies)
67 for (
const auto &Dep : ModuleDependencies)
71 void printDependencies(std::string &S) {
72 llvm::raw_string_ostream
OS(S);
73 outputDependencyFile(OS);
77 DependencyPrinter
Generator(*Opts, Dependencies, DependenciesFromModules);
82 std::unique_ptr<DependencyOutputOptions> Opts;
83 std::vector<std::string> Dependencies;
84 std::vector<std::string> DependenciesFromModules;
88static std::pair<std::unique_ptr<driver::Driver>,
89 std::unique_ptr<driver::Compilation>>
92 llvm::BumpPtrAllocator &Alloc) {
94 Argv.reserve(ArgStrs.size());
95 for (
const std::string &Arg : ArgStrs)
96 Argv.push_back(Arg.c_str());
98 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
99 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
100 "clang LLVM compiler", FS);
101 Driver->setTitle(
"clang_based_tool");
108 Diags.
Report(diag::err_drv_expand_response_file)
109 << llvm::toString(std::move(E));
110 return std::make_pair(
nullptr,
nullptr);
113 std::unique_ptr<driver::Compilation> Compilation(
114 Driver->BuildCompilation(Argv));
116 return std::make_pair(
nullptr,
nullptr);
118 if (Compilation->containsError())
119 return std::make_pair(
nullptr,
nullptr);
121 if (Compilation->getJobs().empty()) {
122 Diags.
Report(diag::err_fe_expected_compiler_job)
123 << llvm::join(ArgStrs,
" ");
124 return std::make_pair(
nullptr,
nullptr);
127 return std::make_pair(std::move(Driver), std::move(Compilation));
136 Out.reserve(Args.size() + 1);
138 llvm::append_range(Out, Args);
147 auto FS =
Worker.makeEffectiveVFS(WorkingDirectory, OverlayFS);
152 llvm::BumpPtrAllocator Alloc;
153 auto DiagEngineWithDiagOpts =
156 CommandLine, *DiagEngineWithDiagOpts.DiagEngine, FS, Alloc);
161 for (
const auto &Cmd : Compilation->getJobs())
164 FrontendCommandLines.begin(), FrontendCommandLines.end());
166 return Worker.computeDependencies(WorkingDirectory, FrontendCommandLinesView,
167 Consumer, Controller, DiagConsumer,
168 std::move(OverlayFS));
176 const auto IsCC1Input = (CommandLine.size() >= 2 && CommandLine[1] ==
"-cc1");
177 return IsCC1Input ?
Worker.computeDependencies(WorkingDirectory, CommandLine,
178 Consumer, Controller,
179 DiagConsumer, OverlayFS)
181 Worker, WorkingDirectory, CommandLine, Consumer,
182 Controller, DiagConsumer, OverlayFS);
189 MakeDependencyPrinterConsumer DepConsumer;
195 DepConsumer.printDependencies(Output);
202 class P1689ModuleDependencyPrinterConsumer
203 :
public MakeDependencyPrinterConsumer {
205 P1689ModuleDependencyPrinterConsumer(
P1689Rule &Rule,
207 : Filename(
Command.Filename), Rule(Rule) {
208 Rule.PrimaryOutput =
Command.Output;
211 void handleProvidedAndRequiredStdCXXModules(
212 std::optional<P1689ModuleInfo> Provided,
213 std::vector<P1689ModuleInfo> Requires)
override {
214 Rule.Provides = std::move(Provided);
216 Rule.Provides->SourcePath = Filename.str();
217 Rule.Requires = std::move(Requires);
220 StringRef getMakeFormatDependencyOutputPath() {
234 std::string lookupModuleOutput(
const ModuleDeps &,
239 std::unique_ptr<DependencyActionController> clone()
const override {
240 return std::make_unique<P1689ActionController>();
245 P1689ModuleDependencyPrinterConsumer Consumer(Rule,
Command);
246 P1689ActionController Controller;
248 Controller, DiagConsumer))
251 MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
252 if (!MakeformatOutputPath.empty())
253 Consumer.printDependencies(MakeformatOutput);
257static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
258 std::vector<std::string>>
260 llvm::MemoryBufferRef TUBuffer) {
261 StringRef InputPath = TUBuffer.getBufferIdentifier();
262 auto InputBuf = llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer());
264 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
265 FS->addFile(InputPath, 0, std::move(InputBuf));
267 std::vector<std::string> ModifiedCommandLine(CommandLine);
268 ModifiedCommandLine.emplace_back(InputPath);
270 return std::make_pair(std::move(FS), ModifiedCommandLine);
273static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
274 std::vector<std::string>>
279 static const std::string FakeInput(
282 StringRef InputPath =
283 llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)
284 ?
"Z:\\module-include.input"
285 :
"/module-include.input";
286 auto InputBuf = llvm::MemoryBuffer::getMemBuffer(FakeInput, InputPath);
288 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
289 FS->addFile(InputPath, 0, std::move(InputBuf));
291 std::vector<std::string> ModifiedCommandLine(CommandLine);
292 ModifiedCommandLine.emplace_back(InputPath);
294 return std::make_pair(std::move(FS), ModifiedCommandLine);
297std::optional<TranslationUnitDeps>
301 const llvm::DenseSet<ModuleID> &AlreadySeen,
303 std::optional<llvm::MemoryBufferRef> TUBuffer) {
310 std::vector<std::string> CommandLineWithTUBufferInput;
312 std::tie(OverlayFS, CommandLineWithTUBufferInput) =
314 CommandLine = CommandLineWithTUBufferInput;
318 DiagConsumer, std::move(OverlayFS)))
323static std::optional<SmallVector<std::string, 0>>
330 llvm::BumpPtrAllocator Alloc;
331 const auto [Driver, Compilation] =
337 return StringRef(Cmd.getCreator().getName()) ==
"clang";
340 const auto &Jobs = Compilation->getJobs();
341 if (
const auto It = llvm::find_if(Jobs, IsClangCmd); It != Jobs.end())
349 llvm::function_ref<std::optional<std::string>()> getNextName,
352 auto FS = Worker.makeEffectiveVFS(CWD, OverlayFS);
353 std::vector<std::string> CC1CommandLine;
354 if (ModifiedCommandLine.size() >= 2 && ModifiedCommandLine[1] ==
"-cc1") {
355 CC1CommandLine = std::move(ModifiedCommandLine);
361 ModifiedCommandLine, *DiagEngineWithOpts.
DiagEngine, FS);
364 CC1CommandLine.assign(MaybeFirstCC1->begin(), MaybeFirstCC1->end());
367 return Worker.computeDependenciesByName(CWD, CC1CommandLine,
368 std::move(OverlayFS), DiagConsumer,
369 Controller, getNextName, DepConsumer);
Defines the Diagnostic-related interfaces.
DependencyOutputFormat OutputFormat
The format for the dependency file.
std::string OutputFile
The file to write dependency output to.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
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...
An individual dependency scanning worker that is able to run on its own thread.
static const int32_t MaxNumOfByNameQueries
TranslationUnitDeps takeTranslationUnitDeps()
Command - An executable path/name and argument vector to execute.
const llvm::opt::ArgStringList & getArguments() const
const char * getExecutable() const
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.
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
llvm::Error expandResponseFiles(SmallVectorImpl< const char * > &Args, bool ClangCLMode, llvm::BumpPtrAllocator &Alloc, llvm::vfs::FileSystem *FS=nullptr)
Expand response files from a clang driver or cc1 invocation.
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
A command-line tool invocation that is part of building a TU.
IntrusiveRefCntPtr< DiagnosticsEngine > DiagEngine
void forEachFileDep(llvm::function_ref< void(StringRef)> Cb) const
Invokes Cb for all file dependencies of this module.