xref: /openbsd-src/gnu/llvm/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- DependencyScanningTool.h - clang-scan-deps service -----------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9*12c85518Srobert #ifndef LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
10*12c85518Srobert #define LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
11e5dd7070Spatrick 
12e5dd7070Spatrick #include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
13e5dd7070Spatrick #include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
14ec727ea7Spatrick #include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
15e5dd7070Spatrick #include "clang/Tooling/JSONCompilationDatabase.h"
16*12c85518Srobert #include "llvm/ADT/MapVector.h"
17ec727ea7Spatrick #include "llvm/ADT/StringSet.h"
18*12c85518Srobert #include "llvm/ADT/StringMap.h"
19*12c85518Srobert #include <optional>
20e5dd7070Spatrick #include <string>
21*12c85518Srobert #include <vector>
22e5dd7070Spatrick 
23e5dd7070Spatrick namespace clang {
24e5dd7070Spatrick namespace tooling {
25e5dd7070Spatrick namespace dependencies {
26e5dd7070Spatrick 
27*12c85518Srobert /// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
28*12c85518Srobert using LookupModuleOutputCallback =
29*12c85518Srobert     llvm::function_ref<std::string(const ModuleID &, ModuleOutputKind)>;
30*12c85518Srobert 
31ec727ea7Spatrick /// The full dependencies and module graph for a specific input.
32ec727ea7Spatrick struct FullDependencies {
33a9ac8606Spatrick   /// The identifier of the C++20 module this translation unit exports.
34ec727ea7Spatrick   ///
35a9ac8606Spatrick   /// If the translation unit is not a module then \c ID.ModuleName is empty.
36a9ac8606Spatrick   ModuleID ID;
37ec727ea7Spatrick 
38ec727ea7Spatrick   /// A collection of absolute paths to files that this translation unit
39ec727ea7Spatrick   /// directly depends on, not including transitive dependencies.
40ec727ea7Spatrick   std::vector<std::string> FileDeps;
41ec727ea7Spatrick 
42a9ac8606Spatrick   /// A collection of prebuilt modules this translation unit directly depends
43a9ac8606Spatrick   /// on, not including transitive dependencies.
44a9ac8606Spatrick   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
45a9ac8606Spatrick 
46ec727ea7Spatrick   /// A list of modules this translation unit directly depends on, not including
47ec727ea7Spatrick   /// transitive dependencies.
48ec727ea7Spatrick   ///
49ec727ea7Spatrick   /// This may include modules with a different context hash when it can be
50ec727ea7Spatrick   /// determined that the differences are benign for this compilation.
51a9ac8606Spatrick   std::vector<ModuleID> ClangModuleDeps;
52ec727ea7Spatrick 
53*12c85518Srobert   /// The sequence of commands required to build the translation unit. Commands
54*12c85518Srobert   /// should be executed in order.
55ec727ea7Spatrick   ///
56*12c85518Srobert   /// FIXME: If we add support for multi-arch builds in clang-scan-deps, we
57*12c85518Srobert   /// should make the dependencies between commands explicit to enable parallel
58*12c85518Srobert   /// builds of each architecture.
59*12c85518Srobert   std::vector<Command> Commands;
60a9ac8606Spatrick 
61*12c85518Srobert   /// Deprecated driver command-line. This will be removed in a future version.
62*12c85518Srobert   std::vector<std::string> DriverCommandLine;
63ec727ea7Spatrick };
64ec727ea7Spatrick 
65ec727ea7Spatrick struct FullDependenciesResult {
66ec727ea7Spatrick   FullDependencies FullDeps;
67ec727ea7Spatrick   std::vector<ModuleDeps> DiscoveredModules;
68ec727ea7Spatrick };
69ec727ea7Spatrick 
70*12c85518Srobert struct P1689Rule {
71*12c85518Srobert   std::string PrimaryOutput;
72*12c85518Srobert   std::optional<P1689ModuleInfo> Provides;
73*12c85518Srobert   std::vector<P1689ModuleInfo> Requires;
74*12c85518Srobert };
75*12c85518Srobert 
76e5dd7070Spatrick /// The high-level implementation of the dependency discovery tool that runs on
77e5dd7070Spatrick /// an individual worker thread.
78e5dd7070Spatrick class DependencyScanningTool {
79e5dd7070Spatrick public:
80e5dd7070Spatrick   /// Construct a dependency scanning tool.
81*12c85518Srobert   DependencyScanningTool(DependencyScanningService &Service,
82*12c85518Srobert                          llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
83*12c85518Srobert                              llvm::vfs::createPhysicalFileSystem());
84e5dd7070Spatrick 
85e5dd7070Spatrick   /// Print out the dependency information into a string using the dependency
86e5dd7070Spatrick   /// file format that is specified in the options (-MD is the default) and
87*12c85518Srobert   /// return it. If \p ModuleName isn't empty, this function returns the
88*12c85518Srobert   /// dependency information of module \p ModuleName.
89e5dd7070Spatrick   ///
90e5dd7070Spatrick   /// \returns A \c StringError with the diagnostic output if clang errors
91e5dd7070Spatrick   /// occurred, dependency file contents otherwise.
92e5dd7070Spatrick   llvm::Expected<std::string>
93*12c85518Srobert   getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD,
94*12c85518Srobert                     std::optional<StringRef> ModuleName = std::nullopt);
95e5dd7070Spatrick 
96*12c85518Srobert   /// Collect the module dependency in P1689 format for C++20 named modules.
97*12c85518Srobert   ///
98*12c85518Srobert   /// \param MakeformatOutput The output parameter for dependency information
99*12c85518Srobert   /// in make format if the command line requires to generate make-format
100*12c85518Srobert   /// dependency information by `-MD -MF <dep_file>`.
101*12c85518Srobert   ///
102*12c85518Srobert   /// \param MakeformatOutputPath The output parameter for the path to
103*12c85518Srobert   /// \param MakeformatOutput.
104*12c85518Srobert   ///
105*12c85518Srobert   /// \returns A \c StringError with the diagnostic output if clang errors
106*12c85518Srobert   /// occurred, P1689 dependency format rules otherwise.
107*12c85518Srobert   llvm::Expected<P1689Rule>
108*12c85518Srobert   getP1689ModuleDependencyFile(
109*12c85518Srobert       const clang::tooling::CompileCommand &Command, StringRef CWD,
110*12c85518Srobert       std::string &MakeformatOutput, std::string &MakeformatOutputPath);
111*12c85518Srobert 
112*12c85518Srobert   /// Given a Clang driver command-line for a translation unit, gather the
113*12c85518Srobert   /// modular dependencies and return the information needed for explicit build.
114ec727ea7Spatrick   ///
115a9ac8606Spatrick   /// \param AlreadySeen This stores modules which have previously been
116a9ac8606Spatrick   ///                    reported. Use the same instance for all calls to this
117a9ac8606Spatrick   ///                    function for a single \c DependencyScanningTool in a
118a9ac8606Spatrick   ///                    single build. Use a different one for different tools,
119a9ac8606Spatrick   ///                    and clear it between builds.
120*12c85518Srobert   /// \param LookupModuleOutput This function is called to fill in
121*12c85518Srobert   ///                           "-fmodule-file=", "-o" and other output
122*12c85518Srobert   ///                           arguments for dependencies.
123ec727ea7Spatrick   ///
124ec727ea7Spatrick   /// \returns a \c StringError with the diagnostic output if clang errors
125ec727ea7Spatrick   /// occurred, \c FullDependencies otherwise.
126ec727ea7Spatrick   llvm::Expected<FullDependenciesResult>
127*12c85518Srobert   getFullDependencies(const std::vector<std::string> &CommandLine,
128*12c85518Srobert                       StringRef CWD, const llvm::StringSet<> &AlreadySeen,
129*12c85518Srobert                       LookupModuleOutputCallback LookupModuleOutput,
130*12c85518Srobert                       std::optional<StringRef> ModuleName = std::nullopt);
131*12c85518Srobert 
132*12c85518Srobert   llvm::Expected<FullDependenciesResult> getFullDependenciesLegacyDriverCommand(
133*12c85518Srobert       const std::vector<std::string> &CommandLine, StringRef CWD,
134*12c85518Srobert       const llvm::StringSet<> &AlreadySeen,
135*12c85518Srobert       LookupModuleOutputCallback LookupModuleOutput,
136*12c85518Srobert       std::optional<StringRef> ModuleName = std::nullopt);
137ec727ea7Spatrick 
138e5dd7070Spatrick private:
139e5dd7070Spatrick   DependencyScanningWorker Worker;
140e5dd7070Spatrick };
141e5dd7070Spatrick 
142*12c85518Srobert class FullDependencyConsumer : public DependencyConsumer {
143*12c85518Srobert public:
FullDependencyConsumer(const llvm::StringSet<> & AlreadySeen,LookupModuleOutputCallback LookupModuleOutput,bool EagerLoadModules)144*12c85518Srobert   FullDependencyConsumer(const llvm::StringSet<> &AlreadySeen,
145*12c85518Srobert                          LookupModuleOutputCallback LookupModuleOutput,
146*12c85518Srobert                          bool EagerLoadModules)
147*12c85518Srobert       : AlreadySeen(AlreadySeen), LookupModuleOutput(LookupModuleOutput),
148*12c85518Srobert         EagerLoadModules(EagerLoadModules) {}
149*12c85518Srobert 
handleBuildCommand(Command Cmd)150*12c85518Srobert   void handleBuildCommand(Command Cmd) override {
151*12c85518Srobert     Commands.push_back(std::move(Cmd));
152*12c85518Srobert   }
153*12c85518Srobert 
handleDependencyOutputOpts(const DependencyOutputOptions &)154*12c85518Srobert   void handleDependencyOutputOpts(const DependencyOutputOptions &) override {}
155*12c85518Srobert 
handleFileDependency(StringRef File)156*12c85518Srobert   void handleFileDependency(StringRef File) override {
157*12c85518Srobert     Dependencies.push_back(std::string(File));
158*12c85518Srobert   }
159*12c85518Srobert 
handlePrebuiltModuleDependency(PrebuiltModuleDep PMD)160*12c85518Srobert   void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
161*12c85518Srobert     PrebuiltModuleDeps.emplace_back(std::move(PMD));
162*12c85518Srobert   }
163*12c85518Srobert 
handleModuleDependency(ModuleDeps MD)164*12c85518Srobert   void handleModuleDependency(ModuleDeps MD) override {
165*12c85518Srobert     ClangModuleDeps[MD.ID.ContextHash + MD.ID.ModuleName] = std::move(MD);
166*12c85518Srobert   }
167*12c85518Srobert 
handleContextHash(std::string Hash)168*12c85518Srobert   void handleContextHash(std::string Hash) override {
169*12c85518Srobert     ContextHash = std::move(Hash);
170*12c85518Srobert   }
171*12c85518Srobert 
lookupModuleOutput(const ModuleID & ID,ModuleOutputKind Kind)172*12c85518Srobert   std::string lookupModuleOutput(const ModuleID &ID,
173*12c85518Srobert                                  ModuleOutputKind Kind) override {
174*12c85518Srobert     return LookupModuleOutput(ID, Kind);
175*12c85518Srobert   }
176*12c85518Srobert 
177*12c85518Srobert   FullDependenciesResult getFullDependenciesLegacyDriverCommand(
178*12c85518Srobert       const std::vector<std::string> &OriginalCommandLine) const;
179*12c85518Srobert 
180*12c85518Srobert   FullDependenciesResult takeFullDependencies();
181*12c85518Srobert 
182*12c85518Srobert private:
183*12c85518Srobert   std::vector<std::string> Dependencies;
184*12c85518Srobert   std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
185*12c85518Srobert   llvm::MapVector<std::string, ModuleDeps, llvm::StringMap<unsigned>>
186*12c85518Srobert       ClangModuleDeps;
187*12c85518Srobert   std::vector<Command> Commands;
188*12c85518Srobert   std::string ContextHash;
189*12c85518Srobert   std::vector<std::string> OutputPaths;
190*12c85518Srobert   const llvm::StringSet<> &AlreadySeen;
191*12c85518Srobert   LookupModuleOutputCallback LookupModuleOutput;
192*12c85518Srobert   bool EagerLoadModules;
193*12c85518Srobert };
194*12c85518Srobert 
195e5dd7070Spatrick } // end namespace dependencies
196e5dd7070Spatrick } // end namespace tooling
197e5dd7070Spatrick } // end namespace clang
198e5dd7070Spatrick 
199*12c85518Srobert #endif // LLVM_CLANG_TOOLING_DEPENDENCYSCANNING_DEPENDENCYSCANNINGTOOL_H
200