18#include "llvm/ADT/SmallVectorExtras.h"
19#include "llvm/ADT/iterator.h"
20#include "llvm/TargetParser/Host.h"
31 void handleBuildCommand(Command)
override {}
34 handleDependencyOutputOpts(
const DependencyOutputOptions &Opts)
override {
35 this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
38 void handleFileDependency(StringRef
File)
override {
39 SmallString<128> NormalizedFile =
File;
40 llvm::sys::path::remove_dots(NormalizedFile,
true);
41 Dependencies.emplace_back(NormalizedFile.str());
47 void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD)
override {}
48 void handleModuleDependency(ModuleDeps MD)
override {
50 DependenciesFromModules.push_back(std::string(
File));
53 void handleDirectModuleDependency(ModuleID ID)
override {}
54 void handleVisibleModule(std::string ModuleName)
override {}
55 void handleContextHash(std::string Hash)
override {}
57 void printDependencies(std::string &S) {
58 assert(Opts &&
"Handled dependency output options.");
60 class DependencyPrinter :
public DependencyFileGenerator {
62 DependencyPrinter(DependencyOutputOptions &Opts,
63 ArrayRef<std::string> Dependencies,
64 ArrayRef<std::string> ModuleDependencies)
65 : DependencyFileGenerator(Opts) {
66 for (
const auto &Dep : Dependencies)
68 for (
const auto &Dep : ModuleDependencies)
72 void printDependencies(std::string &S) {
73 llvm::raw_string_ostream
OS(S);
74 outputDependencyFile(OS);
78 DependencyPrinter
Generator(*Opts, Dependencies, DependenciesFromModules);
83 std::unique_ptr<DependencyOutputOptions> Opts;
84 std::vector<std::string> Dependencies;
85 std::vector<std::string> DependenciesFromModules;
89static std::pair<std::unique_ptr<driver::Driver>,
90 std::unique_ptr<driver::Compilation>>
93 llvm::BumpPtrAllocator &Alloc) {
95 Argv.reserve(ArgStrs.size());
96 for (
const std::string &Arg : ArgStrs)
97 Argv.push_back(Arg.c_str());
99 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
100 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
101 "clang LLVM compiler", FS);
102 Driver->setTitle(
"clang_based_tool");
109 Diags.
Report(diag::err_drv_expand_response_file)
110 << llvm::toString(std::move(E));
111 return std::make_pair(
nullptr,
nullptr);
114 std::unique_ptr<driver::Compilation> Compilation(
115 Driver->BuildCompilation(Argv));
117 return std::make_pair(
nullptr,
nullptr);
119 if (Compilation->containsError())
120 return std::make_pair(
nullptr,
nullptr);
122 if (Compilation->getJobs().empty()) {
123 Diags.
Report(diag::err_fe_expected_compiler_job)
124 << llvm::join(ArgStrs,
" ");
125 return std::make_pair(
nullptr,
nullptr);
128 return std::make_pair(std::move(Driver), std::move(Compilation));
137 Out.reserve(Args.size() + 1);
139 llvm::append_range(Out, Args);
148 auto FS =
Worker.makeEffectiveVFS(WorkingDirectory, OverlayFS);
153 llvm::BumpPtrAllocator Alloc;
158 const auto [Driver, Compilation] =
164 for (
const auto &Cmd : Compilation->getJobs())
167 FrontendCommandLines.begin(), FrontendCommandLines.end());
169 return Worker.computeDependencies(WorkingDirectory, FrontendCommandLinesView,
170 Consumer, Controller, DiagConsumer,
171 std::move(OverlayFS));
179 const auto IsCC1Input = (CommandLine.size() >= 2 && CommandLine[1] ==
"-cc1");
180 return IsCC1Input ?
Worker.computeDependencies(WorkingDirectory, CommandLine,
181 Consumer, Controller,
182 DiagConsumer, OverlayFS)
184 Worker, WorkingDirectory, CommandLine, Consumer,
185 Controller, DiagConsumer, OverlayFS);
192 MakeDependencyPrinterConsumer DepConsumer;
198 DepConsumer.printDependencies(Output);
205 class P1689ModuleDependencyPrinterConsumer
206 :
public MakeDependencyPrinterConsumer {
208 P1689ModuleDependencyPrinterConsumer(
P1689Rule &Rule,
210 : Filename(
Command.Filename), Rule(Rule) {
211 Rule.PrimaryOutput =
Command.Output;
214 void handleProvidedAndRequiredStdCXXModules(
215 std::optional<P1689ModuleInfo> Provided,
216 std::vector<P1689ModuleInfo> Requires)
override {
217 Rule.Provides = std::move(Provided);
219 Rule.Provides->SourcePath = Filename.str();
220 Rule.Requires = std::move(Requires);
223 StringRef getMakeFormatDependencyOutputPath() {
237 std::string lookupModuleOutput(
const ModuleDeps &,
242 std::unique_ptr<DependencyActionController> clone()
const override {
243 return std::make_unique<P1689ActionController>();
248 P1689ModuleDependencyPrinterConsumer Consumer(Rule,
Command);
249 P1689ActionController Controller;
251 Controller, DiagConsumer))
254 MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
255 if (!MakeformatOutputPath.empty())
256 Consumer.printDependencies(MakeformatOutput);
260static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
261 std::vector<std::string>>
263 llvm::MemoryBufferRef TUBuffer) {
264 StringRef InputPath = TUBuffer.getBufferIdentifier();
265 auto InputBuf = llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer());
267 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
268 FS->addFile(InputPath, 0, std::move(InputBuf));
270 std::vector<std::string> ModifiedCommandLine(CommandLine);
271 ModifiedCommandLine.emplace_back(InputPath);
273 return std::make_pair(std::move(FS), ModifiedCommandLine);
276static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
277 std::vector<std::string>>
282 static const std::string FakeInput(
285 StringRef InputPath =
286 llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)
287 ?
"Z:\\module-include.input"
288 :
"/module-include.input";
289 auto InputBuf = llvm::MemoryBuffer::getMemBuffer(FakeInput, InputPath);
291 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
292 FS->addFile(InputPath, 0, std::move(InputBuf));
294 std::vector<std::string> ModifiedCommandLine(CommandLine);
295 ModifiedCommandLine.emplace_back(InputPath);
297 return std::make_pair(std::move(FS), ModifiedCommandLine);
300std::optional<TranslationUnitDeps>
304 const llvm::DenseSet<ModuleID> &AlreadySeen,
306 std::optional<llvm::MemoryBufferRef> TUBuffer) {
313 std::vector<std::string> CommandLineWithTUBufferInput;
315 std::tie(OverlayFS, CommandLineWithTUBufferInput) =
317 CommandLine = CommandLineWithTUBufferInput;
321 DiagConsumer, std::move(OverlayFS)))
326static std::optional<SmallVector<std::string, 0>>
333 llvm::BumpPtrAllocator Alloc;
334 const auto [Driver, Compilation] =
340 return StringRef(Cmd.getCreator().getName()) ==
"clang";
343 const auto &Jobs = Compilation->getJobs();
344 if (
const auto It = llvm::find_if(Jobs, IsClangCmd); It != Jobs.end())
352 llvm::function_ref<std::optional<std::string>()> getNextName,
355 auto FS = Worker.makeEffectiveVFS(CWD, OverlayFS);
356 std::vector<std::string> CC1CommandLine;
357 if (ModifiedCommandLine.size() >= 2 && ModifiedCommandLine[1] ==
"-cc1") {
358 CC1CommandLine = std::move(ModifiedCommandLine);
369 CC1CommandLine.assign(MaybeFirstCC1->begin(), MaybeFirstCC1->end());
372 return Worker.computeDependenciesByName(CWD, CC1CommandLine,
373 std::move(OverlayFS), DiagConsumer,
374 Controller, getNextName, DepConsumer);
Defines the Diagnostic-related interfaces.
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation's diagnostic options and replace any existing one ...
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.
std::unique_ptr< DiagnosticOptions > createScanningDiagOptions(ArrayRef< std::string > CommandLine)
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,...
Top level wrappers for InstallAPI frontend operations.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
A command-line tool invocation that is part of building a TU.
void forEachFileDep(llvm::function_ref< void(StringRef)> Cb) const
Invokes Cb for all file dependencies of this module.