Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Tooling/DependencyScanning/DependencyScanningTool.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
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 | |
9 #include "clang/Tooling/DependencyScanning/DependencyScanningTool.h" | |
10 #include "clang/Frontend/Utils.h" | |
11 | |
12 namespace clang{ | |
13 namespace tooling{ | |
14 namespace dependencies{ | |
15 | |
16 std::vector<std::string> FullDependencies::getAdditionalCommandLine( | |
17 std::function<StringRef(ClangModuleDep)> LookupPCMPath, | |
18 std::function<const ModuleDeps &(ClangModuleDep)> LookupModuleDeps) const { | |
19 std::vector<std::string> Ret = AdditionalNonPathCommandLine; | |
20 | |
21 dependencies::detail::appendCommonModuleArguments( | |
22 ClangModuleDeps, LookupPCMPath, LookupModuleDeps, Ret); | |
23 | |
24 return Ret; | |
25 } | |
26 | |
27 DependencyScanningTool::DependencyScanningTool( | |
28 DependencyScanningService &Service) | |
29 : Worker(Service) {} | |
30 | |
31 llvm::Expected<std::string> DependencyScanningTool::getDependencyFile( | |
32 const tooling::CompilationDatabase &Compilations, StringRef CWD) { | |
33 /// Prints out all of the gathered dependencies into a string. | |
34 class MakeDependencyPrinterConsumer : public DependencyConsumer { | |
35 public: | |
36 void handleFileDependency(const DependencyOutputOptions &Opts, | |
37 StringRef File) override { | |
38 if (!this->Opts) | |
39 this->Opts = std::make_unique<DependencyOutputOptions>(Opts); | |
40 Dependencies.push_back(std::string(File)); | |
41 } | |
42 | |
43 void handleModuleDependency(ModuleDeps MD) override { | |
44 // These are ignored for the make format as it can't support the full | |
45 // set of deps, and handleFileDependency handles enough for implicitly | |
46 // built modules to work. | |
47 } | |
48 | |
49 void handleContextHash(std::string Hash) override {} | |
50 | |
51 void printDependencies(std::string &S) { | |
52 if (!Opts) | |
53 return; | |
54 | |
55 class DependencyPrinter : public DependencyFileGenerator { | |
56 public: | |
57 DependencyPrinter(DependencyOutputOptions &Opts, | |
58 ArrayRef<std::string> Dependencies) | |
59 : DependencyFileGenerator(Opts) { | |
60 for (const auto &Dep : Dependencies) | |
61 addDependency(Dep); | |
62 } | |
63 | |
64 void printDependencies(std::string &S) { | |
65 llvm::raw_string_ostream OS(S); | |
66 outputDependencyFile(OS); | |
67 } | |
68 }; | |
69 | |
70 DependencyPrinter Generator(*Opts, Dependencies); | |
71 Generator.printDependencies(S); | |
72 } | |
73 | |
74 private: | |
75 std::unique_ptr<DependencyOutputOptions> Opts; | |
76 std::vector<std::string> Dependencies; | |
77 }; | |
78 | |
79 // We expect a single command here because if a source file occurs multiple | |
80 // times in the original CDB, then `computeDependencies` would run the | |
81 // `DependencyScanningAction` once for every time the input occured in the | |
82 // CDB. Instead we split up the CDB into single command chunks to avoid this | |
83 // behavior. | |
84 assert(Compilations.getAllCompileCommands().size() == 1 && | |
85 "Expected a compilation database with a single command!"); | |
86 std::string Input = Compilations.getAllCompileCommands().front().Filename; | |
87 | |
88 MakeDependencyPrinterConsumer Consumer; | |
89 auto Result = Worker.computeDependencies(Input, CWD, Compilations, Consumer); | |
90 if (Result) | |
91 return std::move(Result); | |
92 std::string Output; | |
93 Consumer.printDependencies(Output); | |
94 return Output; | |
95 } | |
96 | |
97 llvm::Expected<FullDependenciesResult> | |
98 DependencyScanningTool::getFullDependencies( | |
99 const tooling::CompilationDatabase &Compilations, StringRef CWD, | |
100 const llvm::StringSet<> &AlreadySeen) { | |
101 class FullDependencyPrinterConsumer : public DependencyConsumer { | |
102 public: | |
103 FullDependencyPrinterConsumer(const llvm::StringSet<> &AlreadySeen) | |
104 : AlreadySeen(AlreadySeen) {} | |
105 | |
106 void handleFileDependency(const DependencyOutputOptions &Opts, | |
107 StringRef File) override { | |
108 Dependencies.push_back(std::string(File)); | |
109 } | |
110 | |
111 void handleModuleDependency(ModuleDeps MD) override { | |
112 ClangModuleDeps[MD.ContextHash + MD.ModuleName] = std::move(MD); | |
113 } | |
114 | |
115 void handleContextHash(std::string Hash) override { | |
116 ContextHash = std::move(Hash); | |
117 } | |
118 | |
119 FullDependenciesResult getFullDependencies() const { | |
120 FullDependencies FD; | |
121 | |
122 FD.ContextHash = std::move(ContextHash); | |
123 | |
124 FD.FileDeps.assign(Dependencies.begin(), Dependencies.end()); | |
125 | |
126 for (auto &&M : ClangModuleDeps) { | |
127 auto &MD = M.second; | |
128 if (MD.ImportedByMainFile) | |
129 FD.ClangModuleDeps.push_back({MD.ModuleName, ContextHash}); | |
130 } | |
131 | |
132 FullDependenciesResult FDR; | |
133 | |
134 for (auto &&M : ClangModuleDeps) { | |
135 // TODO: Avoid handleModuleDependency even being called for modules | |
136 // we've already seen. | |
137 if (AlreadySeen.count(M.first)) | |
138 continue; | |
139 FDR.DiscoveredModules.push_back(std::move(M.second)); | |
140 } | |
141 | |
142 FDR.FullDeps = std::move(FD); | |
143 return FDR; | |
144 } | |
145 | |
146 private: | |
147 std::vector<std::string> Dependencies; | |
148 std::unordered_map<std::string, ModuleDeps> ClangModuleDeps; | |
149 std::string ContextHash; | |
150 std::vector<std::string> OutputPaths; | |
151 const llvm::StringSet<> &AlreadySeen; | |
152 }; | |
153 | |
154 // We expect a single command here because if a source file occurs multiple | |
155 // times in the original CDB, then `computeDependencies` would run the | |
156 // `DependencyScanningAction` once for every time the input occured in the | |
157 // CDB. Instead we split up the CDB into single command chunks to avoid this | |
158 // behavior. | |
159 assert(Compilations.getAllCompileCommands().size() == 1 && | |
160 "Expected a compilation database with a single command!"); | |
161 std::string Input = Compilations.getAllCompileCommands().front().Filename; | |
162 | |
163 FullDependencyPrinterConsumer Consumer(AlreadySeen); | |
164 llvm::Error Result = | |
165 Worker.computeDependencies(Input, CWD, Compilations, Consumer); | |
166 if (Result) | |
167 return std::move(Result); | |
168 return Consumer.getFullDependencies(); | |
169 } | |
170 | |
171 } // end namespace dependencies | |
172 } // end namespace tooling | |
173 } // end namespace clang |