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