clang 17.0.0git
DependencyScanningWorker.cpp
Go to the documentation of this file.
1//===- DependencyScanningWorker.cpp - clang-scan-deps worker --------------===//
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
14#include "clang/Driver/Driver.h"
15#include "clang/Driver/Job.h"
16#include "clang/Driver/Tool.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/Error.h"
28#include "llvm/TargetParser/Host.h"
29#include <optional>
30
31using namespace clang;
32using namespace tooling;
33using namespace dependencies;
34
35namespace {
36
37/// Forwards the gatherered dependencies to the consumer.
38class DependencyConsumerForwarder : public DependencyFileGenerator {
39public:
40 DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts,
41 StringRef WorkingDirectory, DependencyConsumer &C)
42 : DependencyFileGenerator(*Opts), WorkingDirectory(WorkingDirectory),
43 Opts(std::move(Opts)), C(C) {}
44
45 void finishedMainFile(DiagnosticsEngine &Diags) override {
46 C.handleDependencyOutputOpts(*Opts);
47 llvm::SmallString<256> CanonPath;
48 for (const auto &File : getDependencies()) {
49 CanonPath = File;
50 llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
51 llvm::sys::fs::make_absolute(WorkingDirectory, CanonPath);
52 C.handleFileDependency(CanonPath);
53 }
54 }
55
56private:
57 StringRef WorkingDirectory;
58 std::unique_ptr<DependencyOutputOptions> Opts;
60};
61
62using PrebuiltModuleFilesT = decltype(HeaderSearchOptions::PrebuiltModuleFiles);
63
64/// A listener that collects the imported modules and optionally the input
65/// files.
66class PrebuiltModuleListener : public ASTReaderListener {
67public:
68 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
69 llvm::SmallVector<std::string> &NewModuleFiles)
70 : PrebuiltModuleFiles(PrebuiltModuleFiles),
71 NewModuleFiles(NewModuleFiles) {}
72
73 bool needsImportVisitation() const override { return true; }
74
75 void visitImport(StringRef ModuleName, StringRef Filename) override {
76 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
77 NewModuleFiles.push_back(Filename.str());
78 }
79
80private:
81 PrebuiltModuleFilesT &PrebuiltModuleFiles;
82 llvm::SmallVector<std::string> &NewModuleFiles;
83};
84
85/// Visit the given prebuilt module and collect all of the modules it
86/// transitively imports and contributing input files.
87static void visitPrebuiltModule(StringRef PrebuiltModuleFilename,
89 PrebuiltModuleFilesT &ModuleFiles) {
90 // List of module files to be processed.
91 llvm::SmallVector<std::string> Worklist{PrebuiltModuleFilename.str()};
92 PrebuiltModuleListener Listener(ModuleFiles, Worklist);
93
94 while (!Worklist.empty())
96 Worklist.pop_back_val(), CI.getFileManager(), CI.getModuleCache(),
98 /*FindModuleFileExtensions=*/false, Listener,
99 /*ValidateDiagnosticOptions=*/false);
100}
101
102/// Transform arbitrary file name into an object-like file name.
103static std::string makeObjFileName(StringRef FileName) {
104 SmallString<128> ObjFileName(FileName);
105 llvm::sys::path::replace_extension(ObjFileName, "o");
106 return std::string(ObjFileName.str());
107}
108
109/// Deduce the dependency target based on the output file and input files.
110static std::string
111deduceDepTarget(const std::string &OutputFile,
112 const SmallVectorImpl<FrontendInputFile> &InputFiles) {
113 if (OutputFile != "-")
114 return OutputFile;
115
116 if (InputFiles.empty() || !InputFiles.front().isFile())
117 return "clang-scan-deps\\ dependency";
118
119 return makeObjFileName(InputFiles.front().getFile());
120}
121
122/// Sanitize diagnostic options for dependency scan.
123static void sanitizeDiagOpts(DiagnosticOptions &DiagOpts) {
124 // Don't print 'X warnings and Y errors generated'.
125 DiagOpts.ShowCarets = false;
126 // Don't write out diagnostic file.
127 DiagOpts.DiagnosticSerializationFile.clear();
128 // Don't emit warnings as errors (and all other warnings too).
129 DiagOpts.IgnoreWarnings = true;
130}
131
132/// A clang tool that runs the preprocessor in a mode that's optimized for
133/// dependency scanning for the given compiler invocation.
134class DependencyScanningAction : public tooling::ToolAction {
135public:
136 DependencyScanningAction(
137 StringRef WorkingDirectory, DependencyConsumer &Consumer,
138 DependencyActionController &Controller,
140 ScanningOutputFormat Format, bool OptimizeArgs, bool EagerLoadModules,
141 bool DisableFree, std::optional<StringRef> ModuleName = std::nullopt)
142 : WorkingDirectory(WorkingDirectory), Consumer(Consumer),
143 Controller(Controller), DepFS(std::move(DepFS)), Format(Format),
144 OptimizeArgs(OptimizeArgs), EagerLoadModules(EagerLoadModules),
145 DisableFree(DisableFree), ModuleName(ModuleName) {}
146
147 bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
148 FileManager *FileMgr,
149 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
150 DiagnosticConsumer *DiagConsumer) override {
151 // Make a deep copy of the original Clang invocation.
152 CompilerInvocation OriginalInvocation(*Invocation);
153 // Restore the value of DisableFree, which may be modified by Tooling.
154 OriginalInvocation.getFrontendOpts().DisableFree = DisableFree;
155
156 if (Scanned) {
157 // Scanning runs once for the first -cc1 invocation in a chain of driver
158 // jobs. For any dependent jobs, reuse the scanning result and just
159 // update the LastCC1Arguments to correspond to the new invocation.
160 // FIXME: to support multi-arch builds, each arch requires a separate scan
161 setLastCC1Arguments(std::move(OriginalInvocation));
162 return true;
163 }
164
165 Scanned = true;
166
167 // Create a compiler instance to handle the actual work.
168 ScanInstanceStorage.emplace(std::move(PCHContainerOps));
169 CompilerInstance &ScanInstance = *ScanInstanceStorage;
170 ScanInstance.setInvocation(std::move(Invocation));
171
172 // Create the compiler's actual diagnostics engine.
173 sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
174 ScanInstance.createDiagnostics(DiagConsumer, /*ShouldOwnClient=*/false);
175 if (!ScanInstance.hasDiagnostics())
176 return false;
177
179 true;
180
181 ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex = false;
182 ScanInstance.getFrontendOpts().UseGlobalModuleIndex = false;
183 ScanInstance.getFrontendOpts().ModulesShareFileManager = false;
184 ScanInstance.getHeaderSearchOpts().ModuleFormat = "raw";
185
186 ScanInstance.setFileManager(FileMgr);
187 // Support for virtual file system overlays.
189 ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
190 FileMgr->getVirtualFileSystemPtr()));
191
192 ScanInstance.createSourceManager(*FileMgr);
193
194 // Store the list of prebuilt module files into header search options. This
195 // will prevent the implicit build to create duplicate modules and will
196 // force reuse of the existing prebuilt module files instead.
197 if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
198 visitPrebuiltModule(
199 ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, ScanInstance,
201
202 // Use the dependency scanning optimized file system if requested to do so.
203 if (DepFS) {
205 DepFS;
207 [LocalDepFS = std::move(LocalDepFS)](FileEntryRef File)
209 if (llvm::ErrorOr<EntryRef> Entry =
210 LocalDepFS->getOrCreateFileSystemEntry(File.getName()))
211 return Entry->getDirectiveTokens();
212 return std::nullopt;
213 };
214 }
215
216 // Create the dependency collector that will collect the produced
217 // dependencies.
218 //
219 // This also moves the existing dependency output options from the
220 // invocation to the collector. The options in the invocation are reset,
221 // which ensures that the compiler won't create new dependency collectors,
222 // and thus won't write out the extra '.d' files to disk.
223 auto Opts = std::make_unique<DependencyOutputOptions>();
224 std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts());
225 // We need at least one -MT equivalent for the generator of make dependency
226 // files to work.
227 if (Opts->Targets.empty())
228 Opts->Targets = {
229 deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile,
230 ScanInstance.getFrontendOpts().Inputs)};
231 Opts->IncludeSystemHeaders = true;
232
233 switch (Format) {
234 case ScanningOutputFormat::Make:
235 ScanInstance.addDependencyCollector(
236 std::make_shared<DependencyConsumerForwarder>(
237 std::move(Opts), WorkingDirectory, Consumer));
238 break;
239 case ScanningOutputFormat::P1689:
240 case ScanningOutputFormat::Full:
241 MDC = std::make_shared<ModuleDepCollector>(
242 std::move(Opts), ScanInstance, Consumer, Controller,
243 OriginalInvocation, OptimizeArgs, EagerLoadModules,
244 Format == ScanningOutputFormat::P1689);
245 ScanInstance.addDependencyCollector(MDC);
246 break;
247 }
248
249 // Consider different header search and diagnostic options to create
250 // different modules. This avoids the unsound aliasing of module PCMs.
251 //
252 // TODO: Implement diagnostic bucketing to reduce the impact of strict
253 // context hashing.
254 ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash = true;
255
256 std::unique_ptr<FrontendAction> Action;
257
258 if (ModuleName)
259 Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
260 else
261 Action = std::make_unique<ReadPCHAndPreprocessAction>();
262
263 const bool Result = ScanInstance.ExecuteAction(*Action);
264
265 if (Result)
266 setLastCC1Arguments(std::move(OriginalInvocation));
267
268 return Result;
269 }
270
271 bool hasScanned() const { return Scanned; }
272
273 /// Take the cc1 arguments corresponding to the most recent invocation used
274 /// with this action. Any modifications implied by the discovered dependencies
275 /// will have already been applied.
276 std::vector<std::string> takeLastCC1Arguments() {
277 std::vector<std::string> Result;
278 std::swap(Result, LastCC1Arguments); // Reset LastCC1Arguments to empty.
279 return Result;
280 }
281
282private:
283 void setLastCC1Arguments(CompilerInvocation &&CI) {
284 if (MDC)
285 MDC->applyDiscoveredDependencies(CI);
286 LastCC1Arguments = CI.getCC1CommandLine();
287 }
288
289private:
290 StringRef WorkingDirectory;
291 DependencyConsumer &Consumer;
292 DependencyActionController &Controller;
295 bool OptimizeArgs;
296 bool EagerLoadModules;
297 bool DisableFree;
298 std::optional<StringRef> ModuleName;
299 std::optional<CompilerInstance> ScanInstanceStorage;
300 std::shared_ptr<ModuleDepCollector> MDC;
301 std::vector<std::string> LastCC1Arguments;
302 bool Scanned = false;
303};
304
305} // end anonymous namespace
306
310 : Format(Service.getFormat()), OptimizeArgs(Service.canOptimizeArgs()),
311 EagerLoadModules(Service.shouldEagerLoadModules()) {
312 PCHContainerOps = std::make_shared<PCHContainerOperations>();
313 // We need to read object files from PCH built outside the scanner.
314 PCHContainerOps->registerReader(
315 std::make_unique<ObjectFilePCHContainerReader>());
316 // The scanner itself writes only raw ast files.
317 PCHContainerOps->registerWriter(std::make_unique<RawPCHContainerWriter>());
318
319 switch (Service.getMode()) {
321 DepFS =
323 BaseFS = DepFS;
324 break;
326 DepFS = nullptr;
327 BaseFS = FS;
328 break;
329 }
330}
331
333 StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
334 DependencyConsumer &Consumer, DependencyActionController &Controller,
335 std::optional<StringRef> ModuleName) {
336 std::vector<const char *> CLI;
337 for (const std::string &Arg : CommandLine)
338 CLI.push_back(Arg.c_str());
339 auto DiagOpts = CreateAndPopulateDiagOpts(CLI);
340 sanitizeDiagOpts(*DiagOpts);
341
342 // Capture the emitted diagnostics and report them to the client
343 // in the case of a failure.
344 std::string DiagnosticOutput;
345 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
346 TextDiagnosticPrinter DiagPrinter(DiagnosticsOS, DiagOpts.release());
347
348 if (computeDependencies(WorkingDirectory, CommandLine, Consumer, Controller,
349 DiagPrinter, ModuleName))
350 return llvm::Error::success();
351 return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
352 llvm::inconvertibleErrorCode());
353}
354
357 llvm::function_ref<bool(const driver::Command &Cmd)> Callback) {
359 Argv.reserve(ArgStrs.size());
360 for (const std::string &Arg : ArgStrs)
361 Argv.push_back(Arg.c_str());
362
363 llvm::vfs::FileSystem *FS = &FM.getVirtualFileSystem();
364
365 std::unique_ptr<driver::Driver> Driver = std::make_unique<driver::Driver>(
366 Argv[0], llvm::sys::getDefaultTargetTriple(), Diags,
367 "clang LLVM compiler", FS);
368 Driver->setTitle("clang_based_tool");
369
370 llvm::BumpPtrAllocator Alloc;
371 bool CLMode = driver::IsClangCL(
372 driver::getDriverMode(Argv[0], ArrayRef(Argv).slice(1)));
373
374 if (llvm::Error E = driver::expandResponseFiles(Argv, CLMode, Alloc, FS)) {
375 Diags.Report(diag::err_drv_expand_response_file)
376 << llvm::toString(std::move(E));
377 return false;
378 }
379
380 const std::unique_ptr<driver::Compilation> Compilation(
381 Driver->BuildCompilation(llvm::ArrayRef(Argv)));
382 if (!Compilation)
383 return false;
384
385 for (const driver::Command &Job : Compilation->getJobs()) {
386 if (!Callback(Job))
387 return false;
388 }
389 return true;
390}
391
393 StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
394 DependencyConsumer &Consumer, DependencyActionController &Controller,
395 DiagnosticConsumer &DC, std::optional<StringRef> ModuleName) {
396 // Reset what might have been modified in the previous worker invocation.
397 BaseFS->setCurrentWorkingDirectory(WorkingDirectory);
398
399 std::optional<std::vector<std::string>> ModifiedCommandLine;
401
402 // If we're scanning based on a module name alone, we don't expect the client
403 // to provide us with an input file. However, the driver really wants to have
404 // one. Let's just make it up to make the driver happy.
405 if (ModuleName) {
406 auto OverlayFS =
407 llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
408 auto InMemoryFS =
409 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
410 InMemoryFS->setCurrentWorkingDirectory(WorkingDirectory);
411 OverlayFS->pushOverlay(InMemoryFS);
412 ModifiedFS = OverlayFS;
413
414 SmallString<128> FakeInputPath;
415 // TODO: We should retry the creation if the path already exists.
416 llvm::sys::fs::createUniquePath(*ModuleName + "-%%%%%%%%.input",
417 FakeInputPath,
418 /*MakeAbsolute=*/false);
419 InMemoryFS->addFile(FakeInputPath, 0, llvm::MemoryBuffer::getMemBuffer(""));
420
421 ModifiedCommandLine = CommandLine;
422 ModifiedCommandLine->emplace_back(FakeInputPath);
423 }
424
425 const std::vector<std::string> &FinalCommandLine =
426 ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
427 auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
428
429 FileSystemOptions FSOpts;
430 FSOpts.WorkingDir = WorkingDirectory.str();
431 auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS);
432
433 std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr);
434 llvm::transform(FinalCommandLine, FinalCCommandLine.begin(),
435 [](const std::string &Str) { return Str.c_str(); });
436
437 auto DiagOpts = CreateAndPopulateDiagOpts(FinalCCommandLine);
438 sanitizeDiagOpts(*DiagOpts);
440 CompilerInstance::createDiagnostics(DiagOpts.release(), &DC,
441 /*ShouldOwnClient=*/false);
442
443 // Although `Diagnostics` are used only for command-line parsing, the
444 // custom `DiagConsumer` might expect a `SourceManager` to be present.
445 SourceManager SrcMgr(*Diags, *FileMgr);
446 Diags->setSourceManager(&SrcMgr);
447 // DisableFree is modified by Tooling for running
448 // in-process; preserve the original value, which is
449 // always true for a driver invocation.
450 bool DisableFree = true;
451 DependencyScanningAction Action(WorkingDirectory, Consumer, Controller, DepFS,
452 Format, OptimizeArgs, EagerLoadModules,
453 DisableFree, ModuleName);
454 bool Success = forEachDriverJob(
455 FinalCommandLine, *Diags, *FileMgr, [&](const driver::Command &Cmd) {
456 if (StringRef(Cmd.getCreator().getName()) != "clang") {
457 // Non-clang command. Just pass through to the dependency
458 // consumer.
459 Consumer.handleBuildCommand(
460 {Cmd.getExecutable(),
461 {Cmd.getArguments().begin(), Cmd.getArguments().end()}});
462 return true;
463 }
464
465 std::vector<std::string> Argv;
466 Argv.push_back(Cmd.getExecutable());
467 Argv.insert(Argv.end(), Cmd.getArguments().begin(),
468 Cmd.getArguments().end());
469
470 // Create an invocation that uses the underlying file
471 // system to ensure that any file system requests that
472 // are made by the driver do not go through the
473 // dependency scanning filesystem.
474 ToolInvocation Invocation(std::move(Argv), &Action, &*FileMgr,
475 PCHContainerOps);
476 Invocation.setDiagnosticConsumer(Diags->getClient());
477 Invocation.setDiagnosticOptions(&Diags->getDiagnosticOptions());
478 if (!Invocation.run())
479 return false;
480
481 std::vector<std::string> Args = Action.takeLastCC1Arguments();
482 Consumer.handleBuildCommand({Cmd.getExecutable(), std::move(Args)});
483 return true;
484 });
485
486 if (Success && !Action.hasScanned())
487 Diags->Report(diag::err_fe_expected_compiler_job)
488 << llvm::join(FinalCommandLine, " ");
489 return Success && Action.hasScanned();
490}
491
static bool forEachDriverJob(ArrayRef< std::string > ArgStrs, DiagnosticsEngine &Diags, FileManager &FM, llvm::function_ref< bool(const driver::Command &Cmd)> Callback)
StringRef Filename
Definition: Format.cpp:2792
CompileCommand Cmd
Abstract interface for callback invocations by the ASTReader.
Definition: ASTReader.h:113
virtual void visitImport(StringRef ModuleName, StringRef Filename)
If needsImportVisitation returns true, this is called for each AST file imported by this AST file.
Definition: ASTReader.h:240
virtual bool needsImportVisitation() const
Returns true if this ASTReaderListener wants to receive the imports of the AST file via visitImport,...
Definition: ASTReader.h:236
static bool readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, const InMemoryModuleCache &ModuleCache, const PCHContainerReader &PCHContainerRdr, bool FindModuleFileExtensions, ASTReaderListener &Listener, bool ValidateDiagnosticOptions)
Read the control block for the named AST file.
Definition: ASTReader.cpp:5265
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
void setFileManager(FileManager *Value)
Replace the current file manager and virtual file system.
void createSourceManager(FileManager &FileMgr)
Create the source manager and replace any existing one with it.
void createDiagnostics(DiagnosticConsumer *Client=nullptr, bool ShouldOwnClient=true)
Create the diagnostics engine using the invocation's diagnostic options and replace any existing one ...
const PCHContainerReader & getPCHContainerReader() const
Return the appropriate PCHContainerReader depending on the current CodeGenOptions.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
void setInvocation(std::shared_ptr< CompilerInvocation > Value)
setInvocation - Replace the current invocation.
FileManager & getFileManager() const
Return the current file manager to the caller.
InMemoryModuleCache & getModuleCache() const
void addDependencyCollector(std::shared_ptr< DependencyCollector > Listener)
FrontendOptions & getFrontendOpts()
HeaderSearchOptions & getHeaderSearchOpts()
CompilerInvocation & getInvocation()
PreprocessorOptions & getPreprocessorOpts()
bool ExecuteAction(FrontendAction &Act)
ExecuteAction - Execute the provided action against the compiler's CompilerInvocation object.
DiagnosticOptions & getDiagnosticOpts()
DependencyOutputOptions & getDependencyOutputOpts()
Helper class for holding the data necessary to invoke the compiler.
ArrayRef< std::string > getDependencies() const
Definition: Utils.h:68
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
Definition: Utils.h:106
void finishedMainFile(DiagnosticsEngine &Diags) override
Called when the end of the main file is reached.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1740
Options for controlling the compiler diagnostics engine.
std::string DiagnosticSerializationFile
The file to serialize diagnostics to (non-appending).
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1542
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
Definition: FileEntry.h:57
Implements support for file system lookup, file system caching, and directory search management.
Definition: FileManager.h:53
llvm::vfs::FileSystem & getVirtualFileSystem() const
Definition: FileManager.h:245
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > getVirtualFileSystemPtr() const
Definition: FileManager.h:247
void setVirtualFileSystem(IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
Definition: FileManager.h:251
Keeps track of options that affect how file operations are performed.
std::string WorkingDir
If set, paths are resolved as if the working directory was set to the value of WorkingDir.
unsigned ModulesShareFileManager
Whether to share the FileManager when building modules.
std::string OutputFile
The output file, if any.
unsigned GenerateGlobalModuleIndex
Whether we can generate the global module index if needed.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
unsigned UseGlobalModuleIndex
Whether we can use the global module index if available.
unsigned ModulesStrictContextHash
Whether we should include all things that could impact the module in the hash.
std::map< std::string, std::string, std::less<> > PrebuiltModuleFiles
The mapping of module names to prebuilt module files.
std::string ModuleFormat
The module/pch container format.
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool AllowPCHWithDifferentModulesCachePath
When true, a PCH with modules cache path different to the current compilation will not be rejected.
std::function< std::optional< ArrayRef< dependency_directives_scan::Directive > >(FileEntryRef)> DependencyDirectivesForFile
Function for getting the dependency preprocessor directives of a file.
This class handles loading and caching of source files into memory.
Command - An executable path/name and argument vector to execute.
Definition: Job.h:106
Interface to process a clang::CompilerInvocation.
Definition: Tooling.h:80
virtual bool runInvocation(std::shared_ptr< CompilerInvocation > Invocation, FileManager *Files, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagConsumer)=0
Perform an action for an invocation.
Utility to run a FrontendAction in a single clang invocation.
Definition: Tooling.h:239
void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer)
Set a DiagnosticConsumer to use during driver command-line parsing and the action invocation itself.
Definition: Tooling.h:272
void setDiagnosticOptions(DiagnosticOptions *DiagOpts)
Set a DiagnosticOptions to use during driver command-line parsing.
Definition: Tooling.h:277
bool run()
Run the clang invocation.
Definition: Tooling.cpp:367
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...
DependencyScanningFilesystemSharedCache & getSharedCache()
A virtual file system optimized for the dependency discovery.
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...
DependencyScanningWorker(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS)
llvm::StringRef getDriverMode(StringRef ProgName, ArrayRef< const char * > Args)
Returns the driver mode option's value, i.e.
Definition: Driver.cpp:6475
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.
Definition: Driver.cpp:6492
bool IsClangCL(StringRef DriverMode)
Checks whether the value produced by getDriverMode is for CL mode.
Definition: Driver.cpp:6490
ScanningOutputFormat
The format that is output by the dependency scanner.
@ DependencyDirectivesScan
This mode is used to compute the dependencies by running the preprocessor with special kind of lexing...
@ CanonicalPreprocessing
This mode is used to compute the dependencies by running the preprocessor over the source files.
std::unique_ptr< DiagnosticOptions > CreateAndPopulateDiagOpts(ArrayRef< const char * > Argv)
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
IntrusiveRefCntPtr< llvm::vfs::FileSystem > createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags)
Definition: Format.h:4756