diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h | 190 |
1 files changed, 152 insertions, 38 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h index f88dc472c80b..cb9476d1550d 100644 --- a/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h +++ b/contrib/llvm-project/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h @@ -6,22 +6,35 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H -#define LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H +#ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H +#define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H #include "clang/Tooling/DependencyScanning/DependencyScanningService.h" #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h" #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h" #include "clang/Tooling/JSONCompilationDatabase.h" -#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/MapVector.h" +#include <optional> #include <string> +#include <vector> -namespace clang{ -namespace tooling{ -namespace dependencies{ +namespace clang { +namespace tooling { +namespace dependencies { + +/// A callback to lookup module outputs for "-fmodule-file=", "-o" etc. +using LookupModuleOutputCallback = + llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>; + +/// Graph of modular dependencies. +using ModuleDepsGraph = std::vector<ModuleDeps>; /// The full dependencies and module graph for a specific input. -struct FullDependencies { +struct TranslationUnitDeps { + /// The graph of direct and transitive modular dependencies. + ModuleDepsGraph ModuleGraph; + /// The identifier of the C++20 module this translation unit exports. /// /// If the translation unit is not a module then \c ID.ModuleName is empty. @@ -42,30 +55,22 @@ struct FullDependencies { /// determined that the differences are benign for this compilation. std::vector<ModuleID> ClangModuleDeps; - /// Get additional arguments suitable for appending to the original Clang - /// command line. + /// The sequence of commands required to build the translation unit. Commands + /// should be executed in order. /// - /// \param LookupPCMPath This function is called to fill in "-fmodule-file=" - /// arguments and the "-o" argument. It needs to return - /// a path for where the PCM for the given module is to - /// be located. - /// \param LookupModuleDeps This function is called to collect the full - /// transitive set of dependencies for this - /// compilation and fill in "-fmodule-map-file=" - /// arguments. - std::vector<std::string> getAdditionalArgs( - std::function<StringRef(ModuleID)> LookupPCMPath, - std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const; - - /// Get additional arguments suitable for appending to the original Clang - /// command line, excluding arguments containing modules-related paths: - /// "-fmodule-file=", "-fmodule-map-file=". - std::vector<std::string> getAdditionalArgsWithoutModulePaths() const; + /// FIXME: If we add support for multi-arch builds in clang-scan-deps, we + /// should make the dependencies between commands explicit to enable parallel + /// builds of each architecture. + std::vector<Command> Commands; + + /// Deprecated driver command-line. This will be removed in a future version. + std::vector<std::string> DriverCommandLine; }; -struct FullDependenciesResult { - FullDependencies FullDeps; - std::vector<ModuleDeps> DiscoveredModules; +struct P1689Rule { + std::string PrimaryOutput; + std::optional<P1689ModuleInfo> Provides; + std::vector<P1689ModuleInfo> Requires; }; /// The high-level implementation of the dependency discovery tool that runs on @@ -73,7 +78,9 @@ struct FullDependenciesResult { class DependencyScanningTool { public: /// Construct a dependency scanning tool. - DependencyScanningTool(DependencyScanningService &Service); + DependencyScanningTool(DependencyScanningService &Service, + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = + llvm::vfs::createPhysicalFileSystem()); /// Print out the dependency information into a string using the dependency /// file format that is specified in the options (-MD is the default) and @@ -82,30 +89,137 @@ public: /// \returns A \c StringError with the diagnostic output if clang errors /// occurred, dependency file contents otherwise. llvm::Expected<std::string> - getDependencyFile(const tooling::CompilationDatabase &Compilations, - StringRef CWD); + getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD); - /// Collect the full module dependency graph for the input, ignoring any - /// modules which have already been seen. + /// Collect the module dependency in P1689 format for C++20 named modules. + /// + /// \param MakeformatOutput The output parameter for dependency information + /// in make format if the command line requires to generate make-format + /// dependency information by `-MD -MF <dep_file>`. + /// + /// \param MakeformatOutputPath The output parameter for the path to + /// \param MakeformatOutput. + /// + /// \returns A \c StringError with the diagnostic output if clang errors + /// occurred, P1689 dependency format rules otherwise. + llvm::Expected<P1689Rule> + getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, + StringRef CWD, std::string &MakeformatOutput, + std::string &MakeformatOutputPath); + llvm::Expected<P1689Rule> + getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, + StringRef CWD) { + std::string MakeformatOutput; + std::string MakeformatOutputPath; + + return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput, + MakeformatOutputPath); + } + + /// Given a Clang driver command-line for a translation unit, gather the + /// modular dependencies and return the information needed for explicit build. /// /// \param AlreadySeen This stores modules which have previously been /// reported. Use the same instance for all calls to this /// function for a single \c DependencyScanningTool in a /// single build. Use a different one for different tools, /// and clear it between builds. + /// \param LookupModuleOutput This function is called to fill in + /// "-fmodule-file=", "-o" and other output + /// arguments for dependencies. /// /// \returns a \c StringError with the diagnostic output if clang errors - /// occurred, \c FullDependencies otherwise. - llvm::Expected<FullDependenciesResult> - getFullDependencies(const tooling::CompilationDatabase &Compilations, - StringRef CWD, const llvm::StringSet<> &AlreadySeen); + /// occurred, \c TranslationUnitDeps otherwise. + llvm::Expected<TranslationUnitDeps> + getTranslationUnitDependencies(const std::vector<std::string> &CommandLine, + StringRef CWD, + const llvm::DenseSet<ModuleID> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput); + + /// Given a compilation context specified via the Clang driver command-line, + /// gather modular dependencies of module with the given name, and return the + /// information needed for explicit build. + llvm::Expected<ModuleDepsGraph> getModuleDependencies( + StringRef ModuleName, const std::vector<std::string> &CommandLine, + StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen, + LookupModuleOutputCallback LookupModuleOutput); private: DependencyScanningWorker Worker; }; +class FullDependencyConsumer : public DependencyConsumer { +public: + FullDependencyConsumer(const llvm::DenseSet<ModuleID> &AlreadySeen) + : AlreadySeen(AlreadySeen) {} + + void handleBuildCommand(Command Cmd) override { + Commands.push_back(std::move(Cmd)); + } + + void handleDependencyOutputOpts(const DependencyOutputOptions &) override {} + + void handleFileDependency(StringRef File) override { + Dependencies.push_back(std::string(File)); + } + + void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override { + PrebuiltModuleDeps.emplace_back(std::move(PMD)); + } + + void handleModuleDependency(ModuleDeps MD) override { + ClangModuleDeps[MD.ID] = std::move(MD); + } + + void handleDirectModuleDependency(ModuleID ID) override { + DirectModuleDeps.push_back(ID); + } + + void handleContextHash(std::string Hash) override { + ContextHash = std::move(Hash); + } + + TranslationUnitDeps takeTranslationUnitDeps(); + ModuleDepsGraph takeModuleGraphDeps(); + +private: + std::vector<std::string> Dependencies; + std::vector<PrebuiltModuleDep> PrebuiltModuleDeps; + llvm::MapVector<ModuleID, ModuleDeps> ClangModuleDeps; + std::vector<ModuleID> DirectModuleDeps; + std::vector<Command> Commands; + std::string ContextHash; + std::vector<std::string> OutputPaths; + const llvm::DenseSet<ModuleID> &AlreadySeen; +}; + +/// A simple dependency action controller that uses a callback. If no callback +/// is provided, it is assumed that looking up module outputs is unreachable. +class CallbackActionController : public DependencyActionController { +public: + virtual ~CallbackActionController(); + + CallbackActionController(LookupModuleOutputCallback LMO) + : LookupModuleOutput(std::move(LMO)) { + if (!LookupModuleOutput) { + LookupModuleOutput = [](const ModuleID &, + ModuleOutputKind) -> std::string { + llvm::report_fatal_error("unexpected call to lookupModuleOutput"); + }; + } + } + + std::string lookupModuleOutput(const ModuleID &ID, + ModuleOutputKind Kind) override { + return LookupModuleOutput(ID, Kind); + } + +private: + LookupModuleOutputCallback LookupModuleOutput; +}; + } // end namespace dependencies } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_DEPENDENCY_SCANNING_TOOL_H +#endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H |