1//===----------------------------------------------------------------------===//
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#ifndef LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H
10#define LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H
11
12#include "clang/DependencyScanning/DependencyScanningFilesystem.h"
13#include "clang/DependencyScanning/ModuleDepCollector.h"
14#include "clang/Frontend/CompilerInstance.h"
15#include "clang/Frontend/CompilerInvocation.h"
16#include "clang/Frontend/TextDiagnosticPrinter.h"
17#include "llvm/Support/VirtualFileSystem.h"
18
19namespace clang {
20class DiagnosticConsumer;
21
22namespace dependencies {
23class DependencyScanningService;
24class DependencyScanningWorker;
25
26class DependencyConsumer;
27class DependencyActionController;
28class DependencyScanningWorkerFilesystem;
29
30class DependencyScanningAction {
31public:
32 DependencyScanningAction(
33 DependencyScanningService &Service, StringRef WorkingDirectory,
34 DependencyConsumer &Consumer, DependencyActionController &Controller,
35 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
36 std::optional<StringRef> ModuleName = std::nullopt)
37 : Service(Service), WorkingDirectory(WorkingDirectory),
38 Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {}
39 bool runInvocation(std::string Executable,
40 std::unique_ptr<CompilerInvocation> Invocation,
41 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
42 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
43 DiagnosticConsumer *DiagConsumer);
44
45 bool hasScanned() const { return Scanned; }
46
47private:
48 DependencyScanningService &Service;
49 StringRef WorkingDirectory;
50 DependencyConsumer &Consumer;
51 DependencyActionController &Controller;
52 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
53 std::optional<CompilerInstance> ScanInstanceStorage;
54 std::shared_ptr<ModuleDepCollector> MDC;
55 bool Scanned = false;
56};
57
58// Helper functions and data types.
59std::unique_ptr<DiagnosticOptions>
60createDiagOptions(ArrayRef<std::string> CommandLine);
61
62struct DiagnosticsEngineWithDiagOpts {
63 // We need to bound the lifetime of the DiagOpts used to create the
64 // DiganosticsEngine with the DiagnosticsEngine itself.
65 std::unique_ptr<DiagnosticOptions> DiagOpts;
66 IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine;
67
68 DiagnosticsEngineWithDiagOpts(ArrayRef<std::string> CommandLine,
69 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
70 DiagnosticConsumer &DC);
71};
72
73struct TextDiagnosticsPrinterWithOutput {
74 // We need to bound the lifetime of the data that supports the DiagPrinter
75 // with it together so they have the same lifetime.
76 std::string DiagnosticOutput;
77 llvm::raw_string_ostream DiagnosticsOS;
78 std::unique_ptr<DiagnosticOptions> DiagOpts;
79 TextDiagnosticPrinter DiagPrinter;
80
81 TextDiagnosticsPrinterWithOutput(ArrayRef<std::string> CommandLine)
82 : DiagnosticsOS(DiagnosticOutput),
83 DiagOpts(createDiagOptions(CommandLine)),
84 DiagPrinter(DiagnosticsOS, *DiagOpts) {}
85};
86
87std::unique_ptr<CompilerInvocation>
88createCompilerInvocation(ArrayRef<std::string> CommandLine,
89 DiagnosticsEngine &Diags);
90
91/// Canonicalizes command-line macro defines (e.g. removing "-DX -UX").
92void canonicalizeDefines(PreprocessorOptions &PPOpts);
93
94/// Creates a CompilerInvocation suitable for the dependency scanner.
95std::shared_ptr<CompilerInvocation>
96createScanCompilerInvocation(const CompilerInvocation &Invocation,
97 const DependencyScanningService &Service,
98 DependencyActionController &Controller);
99
100/// Creates dependency output options to be reported to the dependency consumer,
101/// deducing missing information if necessary.
102std::unique_ptr<DependencyOutputOptions>
103createDependencyOutputOptions(const CompilerInvocation &Invocation);
104
105void initializeScanCompilerInstance(
106 CompilerInstance &ScanInstance,
107 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
108 DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service,
109 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS);
110
111SmallVector<StringRef>
112getInitialStableDirs(const CompilerInstance &ScanInstance);
113
114std::optional<PrebuiltModulesAttrsMap>
115computePrebuiltModulesASTMap(CompilerInstance &ScanInstance,
116 SmallVector<StringRef> &StableDirs);
117
118/// Create the dependency collector that will collect the produced
119/// dependencies. May return the created ModuleDepCollector depending
120/// on the scanning format.
121std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector(
122 CompilerInstance &ScanInstance,
123 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
124 StringRef WorkingDirectory, DependencyConsumer &Consumer,
125 DependencyScanningService &Service, CompilerInvocation &Inv,
126 DependencyActionController &Controller,
127 PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
128 llvm::SmallVector<StringRef> &StableDirs);
129} // namespace dependencies
130} // namespace clang
131
132#endif // LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H
133