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