[clang] [clang][Dependency Scanning] Implementing `CompilerInstanceWithContext` to Speedup By Name Scans (PR #160207)
Qiongsi Wu via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 23 11:04:40 PDT 2025
================
@@ -0,0 +1,250 @@
+//===- CompilerInstanceWithContext.cpp - clang scanning compiler instance -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/DependencyScanning/CompilerInstanceWithContext.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
+#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
+#include "llvm/TargetParser/Host.h"
+
+using namespace clang;
+using namespace tooling;
+using namespace dependencies;
+
+const std::string CompilerInstanceWithContext::FakeFileBuffer =
+ std::string(MAX_NUM_NAMES, ' ');
+
+llvm::Error CompilerInstanceWithContext::initialize() {
+ // Virtual file system setup
+ // - Set the current working directory.
+ Worker.BaseFS->setCurrentWorkingDirectory(CWD);
+ OverlayFS =
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(Worker.BaseFS);
+ InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
+ InMemoryFS->setCurrentWorkingDirectory(CWD);
+
+ // - Create the fake file as scanning input source file and setup overlay
+ // FS.
+ SmallString<128> FakeInputPath;
+ llvm::sys::fs::createUniquePath("ScanningCI-%%%%%%%%.input", FakeInputPath,
+ /*MakeAbsolute=*/false);
+ InMemoryFS->addFile(FakeInputPath, 0,
+ llvm::MemoryBuffer::getMemBuffer(FakeFileBuffer));
+ InMemoryOverlay = InMemoryFS;
+ // TODO: we need to handle CAS/CASFS here.
+ // if (Worker.CAS && !Worker.DepCASFS)
+ // InMemoryOverlay = llvm::cas::createCASProvidingFileSystem(
+ // Worker.CAS, std::move(InMemoryFS));
+ OverlayFS->pushOverlay(InMemoryOverlay);
+
+ // Augument the command line.
+ CommandLine.emplace_back(FakeInputPath);
+
+ // Create the file manager, the diagnostics engine, and the source manager.
+ FileMgr = std::make_unique<FileManager>(FileSystemOptions{}, OverlayFS);
+ DiagnosticOutput.clear();
+ auto DiagOpts = createDiagOptions(CommandLine);
+ DiagPrinter = std::make_unique<TextDiagnosticPrinter>(DiagnosticsOS,
+ *(DiagOpts.release()));
+ std::vector<const char *> CCommandLine(CommandLine.size(), nullptr);
+ llvm::transform(CommandLine, CCommandLine.begin(),
+ [](const std::string &Str) { return Str.c_str(); });
+ DiagOpts = CreateAndPopulateDiagOpts(CCommandLine);
+ sanitizeDiagOpts(*DiagOpts);
+ Diags = CompilerInstance::createDiagnostics(*OverlayFS, *(DiagOpts.release()),
+ DiagPrinter.get(),
+ /*ShouldOwnClient=*/false);
+ SrcMgr = std::make_unique<SourceManager>(*Diags, *FileMgr);
+ Diags->setSourceManager(SrcMgr.get());
+
+ // Create the compiler invocation.
+ Driver = std::make_unique<driver::Driver>(
+ CCommandLine[0], llvm::sys::getDefaultTargetTriple(), *Diags,
+ "clang LLVM compiler", OverlayFS);
+ Driver->setTitle("clang_based_tool");
+ Compilation.reset(Driver->BuildCompilation(llvm::ArrayRef(CCommandLine)));
+
+ if (Compilation->containsError()) {
+ return llvm::make_error<llvm::StringError>("Failed to build compilation",
+ llvm::inconvertibleErrorCode());
+ }
+
+ const driver::Command &Command = *(Compilation->getJobs().begin());
+ const auto &CommandArgs = Command.getArguments();
+ size_t ArgSize = CommandArgs.size();
+ assert(ArgSize >= 1 && "Cannot have a command with 0 args");
+ const char *FirstArg = CommandArgs[0];
+ if (strcmp(FirstArg, "-cc1"))
+ return llvm::make_error<llvm::StringError>(
+ "Incorrect compilation command, missing cc1",
+ llvm::inconvertibleErrorCode());
+ Invocation = std::make_unique<CompilerInvocation>();
+ CompilerInvocation::CreateFromArgs(*Invocation, Command.getArguments(),
+ *Diags, Command.getExecutable());
+ Invocation->getFrontendOpts().DisableFree = false;
+ Invocation->getCodeGenOpts().DisableFree = false;
+
+ if (any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::Macros))
+ canonicalizeDefines(Invocation->getPreprocessorOpts());
+
+ // Create the CompilerInstance.
+ ModCache = makeInProcessModuleCache(Worker.Service.getModuleCacheEntries());
+ CIPtr = std::make_unique<CompilerInstance>(
+ std::make_shared<CompilerInvocation>(*Invocation), Worker.PCHContainerOps,
+ ModCache.get());
+ auto &CI = *CIPtr;
+
+ // TODO: the commented out code here should be un-commented when
+ // we enable CAS.
+ // CI.getInvocation().getCASOpts() = Worker.CASOpts;
+ CI.setBuildingModule(false);
+ CI.createVirtualFileSystem(OverlayFS, Diags->getClient());
+ sanitizeDiagOpts(CI.getDiagnosticOpts());
+ CI.createDiagnostics(DiagPrinter.get(), false);
+ CI.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = true;
+ CI.getFrontendOpts().GenerateGlobalModuleIndex = false;
+ CI.getFrontendOpts().UseGlobalModuleIndex = false;
+ // CI.getFrontendOpts().ModulesShareFileManager = Worker.DepCASFS ? false :
+ // true;
+ CI.getHeaderSearchOpts().ModuleFormat = "raw";
+ CI.getHeaderSearchOpts().ModulesIncludeVFSUsage =
+ any(Worker.Service.getOptimizeArgs() & ScanningOptimizations::VFS);
+ CI.getHeaderSearchOpts().ModulesStrictContextHash = true;
+ CI.getHeaderSearchOpts().ModulesSerializeOnlyPreprocessor = true;
+ CI.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true;
+ CI.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;
+ CI.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true;
+ CI.getPreprocessorOpts().ModulesCheckRelocated = false;
+
+ if (CI.getHeaderSearchOpts().ModulesValidateOncePerBuildSession)
+ CI.getHeaderSearchOpts().BuildSessionTimestamp =
+ Worker.Service.getBuildSessionTimestamp();
+
+ CI.setDiagnostics(Diags.get());
----------------
qiongsiwu wrote:
Good catch! Thanks! Fixed.
https://github.com/llvm/llvm-project/pull/160207
More information about the cfe-commits
mailing list