20#include "llvm/ADT/SmallVectorExtras.h"
21#include "llvm/ADT/iterator.h"
22#include "llvm/TargetParser/Host.h"
33 void handleBuildCommand(Command)
override {}
36 handleDependencyOutputOpts(
const DependencyOutputOptions &Opts)
override {
37 this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
40 void handleFileDependency(StringRef
File)
override {
41 SmallString<128> NormalizedFile =
File;
42 llvm::sys::path::remove_dots(NormalizedFile,
true);
43 Dependencies.emplace_back(NormalizedFile.str());
49 void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD)
override {}
50 void handleModuleDependency(ModuleDeps MD)
override {
52 DependenciesFromModules.push_back(std::string(
File));
55 void handleDirectModuleDependency(ModuleID ID)
override {}
56 void handleVisibleModule(std::string ModuleName)
override {}
57 void handleContextHash(std::string Hash)
override {}
59 void printDependencies(std::string &S) {
60 assert(Opts &&
"Handled dependency output options.");
62 class DependencyPrinter :
public DependencyFileGenerator {
64 DependencyPrinter(DependencyOutputOptions &Opts,
65 ArrayRef<std::string> Dependencies,
66 ArrayRef<std::string> ModuleDependencies)
67 : DependencyFileGenerator(Opts) {
68 for (
const auto &Dep : Dependencies)
70 for (
const auto &Dep : ModuleDependencies)
74 void printDependencies(std::string &S) {
75 llvm::raw_string_ostream
OS(S);
76 outputDependencyFile(OS);
80 DependencyPrinter
Generator(*Opts, Dependencies, DependenciesFromModules);
85 std::unique_ptr<DependencyOutputOptions> Opts;
86 std::vector<std::string> Dependencies;
87 std::vector<std::string> DependenciesFromModules;
91static std::pair<std::unique_ptr<driver::Driver>,
92 std::unique_ptr<driver::Compilation>>
97 Argv.reserve(ArgStrs.size());
98 for (
const std::string &Arg : ArgStrs)
99 Argv.push_back(Arg.c_str());
101 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
102 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
103 "clang LLVM compiler", FS);
104 Driver->setTitle(
"clang_based_tool");
111 Diags.
Report(diag::err_drv_expand_response_file)
112 << llvm::toString(std::move(E));
113 return std::make_pair(
nullptr,
nullptr);
116 std::unique_ptr<driver::Compilation> Compilation(
117 Driver->BuildCompilation(Argv));
119 return std::make_pair(
nullptr,
nullptr);
121 if (Compilation->containsError())
122 return std::make_pair(
nullptr,
nullptr);
124 if (Compilation->getJobs().empty()) {
125 Diags.
Report(diag::err_fe_expected_compiler_job)
126 << llvm::join(ArgStrs,
" ");
127 return std::make_pair(
nullptr,
nullptr);
130 const llvm::opt::Arg *LogPathArg =
131 Compilation->getArgs().getLastArg(options::OPT_fdepscan_log_path);
133 LogPathArg ? StringRef(LogPathArg->getValue()).trim() : StringRef();
136 if (LogPathArg && LogPath.empty()) {
137 Diags.
Report(diag::err_drv_depscan_log_path_empty);
138 return std::make_pair(
nullptr,
nullptr);
141 if (!Logger.
enable(LogPath)) {
142 Diags.
Report(diag::err_drv_depscan_log_path_inconsistent)
143 <<
unsigned(!LogPath.empty()) << LogPath
145 return std::make_pair(
nullptr,
nullptr);
148 return std::make_pair(std::move(Driver), std::move(Compilation));
157 Out.reserve(Args.size() + 1);
159 llvm::append_range(Out, Args);
168 auto FS =
Worker.makeEffectiveVFS(WorkingDirectory, OverlayFS);
173 llvm::BumpPtrAllocator Alloc;
179 CommandLine, *DiagEngine, FS, Alloc,
Worker.getService().getLogger());
184 for (
const auto &Cmd : Compilation->getJobs())
187 FrontendCommandLines.begin(), FrontendCommandLines.end());
189 return Worker.computeDependencies(WorkingDirectory, FrontendCommandLinesView,
190 Consumer, Controller, DiagConsumer,
191 std::move(OverlayFS));
199 const auto IsCC1Input = (CommandLine.size() >= 2 && CommandLine[1] ==
"-cc1");
200 return IsCC1Input ?
Worker.computeDependencies(WorkingDirectory, CommandLine,
201 Consumer, Controller,
202 DiagConsumer, OverlayFS)
204 Worker, WorkingDirectory, CommandLine, Consumer,
205 Controller, DiagConsumer, OverlayFS);
212 MakeDependencyPrinterConsumer DepConsumer;
218 DepConsumer.printDependencies(Output);
225 class P1689ModuleDependencyPrinterConsumer
226 :
public MakeDependencyPrinterConsumer {
228 P1689ModuleDependencyPrinterConsumer(
P1689Rule &Rule,
230 : Filename(
Command.Filename), Rule(Rule) {
231 Rule.PrimaryOutput =
Command.Output;
234 void handleProvidedAndRequiredStdCXXModules(
235 std::optional<P1689ModuleInfo> Provided,
236 std::vector<P1689ModuleInfo> Requires)
override {
237 Rule.Provides = std::move(Provided);
239 Rule.Provides->SourcePath = Filename.str();
240 Rule.Requires = std::move(Requires);
243 StringRef getMakeFormatDependencyOutputPath() {
262 std::string lookupModuleOutput(
const ModuleDeps &,
267 std::unique_ptr<DependencyActionController> clone()
const override {
268 return std::make_unique<P1689ActionController>();
273 P1689ModuleDependencyPrinterConsumer Consumer(Rule,
Command);
274 P1689ActionController Controller;
276 Controller, DiagConsumer))
279 MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
280 if (!MakeformatOutputPath.empty())
281 Consumer.printDependencies(MakeformatOutput);
285static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
286 std::vector<std::string>>
288 llvm::MemoryBufferRef TUBuffer) {
289 StringRef InputPath = TUBuffer.getBufferIdentifier();
290 auto InputBuf = llvm::MemoryBuffer::getMemBufferCopy(TUBuffer.getBuffer());
292 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
293 FS->addFile(InputPath, 0, std::move(InputBuf));
295 std::vector<std::string> ModifiedCommandLine(CommandLine);
296 ModifiedCommandLine.emplace_back(InputPath);
298 return std::make_pair(std::move(FS), ModifiedCommandLine);
301static std::pair<IntrusiveRefCntPtr<llvm::vfs::FileSystem>,
302 std::vector<std::string>>
307 static const std::string FakeInput(
310 StringRef InputPath =
311 llvm::sys::path::is_style_windows(llvm::sys::path::Style::native)
312 ?
"Z:\\module-include.input"
313 :
"/module-include.input";
314 auto InputBuf = llvm::MemoryBuffer::getMemBuffer(FakeInput, InputPath);
316 auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
317 FS->addFile(InputPath, 0, std::move(InputBuf));
319 std::vector<std::string> ModifiedCommandLine(CommandLine);
320 ModifiedCommandLine.emplace_back(InputPath);
322 return std::make_pair(std::move(FS), ModifiedCommandLine);
325std::optional<TranslationUnitDeps>
329 const llvm::DenseSet<ModuleID> &AlreadySeen,
331 std::optional<llvm::MemoryBufferRef> TUBuffer) {
338 std::vector<std::string> CommandLineWithTUBufferInput;
340 std::tie(OverlayFS, CommandLineWithTUBufferInput) =
342 CommandLine = CommandLineWithTUBufferInput;
346 DiagConsumer, std::move(OverlayFS)))
351static std::optional<SmallVector<std::string, 0>>
359 llvm::BumpPtrAllocator Alloc;
360 const auto [Driver, Compilation] =
366 return StringRef(Cmd.getCreator().getName()) ==
"clang";
369 const auto &Jobs = Compilation->getJobs();
370 if (
const auto It = llvm::find_if(Jobs, IsClangCmd); It != Jobs.end())
378 llvm::function_ref<std::optional<std::string>()> getNextName,
381 auto FS = Worker.makeEffectiveVFS(CWD, OverlayFS);
382 std::vector<std::string> CC1CommandLine;
383 if (ModifiedCommandLine.size() >= 2 && ModifiedCommandLine[1] ==
"-cc1") {
384 CC1CommandLine = std::move(ModifiedCommandLine);
392 ModifiedCommandLine, *DiagEngine, FS, Worker.getService().getLogger());
395 CC1CommandLine.assign(MaybeFirstCC1->begin(), MaybeFirstCC1->end());
398 return Worker.computeDependenciesByName(CWD, CC1CommandLine,
399 std::move(OverlayFS), DiagConsumer,
400 Controller, getNextName, DepConsumer);
Defines a logger where each line is written atomically to the file.
Defines the Diagnostic-related interfaces.
bool enable(StringRef RequestedLogPath)
Enables the logger if it is not already enabled.
StringRef getLogPath() const
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation's diagnostic options and replace any existing one ...
Helper class for holding the data necessary to invoke the compiler.
PreprocessorOptions & getPreprocessorOpts()
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.
bool DependencyScanningModuleMapImports
When enabled, we don't try to load the corresponding module required by the module map.
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.