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/Driver/Compilation.h"
15#include "clang/Driver/Driver.h"
16#include "clang/Frontend/CompilerInstance.h"
17#include "clang/Frontend/CompilerInvocation.h"
18#include "clang/Frontend/TextDiagnosticPrinter.h"
19#include "clang/Serialization/ObjectFilePCHContainerReader.h"
20#include "llvm/Support/VirtualFileSystem.h"
21
22namespace clang {
23class DiagnosticConsumer;
24
25namespace dependencies {
26class DependencyScanningService;
27class DependencyScanningWorker;
28
29class DependencyConsumer;
30class DependencyActionController;
31class DependencyScanningWorkerFilesystem;
32
33class DependencyScanningAction {
34public:
35 DependencyScanningAction(
36 DependencyScanningService &Service, StringRef WorkingDirectory,
37 DependencyConsumer &Consumer, DependencyActionController &Controller,
38 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS,
39 std::optional<StringRef> ModuleName = std::nullopt)
40 : Service(Service), WorkingDirectory(WorkingDirectory),
41 Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {}
42 bool runInvocation(std::string Executable,
43 std::unique_ptr<CompilerInvocation> Invocation,
44 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
45 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
46 DiagnosticConsumer *DiagConsumer);
47
48 bool hasScanned() const { return Scanned; }
49 bool hasDiagConsumerFinished() const { return DiagConsumerFinished; }
50
51private:
52 DependencyScanningService &Service;
53 StringRef WorkingDirectory;
54 DependencyConsumer &Consumer;
55 DependencyActionController &Controller;
56 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS;
57 std::optional<CompilerInstance> ScanInstanceStorage;
58 std::shared_ptr<ModuleDepCollector> MDC;
59 bool Scanned = false;
60 bool DiagConsumerFinished = false;
61};
62
63// Helper functions and data types.
64std::unique_ptr<DiagnosticOptions>
65createDiagOptions(ArrayRef<std::string> CommandLine);
66
67struct DiagnosticsEngineWithDiagOpts {
68 // We need to bound the lifetime of the DiagOpts used to create the
69 // DiganosticsEngine with the DiagnosticsEngine itself.
70 std::unique_ptr<DiagnosticOptions> DiagOpts;
71 IntrusiveRefCntPtr<DiagnosticsEngine> DiagEngine;
72
73 DiagnosticsEngineWithDiagOpts(ArrayRef<std::string> CommandLine,
74 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
75 DiagnosticConsumer &DC);
76};
77
78struct TextDiagnosticsPrinterWithOutput {
79 // We need to bound the lifetime of the data that supports the DiagPrinter
80 // with it together so they have the same lifetime.
81 std::string DiagnosticOutput;
82 llvm::raw_string_ostream DiagnosticsOS;
83 std::unique_ptr<DiagnosticOptions> DiagOpts;
84 TextDiagnosticPrinter DiagPrinter;
85
86 TextDiagnosticsPrinterWithOutput(ArrayRef<std::string> CommandLine)
87 : DiagnosticsOS(DiagnosticOutput),
88 DiagOpts(createDiagOptions(CommandLine)),
89 DiagPrinter(DiagnosticsOS, *DiagOpts) {}
90};
91
92std::unique_ptr<CompilerInvocation>
93createCompilerInvocation(ArrayRef<std::string> CommandLine,
94 DiagnosticsEngine &Diags);
95
96void initializeScanCompilerInstance(
97 CompilerInstance &ScanInstance,
98 IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
99 DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service,
100 IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> DepFS);
101
102SmallVector<StringRef>
103getInitialStableDirs(const CompilerInstance &ScanInstance);
104
105std::optional<PrebuiltModulesAttrsMap>
106computePrebuiltModulesASTMap(CompilerInstance &ScanInstance,
107 SmallVector<StringRef> &StableDirs);
108
109/// Create the dependency collector that will collect the produced
110/// dependencies. May return the created ModuleDepCollector depending
111/// on the scanning format.
112std::shared_ptr<ModuleDepCollector> initializeScanInstanceDependencyCollector(
113 CompilerInstance &ScanInstance,
114 std::unique_ptr<DependencyOutputOptions> DepOutputOpts,
115 StringRef WorkingDirectory, DependencyConsumer &Consumer,
116 DependencyScanningService &Service, CompilerInvocation &Inv,
117 DependencyActionController &Controller,
118 PrebuiltModulesAttrsMap PrebuiltModulesASTMap,
119 llvm::SmallVector<StringRef> &StableDirs);
120
121class CompilerInstanceWithContext {
122 // Context
123 DependencyScanningWorker &Worker;
124 llvm::StringRef CWD;
125 std::vector<std::string> CommandLine;
126
127 // Context - Diagnostics engine.
128 DiagnosticConsumer *DiagConsumer = nullptr;
129 std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithCmdAndOpts;
130
131 // Context - compiler invocation
132 std::unique_ptr<CompilerInvocation> OriginalInvocation;
133
134 // Context - output options
135 std::unique_ptr<DependencyOutputOptions> OutputOpts;
136
137 // Context - stable directory handling
138 llvm::SmallVector<StringRef> StableDirs;
139 PrebuiltModulesAttrsMap PrebuiltModuleASTMap;
140
141 // Compiler Instance
142 std::unique_ptr<CompilerInstance> CIPtr;
143
144 // Source location offset.
145 int32_t SrcLocOffset = 0;
146
147public:
148 CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD,
149 const std::vector<std::string> &CMD)
150 : Worker(Worker), CWD(CWD), CommandLine(CMD) {};
151
152 // The three methods below returns false when they fail, with the detail
153 // accumulated in \c DiagEngineWithDiagOpts's diagnostic consumer.
154 bool initialize(
155 std::unique_ptr<DiagnosticsEngineWithDiagOpts> DiagEngineWithDiagOpts,
156 IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS);
157 bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer,
158 DependencyActionController &Controller);
159 bool finalize();
160};
161} // namespace dependencies
162} // namespace clang
163
164#endif // LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H
165