clang  15.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 namespace clang {
13 namespace tooling {
14 namespace dependencies {
15 
16 std::vector<std::string> FullDependencies::getCommandLine(
17  std::function<StringRef(ModuleID)> LookupPCMPath) const {
18  std::vector<std::string> Ret = getCommandLineWithoutModulePaths();
19 
20  for (ModuleID MID : ClangModuleDeps)
21  Ret.push_back(("-fmodule-file=" + LookupPCMPath(MID)).str());
22 
23  return Ret;
24 }
25 
26 std::vector<std::string>
28  std::vector<std::string> Args = OriginalCommandLine;
29 
30  Args.push_back("-fno-implicit-modules");
31  Args.push_back("-fno-implicit-module-maps");
32  for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps)
33  Args.push_back("-fmodule-file=" + PMD.PCMFile);
34 
35  // This argument is unused in explicit compiles.
36  llvm::erase_if(Args, [](const std::string &Arg) {
37  return Arg.find("-fmodules-cache-path=") == 0;
38  });
39 
40  // TODO: Filter out the remaining implicit modules leftovers
41  // (e.g. "-fmodules-prune-interval=" or "-fmodules-prune-after=").
42 
43  return Args;
44 }
45 
48  : Worker(Service) {}
49 
51  const std::vector<std::string> &CommandLine, StringRef CWD,
52  llvm::Optional<StringRef> ModuleName) {
53  /// Prints out all of the gathered dependencies into a string.
54  class MakeDependencyPrinterConsumer : public DependencyConsumer {
55  public:
56  void
57  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
58  this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
59  }
60 
61  void handleFileDependency(StringRef File) override {
62  Dependencies.push_back(std::string(File));
63  }
64 
65  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
66  // Same as `handleModuleDependency`.
67  }
68 
69  void handleModuleDependency(ModuleDeps MD) override {
70  // These are ignored for the make format as it can't support the full
71  // set of deps, and handleFileDependency handles enough for implicitly
72  // built modules to work.
73  }
74 
75  void handleContextHash(std::string Hash) override {}
76 
77  void printDependencies(std::string &S) {
78  assert(Opts && "Handled dependency output options.");
79 
80  class DependencyPrinter : public DependencyFileGenerator {
81  public:
82  DependencyPrinter(DependencyOutputOptions &Opts,
83  ArrayRef<std::string> Dependencies)
84  : DependencyFileGenerator(Opts) {
85  for (const auto &Dep : Dependencies)
86  addDependency(Dep);
87  }
88 
89  void printDependencies(std::string &S) {
90  llvm::raw_string_ostream OS(S);
91  outputDependencyFile(OS);
92  }
93  };
94 
95  DependencyPrinter Generator(*Opts, Dependencies);
96  Generator.printDependencies(S);
97  }
98 
99  private:
100  std::unique_ptr<DependencyOutputOptions> Opts;
101  std::vector<std::string> Dependencies;
102  };
103 
104  MakeDependencyPrinterConsumer Consumer;
105  auto Result =
106  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
107  if (Result)
108  return std::move(Result);
109  std::string Output;
110  Consumer.printDependencies(Output);
111  return Output;
112 }
113 
116  const std::vector<std::string> &CommandLine, StringRef CWD,
117  const llvm::StringSet<> &AlreadySeen,
118  llvm::Optional<StringRef> ModuleName) {
119  class FullDependencyPrinterConsumer : public DependencyConsumer {
120  public:
121  FullDependencyPrinterConsumer(const llvm::StringSet<> &AlreadySeen)
122  : AlreadySeen(AlreadySeen) {}
123 
124  void
125  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {}
126 
127  void handleFileDependency(StringRef File) override {
128  Dependencies.push_back(std::string(File));
129  }
130 
131  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
132  PrebuiltModuleDeps.emplace_back(std::move(PMD));
133  }
134 
135  void handleModuleDependency(ModuleDeps MD) override {
136  ClangModuleDeps[MD.ID.ContextHash + MD.ID.ModuleName] = std::move(MD);
137  }
138 
139  void handleContextHash(std::string Hash) override {
140  ContextHash = std::move(Hash);
141  }
142 
144  const std::vector<std::string> &OriginalCommandLine) const {
145  FullDependencies FD;
146 
148  ArrayRef<std::string>(OriginalCommandLine).slice(1);
149 
150  FD.ID.ContextHash = std::move(ContextHash);
151 
152  FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
153 
154  for (auto &&M : ClangModuleDeps) {
155  auto &MD = M.second;
156  if (MD.ImportedByMainFile)
157  FD.ClangModuleDeps.push_back(MD.ID);
158  }
159 
160  FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
161 
163 
164  for (auto &&M : ClangModuleDeps) {
165  // TODO: Avoid handleModuleDependency even being called for modules
166  // we've already seen.
167  if (AlreadySeen.count(M.first))
168  continue;
169  FDR.DiscoveredModules.push_back(std::move(M.second));
170  }
171 
172  FDR.FullDeps = std::move(FD);
173  return FDR;
174  }
175 
176  private:
177  std::vector<std::string> Dependencies;
178  std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
179  std::map<std::string, ModuleDeps> ClangModuleDeps;
180  std::string ContextHash;
181  std::vector<std::string> OutputPaths;
182  const llvm::StringSet<> &AlreadySeen;
183  };
184 
185  FullDependencyPrinterConsumer Consumer(AlreadySeen);
186  llvm::Error Result =
187  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
188  if (Result)
189  return std::move(Result);
190  return Consumer.getFullDependencies(CommandLine);
191 }
192 
193 } // end namespace dependencies
194 } // end namespace tooling
195 } // end namespace clang
clang::tooling::dependencies::FullDependencies::getCommandLineWithoutModulePaths
std::vector< std::string > getCommandLineWithoutModulePaths() const
Get the full command line, excluding -fmodule-file=" arguments.
Definition: DependencyScanningTool.cpp:27
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:24
clang::DeclaratorContext::File
@ File
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
Ret
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.cpp:34
clang::tooling::dependencies::FullDependenciesResult
Definition: DependencyScanningTool.h:61
clang::tooling::dependencies::DependencyConsumer
Definition: DependencyScanningWorker.h:32
clang::tooling::dependencies::DependencyScanningTool::DependencyScanningTool
DependencyScanningTool(DependencyScanningService &Service)
Construct a dependency scanning tool.
Definition: DependencyScanningTool.cpp:46
clang::tooling::dependencies::FullDependencies::getCommandLine
std::vector< std::string > getCommandLine(std::function< StringRef(ModuleID)> LookupPCMPath) const
Get the full command line.
Definition: DependencyScanningTool.cpp:16
clang::tooling::dependencies::DependencyScanningTool::getFullDependencies
llvm::Expected< FullDependenciesResult > getFullDependencies(const std::vector< std::string > &CommandLine, StringRef CWD, const llvm::StringSet<> &AlreadySeen, llvm::Optional< StringRef > ModuleName=None)
Collect the full module dependency graph for the input, ignoring any modules which have already been ...
Definition: DependencyScanningTool.cpp:115
clang::tooling::dependencies::FullDependencies::ID
ModuleID ID
The identifier of the C++20 module this translation unit exports.
Definition: DependencyScanningTool.h:28
llvm::Optional
Definition: LLVM.h:40
llvm::Expected
Definition: LLVM.h:41
clang::tooling::dependencies::FullDependenciesResult::DiscoveredModules
std::vector< ModuleDeps > DiscoveredModules
Definition: DependencyScanningTool.h:63
clang::tooling::dependencies::ModuleDeps::ID
ModuleID ID
The identifier of the module.
Definition: ModuleDepCollector.h:70
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:50
clang::tooling::dependencies::PrebuiltModuleDep
Modular dependency that has already been built prior to the dependency scan.
Definition: ModuleDepCollector.h:32
clang::tooling::dependencies::FullDependencies::OriginalCommandLine
std::vector< std::string > OriginalCommandLine
The original command line of the TU (excluding the compiler executable).
Definition: DependencyScanningTool.h:46
Utils.h
clang::tooling::dependencies::ModuleDeps::ImportedByMainFile
bool ImportedByMainFile
Definition: ModuleDepCollector.h:105
clang::transformer::Generator
std::shared_ptr< MatchComputation< T > > Generator
Definition: RewriteRule.h:64
clang::tooling::dependencies::ModuleID::ModuleName
std::string ModuleName
The name of the module.
Definition: ModuleDepCollector.h:47
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:32
clang::tooling::dependencies::DependencyScanningWorker::computeDependencies
llvm::Error computeDependencies(StringRef WorkingDirectory, const std::vector< std::string > &CommandLine, DependencyConsumer &Consumer, llvm::Optional< StringRef > ModuleName=None)
Run the dependency scanning tool for a given clang driver command-line, and report the discovered dep...
Definition: DependencyScanningWorker.cpp:315
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::FullDependencies::ClangModuleDeps
std::vector< ModuleID > ClangModuleDeps
A list of modules this translation unit directly depends on, not including transitive dependencies.
Definition: DependencyScanningTool.h:43
llvm::ArrayRef< std::string >
clang::tooling::dependencies::ModuleDeps
Definition: ModuleDepCollector.h:68
clang::tooling::dependencies::DependencyScanningService
The dependency scanning service contains the shared state that is used by the invidual dependency sca...
Definition: DependencyScanningService.h:47
clang::tooling::dependencies::FullDependenciesResult::FullDeps
FullDependencies FullDeps
Definition: DependencyScanningTool.h:62
clang::tooling::dependencies::ModuleID::ContextHash
std::string ContextHash
The context hash of a module represents the set of compiler options that may make one version of a mo...
Definition: ModuleDepCollector.h:55
clang
Definition: CalledOnceCheck.h:17
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:36
DependencyScanningTool.h
clang::tooling::dependencies::ModuleID
This is used to identify a specific module.
Definition: ModuleDepCollector.h:44