Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:11

0001 //===- DependencyScanningTool.h - clang-scan-deps service -----------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
0010 #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
0011 
0012 #include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
0013 #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
0014 #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
0015 #include "clang/Tooling/JSONCompilationDatabase.h"
0016 #include "llvm/ADT/DenseSet.h"
0017 #include "llvm/ADT/MapVector.h"
0018 #include <functional>
0019 #include <optional>
0020 #include <string>
0021 #include <vector>
0022 
0023 namespace clang {
0024 namespace tooling {
0025 namespace dependencies {
0026 
0027 /// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
0028 using LookupModuleOutputCallback =
0029     std::function<std::string(const ModuleID &, ModuleOutputKind)>;
0030 
0031 /// Graph of modular dependencies.
0032 using ModuleDepsGraph = std::vector<ModuleDeps>;
0033 
0034 /// The full dependencies and module graph for a specific input.
0035 struct TranslationUnitDeps {
0036   /// The graph of direct and transitive modular dependencies.
0037   ModuleDepsGraph ModuleGraph;
0038 
0039   /// The identifier of the C++20 module this translation unit exports.
0040   ///
0041   /// If the translation unit is not a module then \c ID.ModuleName is empty.
0042   ModuleID ID;
0043 
0044   /// A collection of absolute paths to files that this translation unit
0045   /// directly depends on, not including transitive dependencies.
0046   std::vector<std::string> FileDeps;
0047 
0048   /// A collection of prebuilt modules this translation unit directly depends
0049   /// on, not including transitive dependencies.
0050   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
0051 
0052   /// A list of modules this translation unit directly depends on, not including
0053   /// transitive dependencies.
0054   ///
0055   /// This may include modules with a different context hash when it can be
0056   /// determined that the differences are benign for this compilation.
0057   std::vector<ModuleID> ClangModuleDeps;
0058 
0059   /// The sequence of commands required to build the translation unit. Commands
0060   /// should be executed in order.
0061   ///
0062   /// FIXME: If we add support for multi-arch builds in clang-scan-deps, we
0063   /// should make the dependencies between commands explicit to enable parallel
0064   /// builds of each architecture.
0065   std::vector<Command> Commands;
0066 
0067   /// Deprecated driver command-line. This will be removed in a future version.
0068   std::vector<std::string> DriverCommandLine;
0069 };
0070 
0071 struct P1689Rule {
0072   std::string PrimaryOutput;
0073   std::optional<P1689ModuleInfo> Provides;
0074   std::vector<P1689ModuleInfo> Requires;
0075 };
0076 
0077 /// The high-level implementation of the dependency discovery tool that runs on
0078 /// an individual worker thread.
0079 class DependencyScanningTool {
0080 public:
0081   /// Construct a dependency scanning tool.
0082   DependencyScanningTool(DependencyScanningService &Service,
0083                          llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
0084                              llvm::vfs::createPhysicalFileSystem());
0085 
0086   /// Print out the dependency information into a string using the dependency
0087   /// file format that is specified in the options (-MD is the default) and
0088   /// return it.
0089   ///
0090   /// \returns A \c StringError with the diagnostic output if clang errors
0091   /// occurred, dependency file contents otherwise.
0092   llvm::Expected<std::string>
0093   getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD);
0094 
0095   /// Collect the module dependency in P1689 format for C++20 named modules.
0096   ///
0097   /// \param MakeformatOutput The output parameter for dependency information
0098   /// in make format if the command line requires to generate make-format
0099   /// dependency information by `-MD -MF <dep_file>`.
0100   ///
0101   /// \param MakeformatOutputPath The output parameter for the path to
0102   /// \param MakeformatOutput.
0103   ///
0104   /// \returns A \c StringError with the diagnostic output if clang errors
0105   /// occurred, P1689 dependency format rules otherwise.
0106   llvm::Expected<P1689Rule>
0107   getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command,
0108                                StringRef CWD, std::string &MakeformatOutput,
0109                                std::string &MakeformatOutputPath);
0110   llvm::Expected<P1689Rule>
0111   getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command,
0112                                StringRef CWD) {
0113     std::string MakeformatOutput;
0114     std::string MakeformatOutputPath;
0115 
0116     return getP1689ModuleDependencyFile(Command, CWD, MakeformatOutput,
0117                                         MakeformatOutputPath);
0118   }
0119 
0120   /// Given a Clang driver command-line for a translation unit, gather the
0121   /// modular dependencies and return the information needed for explicit build.
0122   ///
0123   /// \param AlreadySeen This stores modules which have previously been
0124   ///                    reported. Use the same instance for all calls to this
0125   ///                    function for a single \c DependencyScanningTool in a
0126   ///                    single build. Use a different one for different tools,
0127   ///                    and clear it between builds.
0128   /// \param LookupModuleOutput This function is called to fill in
0129   ///                           "-fmodule-file=", "-o" and other output
0130   ///                           arguments for dependencies.
0131   ///
0132   /// \returns a \c StringError with the diagnostic output if clang errors
0133   /// occurred, \c TranslationUnitDeps otherwise.
0134   llvm::Expected<TranslationUnitDeps>
0135   getTranslationUnitDependencies(const std::vector<std::string> &CommandLine,
0136                                  StringRef CWD,
0137                                  const llvm::DenseSet<ModuleID> &AlreadySeen,
0138                                  LookupModuleOutputCallback LookupModuleOutput);
0139 
0140   /// Given a compilation context specified via the Clang driver command-line,
0141   /// gather modular dependencies of module with the given name, and return the
0142   /// information needed for explicit build.
0143   llvm::Expected<ModuleDepsGraph> getModuleDependencies(
0144       StringRef ModuleName, const std::vector<std::string> &CommandLine,
0145       StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
0146       LookupModuleOutputCallback LookupModuleOutput);
0147 
0148   llvm::vfs::FileSystem &getWorkerVFS() const { return Worker.getVFS(); }
0149 
0150 private:
0151   DependencyScanningWorker Worker;
0152 };
0153 
0154 class FullDependencyConsumer : public DependencyConsumer {
0155 public:
0156   FullDependencyConsumer(const llvm::DenseSet<ModuleID> &AlreadySeen)
0157       : AlreadySeen(AlreadySeen) {}
0158 
0159   void handleBuildCommand(Command Cmd) override {
0160     Commands.push_back(std::move(Cmd));
0161   }
0162 
0163   void handleDependencyOutputOpts(const DependencyOutputOptions &) override {}
0164 
0165   void handleFileDependency(StringRef File) override {
0166     Dependencies.push_back(std::string(File));
0167   }
0168 
0169   void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
0170     PrebuiltModuleDeps.emplace_back(std::move(PMD));
0171   }
0172 
0173   void handleModuleDependency(ModuleDeps MD) override {
0174     ClangModuleDeps[MD.ID] = std::move(MD);
0175   }
0176 
0177   void handleDirectModuleDependency(ModuleID ID) override {
0178     DirectModuleDeps.push_back(ID);
0179   }
0180 
0181   void handleContextHash(std::string Hash) override {
0182     ContextHash = std::move(Hash);
0183   }
0184 
0185   TranslationUnitDeps takeTranslationUnitDeps();
0186   ModuleDepsGraph takeModuleGraphDeps();
0187 
0188 private:
0189   std::vector<std::string> Dependencies;
0190   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
0191   llvm::MapVector<ModuleID, ModuleDeps> ClangModuleDeps;
0192   std::vector<ModuleID> DirectModuleDeps;
0193   std::vector<Command> Commands;
0194   std::string ContextHash;
0195   std::vector<std::string> OutputPaths;
0196   const llvm::DenseSet<ModuleID> &AlreadySeen;
0197 };
0198 
0199 /// A simple dependency action controller that uses a callback. If no callback
0200 /// is provided, it is assumed that looking up module outputs is unreachable.
0201 class CallbackActionController : public DependencyActionController {
0202 public:
0203   virtual ~CallbackActionController();
0204 
0205   CallbackActionController(LookupModuleOutputCallback LMO)
0206       : LookupModuleOutput(std::move(LMO)) {
0207     if (!LookupModuleOutput) {
0208       LookupModuleOutput = [](const ModuleID &,
0209                               ModuleOutputKind) -> std::string {
0210         llvm::report_fatal_error("unexpected call to lookupModuleOutput");
0211       };
0212     }
0213   }
0214 
0215   std::string lookupModuleOutput(const ModuleID &ID,
0216                                  ModuleOutputKind Kind) override {
0217     return LookupModuleOutput(ID, Kind);
0218   }
0219 
0220 private:
0221   LookupModuleOutputCallback LookupModuleOutput;
0222 };
0223 
0224 } // end namespace dependencies
0225 } // end namespace tooling
0226 } // end namespace clang
0227 
0228 #endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H