//===----------------------------------------------------------------------===// // // 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_DEPENDENCYSCANNINGWORKER_H #define LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNINGWORKER_H #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/DependencyScanning/DependencyScannerImpl.h" #include "clang/DependencyScanning/DependencyScanningService.h" #include "clang/DependencyScanning/ModuleDepCollector.h" #include "clang/Frontend/PCHContainerOperations.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/VirtualFileSystem.h" #include #include namespace clang { class DependencyOutputOptions; namespace dependencies { class DependencyScanningWorkerFilesystem; class CompilerInstanceWithContext; /// A command-line tool invocation that is part of building a TU. /// /// \see TranslationUnitDeps::Commands. struct Command { std::string Executable; std::vector Arguments; }; class DependencyConsumer { public: virtual ~DependencyConsumer() {} virtual void handleProvidedAndRequiredStdCXXModules( std::optional Provided, std::vector Requires) {} virtual void handleBuildCommand(Command Cmd) {} virtual void handleDependencyOutputOpts(const DependencyOutputOptions &Opts) = 0; virtual void handleFileDependency(StringRef Filename) = 0; virtual void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) = 0; virtual void handleModuleDependency(ModuleDeps MD) = 0; virtual void handleDirectModuleDependency(ModuleID MD) = 0; virtual void handleVisibleModule(std::string ModuleName) = 0; virtual void handleContextHash(std::string Hash) = 0; }; /// Dependency scanner callbacks that are used during scanning to influence the /// behaviour of the scan - for example, to customize the scanned invocations. class DependencyActionController { public: virtual ~DependencyActionController(); virtual std::string lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind Kind) = 0; }; /// An individual dependency scanning worker that is able to run on its own /// thread. /// /// The worker computes the dependencies for the input files by preprocessing /// sources either using a fast mode where the source files are minimized, or /// using the regular processing run. class DependencyScanningWorker { public: /// Construct a dependency scanning worker. /// /// @param Service The parent service. Must outlive the worker. /// @param BaseFS The filesystem for the worker to use. DependencyScanningWorker(DependencyScanningService &Service, IntrusiveRefCntPtr BaseFS); ~DependencyScanningWorker(); /// Run the dependency scanning worker for the given frontend command-line, /// and report the discovered dependencies to the provided consumer. /// /// OverlayFS should be based on the Worker's dependency scanning file-system /// and can be used to provide any input specified on the command-line as /// in-memory file. If no overlay file-system is provided, the Worker's /// dependency scanning file-system is used instead. /// /// \returns false if any errors occurred (with diagnostics reported to /// \c DiagConsumer), true otherwise. bool computeDependencies( StringRef WorkingDirectory, ArrayRef CommandLine, DependencyConsumer &DepConsumer, DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, llvm::IntrusiveRefCntPtr OverlayFS = nullptr); /// Run the dependency scanning tool for all given frontend command-lines, /// and report the discovered dependencies to the provided consumer. /// /// OverlayFS should be based on the Worker's dependency scanning file-system /// and can be used to provide any input specified on the command-line as /// in-memory file. If no overlay file-system is provided, the Worker's /// dependency scanning file-system is used instead. /// /// \returns false if any errors occurred (with diagnostics reported to /// \c DiagConsumer), true otherwise. bool computeDependencies( StringRef WorkingDirectory, ArrayRef> CommandLines, DependencyConsumer &DepConsumer, DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, llvm::IntrusiveRefCntPtr OverlayFS = nullptr); /// The three method below implements a new interface for by name /// dependency scanning. They together enable the dependency scanning worker /// to more effectively perform scanning for a sequence of modules /// by name when the CWD and CommandLine do not change across the queries. /// The initialization function asks the client for a DiagnosticsConsumer /// that it direct the diagnostics to. /// @brief Initializing the context and the compiler instance. /// @param CWD The current working directory used during the scan. /// @param CommandLine The commandline used for the scan. /// @return False if the initializaiton fails. bool initializeCompilerInstanceWithContext(StringRef CWD, ArrayRef CommandLine, DiagnosticConsumer &DC); /// @brief Initializing the context and the compiler instance. /// @param CWD The current working directory used during the scan. /// @param CommandLine The commandline used for the scan. /// @param DiagEngineWithCmdAndOpts Preconfigured diagnostics engine and /// options associated with the cc1 command line. /// @param FS The overlay file system to use for this compiler instance. /// @return False if the initializaiton fails. bool initializeCompilerInstanceWithContext( StringRef CWD, ArrayRef CommandLine, std::unique_ptr DiagEngineWithCmdAndOpts, IntrusiveRefCntPtr OverlayFS); /// @brief Performaces dependency scanning for the module whose name is /// specified. /// @param ModuleName The name of the module whose dependency will be /// scanned. /// @param Consumer The dependency consumer that stores the results. /// @param Controller The controller for the dependency scanning action. /// @return False if the scanner incurs errors. bool computeDependenciesByNameWithContext(StringRef ModuleName, DependencyConsumer &Consumer, DependencyActionController &Controller); /// @brief Finalizes the diagnostics engine and deletes the compiler instance. /// @return False if errors occur during finalization. bool finalizeCompilerInstanceWithContext(); llvm::vfs::FileSystem &getVFS() const { return *DepFS; } private: /// The parent dependency scanning service. DependencyScanningService &Service; std::shared_ptr PCHContainerOps; /// This is the caching (and optionally dependency-directives-providing) VFS /// overlaid on top of the base VFS passed in the constructor. IntrusiveRefCntPtr DepFS; friend CompilerInstanceWithContext; std::unique_ptr CIWithContext; }; std::pair, std::vector> initVFSForTUBufferScanning(IntrusiveRefCntPtr BaseFS, ArrayRef CommandLine, StringRef WorkingDirectory, llvm::MemoryBufferRef TUBuffer); std::pair, std::vector> initVFSForByNameScanning(IntrusiveRefCntPtr BaseFS, ArrayRef CommandLine, StringRef WorkingDirectory, StringRef ModuleName); } // end namespace dependencies } // end namespace clang #endif // LLVM_CLANG_DEPENDENCYSCANNING_DEPENDENCYSCANNINGWORKER_H