21 using namespace clang;
22 using namespace tooling;
23 using namespace dependencies;
30 DependencyConsumerForwarder(std::unique_ptr<DependencyOutputOptions> Opts,
31 DependencyConsumer &C)
35 C.handleDependencyOutputOpts(*Opts);
37 for (
const auto &File : getDependencies()) {
39 llvm::sys::path::remove_dots(CanonPath,
true);
40 C.handleFileDependency(CanonPath);
45 std::unique_ptr<DependencyOutputOptions> Opts;
46 DependencyConsumer &
C;
55 PrebuiltModuleListener(PrebuiltModuleFilesT &PrebuiltModuleFiles,
56 llvm::StringSet<> &InputFiles,
bool VisitInputFiles,
58 : PrebuiltModuleFiles(PrebuiltModuleFiles), InputFiles(InputFiles),
59 VisitInputFiles(VisitInputFiles), NewModuleFiles(NewModuleFiles) {}
61 bool needsImportVisitation()
const override {
return true; }
62 bool needsInputFileVisitation()
override {
return VisitInputFiles; }
63 bool needsSystemInputFileVisitation()
override {
return VisitInputFiles; }
65 void visitImport(StringRef ModuleName, StringRef
Filename)
override {
66 if (PrebuiltModuleFiles.insert({ModuleName.str(), Filename.str()}).second)
67 NewModuleFiles.push_back(
Filename.str());
71 bool isExplicitModule)
override {
77 PrebuiltModuleFilesT &PrebuiltModuleFiles;
78 llvm::StringSet<> &InputFiles;
85 static void visitPrebuiltModule(StringRef PrebuiltModuleFilename,
87 PrebuiltModuleFilesT &ModuleFiles,
88 llvm::StringSet<> &InputFiles,
89 bool VisitInputFiles) {
92 PrebuiltModuleListener Listener(ModuleFiles, InputFiles, VisitInputFiles,
95 while (!Worklist.empty())
104 static std::string makeObjFileName(StringRef FileName) {
106 llvm::sys::path::replace_extension(ObjFileName,
"o");
114 if (OutputFile !=
"-")
117 if (InputFiles.empty() || !InputFiles.front().isFile())
118 return "clang-scan-deps\\ dependency";
120 return makeObjFileName(InputFiles.front().getFile());
126 DiagOpts.ShowCarets =
false;
130 DiagOpts.
Warnings.push_back(
"no-error");
137 DependencyScanningAction(
138 StringRef WorkingDirectory, DependencyConsumer &Consumer,
143 : WorkingDirectory(WorkingDirectory), Consumer(Consumer),
144 DepFS(
std::move(DepFS)), PPSkipMappings(PPSkipMappings), Format(Format),
145 OptimizeArgs(OptimizeArgs), ModuleName(ModuleName) {}
147 bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
149 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
156 ScanInstance.setInvocation(std::move(Invocation));
159 sanitizeDiagOpts(ScanInstance.getDiagnosticOpts());
160 ScanInstance.createDiagnostics(DiagConsumer,
false);
161 if (!ScanInstance.hasDiagnostics())
164 ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath =
167 ScanInstance.getFrontendOpts().GenerateGlobalModuleIndex =
false;
168 ScanInstance.getFrontendOpts().UseGlobalModuleIndex =
false;
171 ScanInstance.setFileManager(FileMgr);
172 ScanInstance.createSourceManager(*FileMgr);
174 llvm::StringSet<> PrebuiltModulesInputFiles;
178 if (!ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
180 ScanInstance.getPreprocessorOpts().ImplicitPCHInclude, ScanInstance,
181 ScanInstance.getHeaderSearchOpts().PrebuiltModuleFiles,
182 PrebuiltModulesInputFiles, DepFS !=
nullptr);
186 DepFS->enableMinimizationOfAllFiles();
191 for (
const auto &File : PrebuiltModulesInputFiles)
192 DepFS->disableMinimization(
File.getKey());
195 for (
const auto &E : ScanInstance.getHeaderSearchOpts().UserEntries)
196 DepFS->disableMinimization(E.Path);
197 for (
const auto &F : ScanInstance.getHeaderSearchOpts().VFSOverlayFiles)
198 DepFS->disableMinimization(F);
203 ScanInstance.getInvocation(), ScanInstance.getDiagnostics(), DepFS));
207 ScanInstance.getPreprocessorOpts()
208 .ExcludedConditionalDirectiveSkipMappings = &PPSkipMappings;
218 auto Opts = std::make_unique<DependencyOutputOptions>();
219 std::swap(*Opts, ScanInstance.getInvocation().getDependencyOutputOpts());
222 if (Opts->Targets.empty())
224 deduceDepTarget(ScanInstance.getFrontendOpts().OutputFile,
225 ScanInstance.getFrontendOpts().Inputs)};
226 Opts->IncludeSystemHeaders =
true;
230 ScanInstance.addDependencyCollector(
231 std::make_shared<DependencyConsumerForwarder>(std::move(Opts),
235 ScanInstance.addDependencyCollector(std::make_shared<ModuleDepCollector>(
236 std::move(Opts), ScanInstance, Consumer,
237 std::move(OriginalInvocation), OptimizeArgs));
246 ScanInstance.getHeaderSearchOpts().ModulesStrictContextHash =
true;
248 std::unique_ptr<FrontendAction> Action;
250 if (ModuleName.hasValue())
251 Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName);
253 Action = std::make_unique<ReadPCHAndPreprocessAction>();
255 const bool Result = ScanInstance.ExecuteAction(*Action);
262 StringRef WorkingDirectory;
263 DependencyConsumer &Consumer;
275 : Format(Service.getFormat()), OptimizeArgs(Service.canOptimizeArgs()) {
276 PCHContainerOps = std::make_shared<PCHContainerOperations>();
277 PCHContainerOps->registerReader(
278 std::make_unique<ObjectFilePCHContainerReader>());
281 PCHContainerOps->registerWriter(
282 std::make_unique<ObjectFilePCHContainerWriter>());
284 auto OverlayFS = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(
285 llvm::vfs::createPhysicalFileSystem());
286 InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
287 OverlayFS->pushOverlay(InMemoryFS);
292 RealFS, PPSkipMappings);
301 sanitizeDiagOpts(*DiagOpts);
306 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
309 if (BodyShouldSucceed(DiagPrinter, *DiagOpts))
310 return llvm::Error::success();
311 return llvm::make_error<llvm::StringError>(DiagnosticsOS.str(),
312 llvm::inconvertibleErrorCode());
316 StringRef WorkingDirectory,
const std::vector<std::string> &CommandLine,
319 RealFS->setCurrentWorkingDirectory(WorkingDirectory);
321 Files->setVirtualFileSystem(RealFS);
327 if (ModuleName.hasValue()) {
328 ModifiedCommandLine = CommandLine;
329 InMemoryFS->addFile(*ModuleName, 0, llvm::MemoryBuffer::getMemBuffer(
""));
330 ModifiedCommandLine->emplace_back(*ModuleName);
333 const std::vector<std::string> &FinalCommandLine =
334 ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
336 std::vector<const char *> FinalCCommandLine(CommandLine.size(),
nullptr);
337 llvm::transform(CommandLine, FinalCCommandLine.begin(),
338 [](
const std::string &Str) { return Str.c_str(); });
342 DependencyScanningAction Action(
343 WorkingDirectory, Consumer, DepFS, PPSkipMappings,
344 Format, OptimizeArgs, ModuleName);
354 return Invocation.
run();