[DependencyScanning] Perform Clang Module By-Name Dependency Query Using a Shared Clang Compiler Instance (#85555)

<!--
If this pull request is targeting a release branch, please fill out the
following form:

https://github.com/swiftlang/.github/blob/main/PULL_REQUEST_TEMPLATE/release.md?plain=1

Otherwise, replace this comment with a description of your changes and
rationale. Provide links to external references/discussions if
appropriate.
If this pull request resolves any GitHub issues, link them like so:

  Resolves <link to issue>, resolves <link to another issue>.

For more information about linking a pull request to an issue, see:

https://docs.github.com/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue
-->

<!--
Before merging this pull request, you must run the Swift continuous
integration tests.
For information about triggering CI builds via @swift-ci, see:

https://github.com/apple/swift/blob/main/docs/ContinuousIntegration.md#swift-ci

Thank you for your contribution to Swift!
-->

This PR teaches Swift to take advantage of the new clang dependency
scanning API to use a single clang compiler instance per dependency
scanning worker to perform by-name queries.

rdar://136303612
This commit is contained in:
Qiongsi Wu
2026-01-02 20:57:14 -08:00
committed by GitHub
parent 3b62735c51
commit 954c8a28d0
4 changed files with 117 additions and 36 deletions

View File

@@ -298,6 +298,15 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker(
workerCompilerInvocation->getSearchPathOptions().ExplicitSwiftModuleInputs);
}
llvm::Error ModuleDependencyScanningWorker::initializeClangScanningTool() {
return clangScanningTool.initializeCompilerInstanceWithContext(
clangScanningWorkingDirectoryPath, clangScanningModuleCommandLineArgs);
}
llvm::Error ModuleDependencyScanningWorker::finalizeClangScanningTool() {
return clangScanningTool.finalizeCompilerInstanceWithContext();
}
SwiftModuleScannerQueryResult
ModuleDependencyScanningWorker::scanFilesystemForSwiftModuleDependency(
Identifier moduleName, bool isTestableImport) {
@@ -308,23 +317,23 @@ ModuleDependencyScanningWorker::scanFilesystemForSwiftModuleDependency(
std::optional<clang::tooling::dependencies::TranslationUnitDeps>
ModuleDependencyScanningWorker::scanFilesystemForClangModuleDependency(
Identifier moduleName,
LookupModuleOutputCallback lookupModuleOutput,
Identifier moduleName, LookupModuleOutputCallback lookupModuleOutput,
const llvm::DenseSet<clang::tooling::dependencies::ModuleID>
&alreadySeenModules) {
diagnosticReporter.registerNamedClangModuleQuery();
auto clangModuleDependencies = clangScanningTool.getModuleDependencies(
moduleName.str(), clangScanningModuleCommandLineArgs,
clangScanningWorkingDirectoryPath, alreadySeenModules,
lookupModuleOutput);
auto clangModuleDependencies =
clangScanningTool.computeDependenciesByNameWithContext(
moduleName.str(), alreadySeenModules, lookupModuleOutput);
if (!clangModuleDependencies) {
llvm::handleAllErrors(clangModuleDependencies.takeError(), [this, &moduleName](
const llvm::StringError &E) {
llvm::handleAllErrors(
clangModuleDependencies.takeError(),
[this, &moduleName](const llvm::StringError &E) {
auto &message = E.getMessage();
if (message.find("fatal error: module '" + moduleName.str().str() +
"' not found") == std::string::npos)
workerDiagnosticEngine->diagnose(SourceLoc(), diag::clang_dependency_scan_error, message);
});
"' not found") == std::string::npos)
workerDiagnosticEngine->diagnose(
SourceLoc(), diag::clang_dependency_scan_error, message);
});
return std::nullopt;
}
return clangModuleDependencies.get();
@@ -519,6 +528,35 @@ SwiftDependencyTracker::createTreeFromDependencies() {
return *includeTreeList;
}
llvm::ErrorOr<std::unique_ptr<ModuleDependencyScanner>>
ModuleDependencyScanner::create(SwiftDependencyScanningService &service,
CompilerInstance *instance,
ModuleDependenciesCache &cache) {
auto scanner =
std::unique_ptr<ModuleDependencyScanner>(new ModuleDependencyScanner(
service, cache, instance->getInvocation(), instance->getSILOptions(),
instance->getASTContext(), *instance->getDependencyTracker(),
instance->getSharedCASInstance(), instance->getSharedCacheInstance(),
instance->getDiags(),
instance->getInvocation().getFrontendOptions().ParallelDependencyScan,
instance->getInvocation()
.getFrontendOptions()
.EmitDependencyScannerRemarks));
auto initError = scanner->initializeWorkerClangScanningTool();
if (initError) {
llvm::handleAllErrors(
std::move(initError), [&](const llvm::StringError &E) {
instance->getDiags().diagnose(
SourceLoc(), diag::clang_dependency_scan_error, E.getMessage());
});
return std::make_error_code(std::errc::invalid_argument);
}
return scanner;
}
ModuleDependencyScanner::ModuleDependencyScanner(
SwiftDependencyScanningService &ScanningService,
ModuleDependenciesCache &Cache,
@@ -566,6 +604,27 @@ ModuleDependencyScanner::ModuleDependencyScanner(
PrefixMapper.get()));
}
ModuleDependencyScanner::~ModuleDependencyScanner() {
auto finError = finalizeWorkerClangScanningTool();
assert(!finError && "ClangScanningTool finalization must succeed.");
}
llvm::Error ModuleDependencyScanner::initializeWorkerClangScanningTool() {
for (auto &W : Workers) {
if (auto error = W->initializeClangScanningTool())
return error;
}
return llvm::Error::success();
}
llvm::Error ModuleDependencyScanner::finalizeWorkerClangScanningTool() {
for (auto &W : Workers) {
if (auto error = W->finalizeClangScanningTool())
return error;
}
return llvm::Error::success();
}
static std::set<ModuleDependencyID>
collectBinarySwiftDeps(const ModuleDependenciesCache &cache) {
std::set<ModuleDependencyID> binarySwiftModuleDepIDs;