clang  19.0.0git
DependencyScanningTool.cpp
Go to the documentation of this file.
1 //===- DependencyScanningTool.cpp - clang-scan-deps service ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/Frontend/Utils.h"
11 #include <optional>
12 
13 using namespace clang;
14 using namespace tooling;
15 using namespace dependencies;
16 
20  : Worker(Service, std::move(FS)) {}
21 
22 namespace {
23 /// Prints out all of the gathered dependencies into a string.
24 class MakeDependencyPrinterConsumer : public DependencyConsumer {
25 public:
26  void handleBuildCommand(Command) override {}
27 
28  void
29  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
30  this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
31  }
32 
33  void handleFileDependency(StringRef File) override {
34  Dependencies.push_back(std::string(File));
35  }
36 
37  // These are ignored for the make format as it can't support the full
38  // set of deps, and handleFileDependency handles enough for implicitly
39  // built modules to work.
40  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {}
41  void handleModuleDependency(ModuleDeps MD) override {}
42  void handleDirectModuleDependency(ModuleID ID) override {}
43  void handleContextHash(std::string Hash) override {}
44 
45  void printDependencies(std::string &S) {
46  assert(Opts && "Handled dependency output options.");
47 
48  class DependencyPrinter : public DependencyFileGenerator {
49  public:
50  DependencyPrinter(DependencyOutputOptions &Opts,
51  ArrayRef<std::string> Dependencies)
52  : DependencyFileGenerator(Opts) {
53  for (const auto &Dep : Dependencies)
54  addDependency(Dep);
55  }
56 
57  void printDependencies(std::string &S) {
58  llvm::raw_string_ostream OS(S);
59  outputDependencyFile(OS);
60  }
61  };
62 
63  DependencyPrinter Generator(*Opts, Dependencies);
64  Generator.printDependencies(S);
65  }
66 
67 protected:
68  std::unique_ptr<DependencyOutputOptions> Opts;
69  std::vector<std::string> Dependencies;
70 };
71 } // anonymous namespace
72 
74  const std::vector<std::string> &CommandLine, StringRef CWD) {
75  MakeDependencyPrinterConsumer Consumer;
76  CallbackActionController Controller(nullptr);
77  auto Result =
78  Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
79  if (Result)
80  return std::move(Result);
81  std::string Output;
82  Consumer.printDependencies(Output);
83  return Output;
84 }
85 
87  const CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput,
88  std::string &MakeformatOutputPath) {
89  class P1689ModuleDependencyPrinterConsumer
90  : public MakeDependencyPrinterConsumer {
91  public:
92  P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
93  const CompileCommand &Command)
94  : Filename(Command.Filename), Rule(Rule) {
95  Rule.PrimaryOutput = Command.Output;
96  }
97 
98  void handleProvidedAndRequiredStdCXXModules(
99  std::optional<P1689ModuleInfo> Provided,
100  std::vector<P1689ModuleInfo> Requires) override {
101  Rule.Provides = Provided;
102  if (Rule.Provides)
103  Rule.Provides->SourcePath = Filename.str();
104  Rule.Requires = Requires;
105  }
106 
107  StringRef getMakeFormatDependencyOutputPath() {
108  if (Opts->OutputFormat != DependencyOutputFormat::Make)
109  return {};
110  return Opts->OutputFile;
111  }
112 
113  private:
114  StringRef Filename;
115  P1689Rule &Rule;
116  };
117 
118  class P1689ActionController : public DependencyActionController {
119  public:
120  // The lookupModuleOutput is for clang modules. P1689 format don't need it.
121  std::string lookupModuleOutput(const ModuleID &,
122  ModuleOutputKind Kind) override {
123  return "";
124  }
125  };
126 
127  P1689Rule Rule;
128  P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
129  P1689ActionController Controller;
130  auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer,
131  Controller);
132  if (Result)
133  return std::move(Result);
134 
135  MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
136  if (!MakeformatOutputPath.empty())
137  Consumer.printDependencies(MakeformatOutput);
138  return Rule;
139 }
140 
143  const std::vector<std::string> &CommandLine, StringRef CWD,
144  const llvm::DenseSet<ModuleID> &AlreadySeen,
145  LookupModuleOutputCallback LookupModuleOutput) {
146  FullDependencyConsumer Consumer(AlreadySeen);
147  CallbackActionController Controller(LookupModuleOutput);
148  llvm::Error Result =
149  Worker.computeDependencies(CWD, CommandLine, Consumer, Controller);
150  if (Result)
151  return std::move(Result);
152  return Consumer.takeTranslationUnitDeps();
153 }
154 
156  StringRef ModuleName, const std::vector<std::string> &CommandLine,
157  StringRef CWD, const llvm::DenseSet<ModuleID> &AlreadySeen,
158  LookupModuleOutputCallback LookupModuleOutput) {
159  FullDependencyConsumer Consumer(AlreadySeen);
160  CallbackActionController Controller(LookupModuleOutput);
161  llvm::Error Result = Worker.computeDependencies(CWD, CommandLine, Consumer,
162  Controller, ModuleName);
163  if (Result)
164  return std::move(Result);
165  return Consumer.takeModuleGraphDeps();
166 }
167 
170 
171  TU.ID.ContextHash = std::move(ContextHash);
172  TU.FileDeps = std::move(Dependencies);
173  TU.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
174  TU.Commands = std::move(Commands);
175 
176  for (auto &&M : ClangModuleDeps) {
177  auto &MD = M.second;
178  // TODO: Avoid handleModuleDependency even being called for modules
179  // we've already seen.
180  if (AlreadySeen.count(M.first))
181  continue;
182  TU.ModuleGraph.push_back(std::move(MD));
183  }
184  TU.ClangModuleDeps = std::move(DirectModuleDeps);
185 
186  return TU;
187 }
188 
190  ModuleDepsGraph ModuleGraph;
191 
192  for (auto &&M : ClangModuleDeps) {
193  auto &MD = M.second;
194  // TODO: Avoid handleModuleDependency even being called for modules
195  // we've already seen.
196  if (AlreadySeen.count(M.first))
197  continue;
198  ModuleGraph.push_back(std::move(MD));
199  }
200 
201  return ModuleGraph;
202 }
203 
static char ID
Definition: Arena.cpp:183
StringRef Filename
Definition: Format.cpp:2976
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
Definition: Utils.h:104
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
A simple dependency action controller that uses a callback.
Dependency scanner callbacks that are used during scanning to influence the behaviour of the scan - f...
The dependency scanning service contains shared configuration and state that is used by the individua...
llvm::Expected< P1689Rule > getP1689ModuleDependencyFile(const clang::tooling::CompileCommand &Command, StringRef CWD, std::string &MakeformatOutput, std::string &MakeformatOutputPath)
Collect the module dependency in P1689 format for C++20 named modules.
llvm::Expected< std::string > getDependencyFile(const std::vector< std::string > &CommandLine, StringRef CWD)
Print out the dependency information into a string using the dependency file format that is specified...
llvm::Expected< ModuleDepsGraph > getModuleDependencies(StringRef ModuleName, 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 ...
llvm::Expected< TranslationUnitDeps > getTranslationUnitDependencies(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::DenseSet< ModuleID > &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput)
Given a Clang driver command-line for a translation unit, gather the modular dependencies and return ...
DependencyScanningTool(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=llvm::vfs::createPhysicalFileSystem())
Construct a dependency scanning tool.
bool computeDependencies(StringRef WorkingDirectory, const std::vector< std::string > &CommandLine, DependencyConsumer &DepConsumer, DependencyActionController &Controller, DiagnosticConsumer &DiagConsumer, std::optional< StringRef > ModuleName=std::nullopt)
Run the dependency scanning tool for a given clang driver command-line, and report the discovered dep...
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
std::vector< ModuleDeps > ModuleDepsGraph
Graph of modular dependencies.
llvm::function_ref< std::string(const ModuleID &, ModuleOutputKind)> LookupModuleOutputCallback
A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
std::shared_ptr< MatchComputation< T > > Generator
Definition: RewriteRule.h:65
The JSON file list parser is used to communicate input to InstallAPI.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
Definition: Format.h:5433
Specifies the working directory and command of a compilation.
A command-line tool invocation that is part of building a TU.
This is used to identify a specific module.
std::string ContextHash
The context hash of a module represents the compiler options that affect the resulting command-line i...
std::vector< P1689ModuleInfo > Requires
std::optional< P1689ModuleInfo > Provides
Modular dependency that has already been built prior to the dependency scan.
The full dependencies and module graph for a specific input.
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modules this translation unit directly depends on, not including transitive ...
std::vector< Command > Commands
The sequence of commands required to build the translation unit.
std::vector< std::string > FileDeps
A collection of absolute paths to files that this translation unit directly depends on,...
ModuleDepsGraph ModuleGraph
The graph of direct and transitive modular dependencies.
ModuleID ID
The identifier of the C++20 module this translation unit exports.
std::vector< ModuleID > ClangModuleDeps
A list of modules this translation unit directly depends on, not including transitive dependencies.