clang  16.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 
12 using namespace clang;
13 using namespace tooling;
14 using namespace dependencies;
15 
16 static std::vector<std::string>
18  std::vector<std::string> Args = OriginalCommandLine;
19 
20  Args.push_back("-fno-implicit-modules");
21  Args.push_back("-fno-implicit-module-maps");
22 
23  // These arguments are unused in explicit compiles.
24  llvm::erase_if(Args, [](StringRef Arg) {
25  if (Arg.consume_front("-fmodules-")) {
26  return Arg.startswith("cache-path=") ||
27  Arg.startswith("prune-interval=") ||
28  Arg.startswith("prune-after=") ||
29  Arg == "validate-once-per-build-session";
30  }
31  return Arg.startswith("-fbuild-session-file=");
32  });
33 
34  return Args;
35 }
36 
40  : Worker(Service, std::move(FS)) {}
41 
43  const std::vector<std::string> &CommandLine, StringRef CWD,
44  llvm::Optional<StringRef> ModuleName) {
45  /// Prints out all of the gathered dependencies into a string.
46  class MakeDependencyPrinterConsumer : public DependencyConsumer {
47  public:
48  void handleBuildCommand(Command) override {}
49 
50  void
51  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
52  this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
53  }
54 
55  void handleFileDependency(StringRef File) override {
56  Dependencies.push_back(std::string(File));
57  }
58 
59  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
60  // Same as `handleModuleDependency`.
61  }
62 
63  void handleModuleDependency(ModuleDeps MD) override {
64  // These are ignored for the make format as it can't support the full
65  // set of deps, and handleFileDependency handles enough for implicitly
66  // built modules to work.
67  }
68 
69  void handleContextHash(std::string Hash) override {}
70 
71  std::string lookupModuleOutput(const ModuleID &ID,
72  ModuleOutputKind Kind) override {
73  llvm::report_fatal_error("unexpected call to lookupModuleOutput");
74  }
75 
76  void printDependencies(std::string &S) {
77  assert(Opts && "Handled dependency output options.");
78 
79  class DependencyPrinter : public DependencyFileGenerator {
80  public:
81  DependencyPrinter(DependencyOutputOptions &Opts,
82  ArrayRef<std::string> Dependencies)
83  : DependencyFileGenerator(Opts) {
84  for (const auto &Dep : Dependencies)
85  addDependency(Dep);
86  }
87 
88  void printDependencies(std::string &S) {
89  llvm::raw_string_ostream OS(S);
90  outputDependencyFile(OS);
91  }
92  };
93 
94  DependencyPrinter Generator(*Opts, Dependencies);
95  Generator.printDependencies(S);
96  }
97 
98  private:
99  std::unique_ptr<DependencyOutputOptions> Opts;
100  std::vector<std::string> Dependencies;
101  };
102 
103  MakeDependencyPrinterConsumer Consumer;
104  auto Result =
105  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
106  if (Result)
107  return std::move(Result);
108  std::string Output;
109  Consumer.printDependencies(Output);
110  return Output;
111 }
112 
115  const std::vector<std::string> &CommandLine, StringRef CWD,
116  const llvm::StringSet<> &AlreadySeen,
117  LookupModuleOutputCallback LookupModuleOutput,
118  llvm::Optional<StringRef> ModuleName) {
119  FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput,
120  Worker.shouldEagerLoadModules());
121  llvm::Error Result =
122  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
123  if (Result)
124  return std::move(Result);
125  return Consumer.takeFullDependencies();
126 }
127 
130  const std::vector<std::string> &CommandLine, StringRef CWD,
131  const llvm::StringSet<> &AlreadySeen,
132  LookupModuleOutputCallback LookupModuleOutput,
133  llvm::Optional<StringRef> ModuleName) {
134  FullDependencyConsumer Consumer(AlreadySeen, LookupModuleOutput,
135  Worker.shouldEagerLoadModules());
136  llvm::Error Result =
137  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
138  if (Result)
139  return std::move(Result);
140  return Consumer.getFullDependenciesLegacyDriverCommand(CommandLine);
141 }
142 
145  FullDependencies &FD = FDR.FullDeps;
146 
147  FD.ID.ContextHash = std::move(ContextHash);
148  FD.FileDeps = std::move(Dependencies);
149  FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
150  FD.Commands = std::move(Commands);
151 
152  for (auto &&M : ClangModuleDeps) {
153  auto &MD = M.second;
154  if (MD.ImportedByMainFile)
155  FD.ClangModuleDeps.push_back(MD.ID);
156  // TODO: Avoid handleModuleDependency even being called for modules
157  // we've already seen.
158  if (AlreadySeen.count(M.first))
159  continue;
160  FDR.DiscoveredModules.push_back(std::move(MD));
161  }
162 
163  return FDR;
164 }
165 
168  const std::vector<std::string> &OriginalCommandLine) const {
169  FullDependencies FD;
170 
172  ArrayRef<std::string>(OriginalCommandLine).slice(1));
173 
174  FD.ID.ContextHash = std::move(ContextHash);
175 
176  FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
177 
178  for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps)
179  FD.DriverCommandLine.push_back("-fmodule-file=" + PMD.PCMFile);
180 
181  for (auto &&M : ClangModuleDeps) {
182  auto &MD = M.second;
183  if (MD.ImportedByMainFile) {
184  FD.ClangModuleDeps.push_back(MD.ID);
185  auto PCMPath = LookupModuleOutput(MD.ID, ModuleOutputKind::ModuleFile);
186  if (EagerLoadModules) {
187  FD.DriverCommandLine.push_back("-fmodule-file=" + PCMPath);
188  } else {
189  FD.DriverCommandLine.push_back("-fmodule-map-file=" +
190  MD.ClangModuleMapFile);
191  FD.DriverCommandLine.push_back("-fmodule-file=" + MD.ID.ModuleName +
192  "=" + PCMPath);
193  }
194  }
195  }
196 
197  FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
198 
200 
201  for (auto &&M : ClangModuleDeps) {
202  // TODO: Avoid handleModuleDependency even being called for modules
203  // we've already seen.
204  if (AlreadySeen.count(M.first))
205  continue;
206  FDR.DiscoveredModules.push_back(std::move(M.second));
207  }
208 
209  FDR.FullDeps = std::move(FD);
210  return FDR;
211 }
clang::DependencyOutputOptions
DependencyOutputOptions - Options for controlling the compiler dependency file generation.
Definition: DependencyOutputOptions.h:33
clang::tooling::dependencies::FullDependencies
The full dependencies and module graph for a specific input.
Definition: DependencyScanningTool.h:31
clang::DeclaratorContext::File
@ File
clang::tooling::dependencies::DependencyScanningWorker::computeDependencies
bool computeDependencies(StringRef WorkingDirectory, const std::vector< std::string > &CommandLine, DependencyConsumer &DepConsumer, DiagnosticConsumer &DiagConsumer, llvm::Optional< StringRef > ModuleName=None)
Run the dependency scanning tool for a given clang driver command-line, and report the discovered dep...
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::tooling::dependencies::DependencyScanningWorker::shouldEagerLoadModules
bool shouldEagerLoadModules() const
Definition: DependencyScanningWorker.h:90
clang::tooling::dependencies::FullDependencies::DriverCommandLine
std::vector< std::string > DriverCommandLine
Deprecated driver command-line. This will be removed in a future version.
Definition: DependencyScanningTool.h:61
clang::tooling::dependencies::FullDependenciesResult
Definition: DependencyScanningTool.h:64
clang::tooling::dependencies::DependencyConsumer
Definition: DependencyScanningWorker.h:39
clang::tooling::dependencies::FullDependencyConsumer
Definition: DependencyScanningTool.h:120
clang::tooling::dependencies::FullDependencyConsumer::getFullDependenciesLegacyDriverCommand
FullDependenciesResult getFullDependenciesLegacyDriverCommand(const std::vector< std::string > &OriginalCommandLine) const
Definition: DependencyScanningTool.cpp:167
clang::tooling::dependencies::FullDependencies::ID
ModuleID ID
The identifier of the C++20 module this translation unit exports.
Definition: DependencyScanningTool.h:35
llvm::Optional
Definition: LLVM.h:40
llvm::Expected
Definition: LLVM.h:41
clang::tooling::dependencies::FullDependenciesResult::DiscoveredModules
std::vector< ModuleDeps > DiscoveredModules
Definition: DependencyScanningTool.h:66
clang::tooling::dependencies::PrebuiltModuleDep
Modular dependency that has already been built prior to the dependency scan.
Definition: ModuleDepCollector.h:32
Utils.h
clang::transformer::Generator
std::shared_ptr< MatchComputation< T > > Generator
Definition: RewriteRule.h:65
clang::tooling::dependencies::FullDependencies::FileDeps
std::vector< std::string > FileDeps
A collection of absolute paths to files that this translation unit directly depends on,...
Definition: DependencyScanningTool.h:39
clang::tooling::dependencies::LookupModuleOutputCallback
llvm::function_ref< std::string(const ModuleID &, ModuleOutputKind)> LookupModuleOutputCallback
A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
Definition: DependencyScanningTool.h:28
clang::DependencyFileGenerator
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
Definition: Utils.h:102
clang::tooling::dependencies::FullDependencyConsumer::takeFullDependencies
FullDependenciesResult takeFullDependencies()
Definition: DependencyScanningTool.cpp:143
clang::tooling::dependencies::FullDependencies::ClangModuleDeps
std::vector< ModuleID > ClangModuleDeps
A list of modules this translation unit directly depends on, not including transitive dependencies.
Definition: DependencyScanningTool.h:50
llvm::ArrayRef< std::string >
clang::tooling::dependencies::ModuleDeps
Definition: ModuleDepCollector.h:77
makeTUCommandLineWithoutPaths
static std::vector< std::string > makeTUCommandLineWithoutPaths(ArrayRef< std::string > OriginalCommandLine)
Definition: DependencyScanningTool.cpp:17
clang::tooling::dependencies::DependencyScanningTool::getFullDependenciesLegacyDriverCommand
llvm::Expected< FullDependenciesResult > getFullDependenciesLegacyDriverCommand(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::StringSet<> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput, llvm::Optional< StringRef > ModuleName=None)
Definition: DependencyScanningTool.cpp:129
clang::tooling::dependencies::DependencyScanningService
The dependency scanning service contains shared configuration and state that is used by the individua...
Definition: DependencyScanningService.h:45
clang::tooling::dependencies::FullDependenciesResult::FullDeps
FullDependencies FullDeps
Definition: DependencyScanningTool.h:65
clang::tooling::dependencies::Command
A command-line tool invocation that is part of building a TU.
Definition: DependencyScanningWorker.h:34
clang::ObjCPropertyAttribute::Kind
Kind
Definition: DeclObjCCommon.h:22
std
Definition: Format.h:4477
clang::tooling::dependencies::ModuleOutputKind
ModuleOutputKind
An output from a module compilation, such as the path of the module file.
Definition: ModuleDepCollector.h:65
clang::tooling::dependencies::ModuleID::ContextHash
std::string ContextHash
The context hash of a module represents the compiler options that affect the resulting command-line i...
Definition: ModuleDepCollector.h:57
clang::Builtin::ID
ID
Definition: Builtins.h:52
clang
Definition: CalledOnceCheck.h:17
clang::tooling::dependencies::ModuleOutputKind::ModuleFile
@ ModuleFile
The module file (.pcm). Required.
clang::tooling::dependencies::FullDependencies::PrebuiltModuleDeps
std::vector< PrebuiltModuleDep > PrebuiltModuleDeps
A collection of prebuilt modules this translation unit directly depends on, not including transitive ...
Definition: DependencyScanningTool.h:43
clang::tooling::dependencies::DependencyScanningTool::getDependencyFile
llvm::Expected< std::string > getDependencyFile(const std::vector< std::string > &CommandLine, StringRef CWD, llvm::Optional< StringRef > ModuleName=None)
Print out the dependency information into a string using the dependency file format that is specified...
Definition: DependencyScanningTool.cpp:42
clang::tooling::dependencies::DependencyScanningTool::DependencyScanningTool
DependencyScanningTool(DependencyScanningService &Service, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > FS=llvm::vfs::createPhysicalFileSystem())
Construct a dependency scanning tool.
Definition: DependencyScanningTool.cpp:37
DependencyScanningTool.h
clang::tooling::dependencies::ModuleID
This is used to identify a specific module.
Definition: ModuleDepCollector.h:44
clang::tooling::dependencies::DependencyScanningTool::getFullDependencies
llvm::Expected< FullDependenciesResult > getFullDependencies(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::StringSet<> &AlreadySeen, LookupModuleOutputCallback LookupModuleOutput, llvm::Optional< StringRef > ModuleName=None)
Collect the full module dependency graph for the input, ignoring any modules which have already been ...
Definition: DependencyScanningTool.cpp:114
clang::tooling::dependencies::FullDependencies::Commands
std::vector< Command > Commands
The sequence of commands required to build the translation unit.
Definition: DependencyScanningTool.h:58
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem >