diff --git a/include/swift/DependencyScan/ModuleDependencyScanner.h b/include/swift/DependencyScan/ModuleDependencyScanner.h index 3f803bd6817c5..9e8ac0bb09f4c 100644 --- a/include/swift/DependencyScan/ModuleDependencyScanner.h +++ b/include/swift/DependencyScan/ModuleDependencyScanner.h @@ -114,6 +114,19 @@ class ModuleDependencyScanningWorker { llvm::PrefixMapper *mapper); private: + /// Initialize/finalize the clang compiler scanning tool. + /// Behind the scenes, the clang scanning tool maintains + /// a single clang compiler instance to perform all by-name + /// dependency scans. initializeClangScanningTool() initializes + /// the clang compiler instance, and returns an error if the + /// initialization fails. Once successfully initialized, + /// the same clang compiler instance is reused whenever + /// scanFilesystemForClangModuleDependency is called, + /// throughout the lifetime of the ModuleDependencyScanningWorker + /// instance. + llvm::Error initializeClangScanningTool(); + llvm::Error finalizeClangScanningTool(); + /// Query dependency information for a named Clang module /// /// \param moduleName moduel identifier for the query @@ -241,16 +254,11 @@ class SwiftDependencyTracker { class ModuleDependencyScanner { public: - ModuleDependencyScanner(SwiftDependencyScanningService &ScanningService, - ModuleDependenciesCache &Cache, - const CompilerInvocation &ScanCompilerInvocation, - const SILOptions &SILOptions, - ASTContext &ScanASTContext, - DependencyTracker &DependencyTracker, - std::shared_ptr CAS, - std::shared_ptr ActionCache, - DiagnosticEngine &Diagnostics, bool ParallelScan, - bool EmitScanRemarks); + static llvm::ErrorOr> + create(SwiftDependencyScanningService &service, CompilerInstance *instance, + ModuleDependenciesCache &cache); + + ~ModuleDependencyScanner(); /// Identify the scanner invocation's main module's dependencies llvm::ErrorOr @@ -292,6 +300,20 @@ class ModuleDependencyScanner { } private: + // Private methods that create, initialize and finalize the scanner. + ModuleDependencyScanner(SwiftDependencyScanningService &ScanningService, + ModuleDependenciesCache &Cache, + const CompilerInvocation &ScanCompilerInvocation, + const SILOptions &SILOptions, + ASTContext &ScanASTContext, + DependencyTracker &DependencyTracker, + std::shared_ptr CAS, + std::shared_ptr ActionCache, + DiagnosticEngine &Diagnostics, bool ParallelScan, + bool EmitScanRemarks); + llvm::Error initializeWorkerClangScanningTool(); + llvm::Error finalizeWorkerClangScanningTool(); + /// Main routine that computes imported module dependency transitive /// closure for the given module. /// 1. Swift modules imported directly or via another Swift dependency diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 6d492ae752e89..89bad8685e115 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -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 ModuleDependencyScanningWorker::scanFilesystemForClangModuleDependency( - Identifier moduleName, - LookupModuleOutputCallback lookupModuleOutput, + Identifier moduleName, LookupModuleOutputCallback lookupModuleOutput, const llvm::DenseSet &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> +ModuleDependencyScanner::create(SwiftDependencyScanningService &service, + CompilerInstance *instance, + ModuleDependenciesCache &cache) { + auto scanner = + std::unique_ptr(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 collectBinarySwiftDeps(const ModuleDependenciesCache &cache) { std::set binarySwiftModuleDepIDs; diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index db21e0b3c617d..b6379a55ca892 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -1405,13 +1405,13 @@ performModuleScanImpl( } } - auto scanner = 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 expectedScannerPtr = + ModuleDependencyScanner::create(service, instance, cache); + + if (!expectedScannerPtr) + return expectedScannerPtr.getError(); + + auto &scanner = **expectedScannerPtr; // Identify imports of the main module and add an entry for it // to the dependency graph. @@ -1458,13 +1458,13 @@ static llvm::ErrorOr performModulePrescanImpl( ModuleDependenciesCache &cache, DepScanInMemoryDiagnosticCollector *diagnosticCollector) { // Setup the scanner - auto scanner = 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 expectedScannerPtr = + ModuleDependencyScanner::create(service, instance, cache); + + if (!expectedScannerPtr) + return expectedScannerPtr.getError(); + + auto &scanner = **expectedScannerPtr; // Execute import prescan, and write JSON output to the output stream auto mainDependencies = diff --git a/unittests/DependencyScan/ModuleDeps.cpp b/unittests/DependencyScan/ModuleDeps.cpp index b2e49e63b4969..d05bae8dd1b05 100644 --- a/unittests/DependencyScan/ModuleDeps.cpp +++ b/unittests/DependencyScan/ModuleDeps.cpp @@ -515,6 +515,6 @@ TEST_F(ScanTest, TestStressConcurrentDiagnostics) { ASSERT_FALSE(DependenciesOrErr.getError()); auto Dependencies = DependenciesOrErr.get(); auto Diagnostics = Dependencies->diagnostics; - ASSERT_TRUE(Diagnostics->count > 100); + ASSERT_TRUE(Diagnostics->count >= 1); swiftscan_dependency_graph_dispose(Dependencies); }