//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H #define LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H #include "clang/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/DependencyScanning/ModuleDepCollector.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" #include "llvm/Support/VirtualFileSystem.h" namespace clang { class DiagnosticConsumer; namespace dependencies { class DependencyScanningService; class DependencyScanningWorker; class DependencyConsumer; class DependencyActionController; class DependencyScanningWorkerFilesystem; class DependencyScanningAction { public: DependencyScanningAction( DependencyScanningService &Service, StringRef WorkingDirectory, DependencyConsumer &Consumer, DependencyActionController &Controller, IntrusiveRefCntPtr DepFS, std::optional ModuleName = std::nullopt) : Service(Service), WorkingDirectory(WorkingDirectory), Consumer(Consumer), Controller(Controller), DepFS(std::move(DepFS)) {} bool runInvocation(std::string Executable, std::unique_ptr Invocation, IntrusiveRefCntPtr FS, std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer); bool hasScanned() const { return Scanned; } bool hasDiagConsumerFinished() const { return DiagConsumerFinished; } private: DependencyScanningService &Service; StringRef WorkingDirectory; DependencyConsumer &Consumer; DependencyActionController &Controller; IntrusiveRefCntPtr DepFS; std::optional ScanInstanceStorage; std::shared_ptr MDC; bool Scanned = false; bool DiagConsumerFinished = false; }; // Helper functions and data types. std::unique_ptr createDiagOptions(ArrayRef CommandLine); struct DiagnosticsEngineWithDiagOpts { // We need to bound the lifetime of the DiagOpts used to create the // DiganosticsEngine with the DiagnosticsEngine itself. std::unique_ptr DiagOpts; IntrusiveRefCntPtr DiagEngine; DiagnosticsEngineWithDiagOpts(ArrayRef CommandLine, IntrusiveRefCntPtr FS, DiagnosticConsumer &DC); }; struct TextDiagnosticsPrinterWithOutput { // We need to bound the lifetime of the data that supports the DiagPrinter // with it together so they have the same lifetime. std::string DiagnosticOutput; llvm::raw_string_ostream DiagnosticsOS; std::unique_ptr DiagOpts; TextDiagnosticPrinter DiagPrinter; TextDiagnosticsPrinterWithOutput(ArrayRef CommandLine) : DiagnosticsOS(DiagnosticOutput), DiagOpts(createDiagOptions(CommandLine)), DiagPrinter(DiagnosticsOS, *DiagOpts) {} }; std::unique_ptr createCompilerInvocation(ArrayRef CommandLine, DiagnosticsEngine &Diags); void initializeScanCompilerInstance( CompilerInstance &ScanInstance, IntrusiveRefCntPtr FS, DiagnosticConsumer *DiagConsumer, DependencyScanningService &Service, IntrusiveRefCntPtr DepFS); SmallVector getInitialStableDirs(const CompilerInstance &ScanInstance); std::optional computePrebuiltModulesASTMap(CompilerInstance &ScanInstance, SmallVector &StableDirs); /// Create the dependency collector that will collect the produced /// dependencies. May return the created ModuleDepCollector depending /// on the scanning format. std::shared_ptr initializeScanInstanceDependencyCollector( CompilerInstance &ScanInstance, std::unique_ptr DepOutputOpts, StringRef WorkingDirectory, DependencyConsumer &Consumer, DependencyScanningService &Service, CompilerInvocation &Inv, DependencyActionController &Controller, PrebuiltModulesAttrsMap PrebuiltModulesASTMap, llvm::SmallVector &StableDirs); class CompilerInstanceWithContext { // Context DependencyScanningWorker &Worker; llvm::StringRef CWD; std::vector CommandLine; // Context - Diagnostics engine. DiagnosticConsumer *DiagConsumer = nullptr; std::unique_ptr DiagEngineWithCmdAndOpts; // Context - compiler invocation std::unique_ptr OriginalInvocation; // Context - output options std::unique_ptr OutputOpts; // Context - stable directory handling llvm::SmallVector StableDirs; PrebuiltModulesAttrsMap PrebuiltModuleASTMap; // Compiler Instance std::unique_ptr CIPtr; // Source location offset. int32_t SrcLocOffset = 0; public: CompilerInstanceWithContext(DependencyScanningWorker &Worker, StringRef CWD, const std::vector &CMD) : Worker(Worker), CWD(CWD), CommandLine(CMD) {}; // The three methods below returns false when they fail, with the detail // accumulated in \c DiagEngineWithDiagOpts's diagnostic consumer. bool initialize( std::unique_ptr DiagEngineWithDiagOpts, IntrusiveRefCntPtr OverlayFS); bool computeDependencies(StringRef ModuleName, DependencyConsumer &Consumer, DependencyActionController &Controller); bool finalize(); }; } // namespace dependencies } // namespace clang #endif // LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNERIMPL_H