clang  14.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::getAdditionalArgs(
17  std::function<StringRef(ModuleID)> LookupPCMPath,
18  std::function<const ModuleDeps &(ModuleID)> LookupModuleDeps) const {
19  std::vector<std::string> Ret = getAdditionalArgsWithoutModulePaths();
20 
21  std::vector<std::string> PCMPaths;
22  std::vector<std::string> ModMapPaths;
24  ClangModuleDeps, LookupPCMPath, LookupModuleDeps, PCMPaths, ModMapPaths);
25  for (const std::string &PCMPath : PCMPaths)
26  Ret.push_back("-fmodule-file=" + PCMPath);
27  for (const std::string &ModMapPath : ModMapPaths)
28  Ret.push_back("-fmodule-map-file=" + ModMapPath);
29 
30  return Ret;
31 }
32 
33 std::vector<std::string>
35  std::vector<std::string> Args{
36  "-fno-implicit-modules",
37  "-fno-implicit-module-maps",
38  };
39 
40  for (const PrebuiltModuleDep &PMD : PrebuiltModuleDeps) {
41  Args.push_back("-fmodule-file=" + PMD.PCMFile);
42  Args.push_back("-fmodule-map-file=" + PMD.ModuleMapFile);
43  }
44 
45  return Args;
46 }
47 
50  : Worker(Service) {}
51 
53  const std::vector<std::string> &CommandLine, StringRef CWD,
54  llvm::Optional<StringRef> ModuleName) {
55  /// Prints out all of the gathered dependencies into a string.
56  class MakeDependencyPrinterConsumer : public DependencyConsumer {
57  public:
58  void
59  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
60  this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
61  }
62 
63  void handleFileDependency(StringRef File) override {
64  Dependencies.push_back(std::string(File));
65  }
66 
67  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
68  // Same as `handleModuleDependency`.
69  }
70 
71  void handleModuleDependency(ModuleDeps MD) override {
72  // These are ignored for the make format as it can't support the full
73  // set of deps, and handleFileDependency handles enough for implicitly
74  // built modules to work.
75  }
76 
77  void handleContextHash(std::string Hash) override {}
78 
79  void printDependencies(std::string &S) {
80  assert(Opts && "Handled dependency output options.");
81 
82  class DependencyPrinter : public DependencyFileGenerator {
83  public:
84  DependencyPrinter(DependencyOutputOptions &Opts,
85  ArrayRef<std::string> Dependencies)
86  : DependencyFileGenerator(Opts) {
87  for (const auto &Dep : Dependencies)
88  addDependency(Dep);
89  }
90 
91  void printDependencies(std::string &S) {
92  llvm::raw_string_ostream OS(S);
93  outputDependencyFile(OS);
94  }
95  };
96 
97  DependencyPrinter Generator(*Opts, Dependencies);
98  Generator.printDependencies(S);
99  }
100 
101  private:
102  std::unique_ptr<DependencyOutputOptions> Opts;
103  std::vector<std::string> Dependencies;
104  };
105 
106  MakeDependencyPrinterConsumer Consumer;
107  auto Result =
108  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
109  if (Result)
110  return std::move(Result);
111  std::string Output;
112  Consumer.printDependencies(Output);
113  return Output;
114 }
115 
118  const std::vector<std::string> &CommandLine, StringRef CWD,
119  const llvm::StringSet<> &AlreadySeen,
120  llvm::Optional<StringRef> ModuleName) {
121  class FullDependencyPrinterConsumer : public DependencyConsumer {
122  public:
123  FullDependencyPrinterConsumer(const llvm::StringSet<> &AlreadySeen)
124  : AlreadySeen(AlreadySeen) {}
125 
126  void
127  handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {}
128 
129  void handleFileDependency(StringRef File) override {
130  Dependencies.push_back(std::string(File));
131  }
132 
133  void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
134  PrebuiltModuleDeps.emplace_back(std::move(PMD));
135  }
136 
137  void handleModuleDependency(ModuleDeps MD) override {
138  ClangModuleDeps[MD.ID.ContextHash + MD.ID.ModuleName] = std::move(MD);
139  }
140 
141  void handleContextHash(std::string Hash) override {
142  ContextHash = std::move(Hash);
143  }
144 
146  FullDependencies FD;
147 
148  FD.ID.ContextHash = std::move(ContextHash);
149 
150  FD.FileDeps.assign(Dependencies.begin(), Dependencies.end());
151 
152  for (auto &&M : ClangModuleDeps) {
153  auto &MD = M.second;
154  if (MD.ImportedByMainFile)
155  FD.ClangModuleDeps.push_back(MD.ID);
156  }
157 
158  FD.PrebuiltModuleDeps = std::move(PrebuiltModuleDeps);
159 
161 
162  for (auto &&M : ClangModuleDeps) {
163  // TODO: Avoid handleModuleDependency even being called for modules
164  // we've already seen.
165  if (AlreadySeen.count(M.first))
166  continue;
167  FDR.DiscoveredModules.push_back(std::move(M.second));
168  }
169 
170  FDR.FullDeps = std::move(FD);
171  return FDR;
172  }
173 
174  private:
175  std::vector<std::string> Dependencies;
176  std::vector<PrebuiltModuleDep> PrebuiltModuleDeps;
177  std::map<std::string, ModuleDeps> ClangModuleDeps;
178  std::string ContextHash;
179  std::vector<std::string> OutputPaths;
180  const llvm::StringSet<> &AlreadySeen;
181  };
182 
183  FullDependencyPrinterConsumer Consumer(AlreadySeen);
184  llvm::Error Result =
185  Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
186  if (Result)
187  return std::move(Result);
188  return Consumer.getFullDependencies();
189 }
190 
191 } // end namespace dependencies
192 } // end namespace tooling
193 } // end namespace clang
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::tooling::dependencies::FullDependencies::getAdditionalArgs
std::vector< std::string > getAdditionalArgs(std::function< StringRef(ModuleID)> LookupPCMPath, std::function< const ModuleDeps &(ModuleID)> LookupModuleDeps) const
Get additional arguments suitable for appending to the original Clang command line.
Definition: DependencyScanningTool.cpp:16
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:66
clang::tooling::dependencies::DependencyConsumer
Definition: DependencyScanningWorker.h:32
clang::tooling::dependencies::DependencyScanningTool::DependencyScanningTool
DependencyScanningTool(DependencyScanningService &Service)
Construct a dependency scanning tool.
Definition: DependencyScanningTool.cpp:48
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:117
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:68
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:52
clang::tooling::dependencies::PrebuiltModuleDep
Modular dependency that has already been built prior to the dependency scan.
Definition: ModuleDepCollector.h:32
Utils.h
clang::tooling::dependencies::ModuleDeps::ImportedByMainFile
bool ImportedByMainFile
Definition: ModuleDepCollector.h:101
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:330
clang::DependencyFileGenerator
Builds a dependency file when attached to a Preprocessor (for includes) and ASTReader (for module imp...
Definition: Utils.h:118
clang::tooling::dependencies::FullDependencies::getAdditionalArgsWithoutModulePaths
std::vector< std::string > getAdditionalArgsWithoutModulePaths() const
Get additional arguments suitable for appending to the original Clang command line,...
Definition: DependencyScanningTool.cpp:34
clang::tooling::dependencies::detail::collectPCMAndModuleMapPaths
void collectPCMAndModuleMapPaths(llvm::ArrayRef< ModuleID > Modules, std::function< StringRef(ModuleID)> LookupPCMPath, std::function< const ModuleDeps &(ModuleID)> LookupModuleDeps, std::vector< std::string > &PCMPaths, std::vector< std::string > &ModMapPaths)
Collect the paths of PCM and module map files for the modules in Modules transitively.
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:67
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