diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index fe42ade6a48..ac95c56461e 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -1093,6 +1093,13 @@ public: /// Allocate string inside ScanningService. StringRef save(StringRef str); + /// Get clang scanning service. + const clang::tooling::dependencies::DependencyScanningService & + getClangScanningService() const { + assert(ClangScanningService); + return *ClangScanningService; + } + private: /// Enforce clients not being allowed to query this cache directly, it must be /// wrapped in an instance of `ModuleDependenciesCache`. diff --git a/include/swift/DependencyScan/ModuleDependencyScanner.h b/include/swift/DependencyScan/ModuleDependencyScanner.h index 26b7b29331f..1996753313e 100644 --- a/include/swift/DependencyScan/ModuleDependencyScanner.h +++ b/include/swift/DependencyScan/ModuleDependencyScanner.h @@ -315,8 +315,6 @@ private: const SILOptions &SILOptions, ASTContext &ScanASTContext, DependencyTracker &DependencyTracker, - std::shared_ptr CAS, - std::shared_ptr ActionCache, DiagnosticEngine &Diagnostics, bool ParallelScan, bool EmitScanRemarks); llvm::Error initializeWorkerClangScanningTool(); diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index c0cd6762f66..1baaabd0cc0 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -655,7 +655,7 @@ swift::dependencies::registerBackDeployLibraries( bool SwiftDependencyScanningService::setupCachingDependencyScanningService( CompilerInstance &Instance) { - if (!Instance.getInvocation().getCASOptions().EnableCaching) + if (!Instance.getInvocation().requiresCAS()) return false; if (CASConfig) { diff --git a/lib/DependencyScan/DependencyScanningTool.cpp b/lib/DependencyScan/DependencyScanningTool.cpp index 3c77dce46de..e60152b3334 100644 --- a/lib/DependencyScan/DependencyScanningTool.cpp +++ b/lib/DependencyScan/DependencyScanningTool.cpp @@ -390,6 +390,12 @@ llvm::ErrorOr DependencyScanningTool::createScanQueryContext( if (std::error_code EC = Invocation.getError()) return EC; + // Setup the CAS instance from scanning service if applicable. + if (Invocation->requiresCAS()) + Instance->setSharedCASInstances( + ScanningService->getClangScanningService().getCAS(), + ScanningService->getClangScanningService().getActionCache()); + // Setup the instance std::string InstanceSetupError; if (Instance->setup(*Invocation, InstanceSetupError)) diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index dbce6bfb6fb..586c439c428 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -218,6 +218,12 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( getClangScanningFS(globalScanningService, CAS, ScanASTContext)), CAS(CAS), ActionCache(ActionCache), diagnosticReporter(DiagnosticReporter) { + assert(globalScanningService.ClangScanningService->getCAS() == CAS && + "Need to be the same CAS instance"); + assert(globalScanningService.ClangScanningService->getActionCache() == + ActionCache && + "Need to be the same ActionCache instance"); + // Instantiate a worker-specific diagnostic engine and copy over // the scanner's diagnostic consumers (expected to be thread-safe). workerDiagnosticEngine = std::make_unique(ScanASTContext.SourceMgr); @@ -534,7 +540,6 @@ ModuleDependencyScanner::create(SwiftDependencyScanningService &service, 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() @@ -560,24 +565,22 @@ ModuleDependencyScanner::ModuleDependencyScanner( ModuleDependenciesCache &Cache, const CompilerInvocation &ScanCompilerInvocation, const SILOptions &SILOptions, ASTContext &ScanASTContext, - swift::DependencyTracker &DependencyTracker, - std::shared_ptr CAS, - std::shared_ptr ActionCache, - DiagnosticEngine &Diagnostics, bool ParallelScan, - bool EmitScanRemarks) + swift::DependencyTracker &DependencyTracker, DiagnosticEngine &Diagnostics, + bool ParallelScan, bool EmitScanRemarks) : ScanCompilerInvocation(ScanCompilerInvocation), ScanASTContext(ScanASTContext), ScanDiagnosticReporter(Diagnostics, EmitScanRemarks), ModuleOutputPath(ScanCompilerInvocation.getFrontendOptions() - .ExplicitModulesOutputPath), + .ExplicitModulesOutputPath), SDKModuleOutputPath(ScanCompilerInvocation.getFrontendOptions() - .ExplicitSDKModulesOutputPath), + .ExplicitSDKModulesOutputPath), DependencyCache(Cache), NumThreads(ParallelScan ? llvm::hardware_concurrency().compute_thread_count() : 1), - ScanningThreadPool(llvm::hardware_concurrency(NumThreads)), CAS(CAS), - ActionCache(ActionCache) { + ScanningThreadPool(llvm::hardware_concurrency(NumThreads)), + CAS(ScanningService.ClangScanningService->getCAS()), + ActionCache(ScanningService.ClangScanningService->getActionCache()) { // Setup prefix mapping. auto &ScannerPrefixMapper = ScanCompilerInvocation.getSearchPathOptions().ScannerPrefixMapper; diff --git a/test/CAS/swift-scan-test-multithread.swift b/test/CAS/swift-scan-test-multithread.swift new file mode 100644 index 00000000000..30de06458cc --- /dev/null +++ b/test/CAS/swift-scan-test-multithread.swift @@ -0,0 +1,39 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +/// Test parallel dependency scanning from libSwiftScan APIs. + // RUN: %swift-scan-test -action scan_dependency -cas-path %t/cas -threads 5 -- \ +// RUN: %target-swift-frontend -scan-dependencies -target arm64-apple-macos26 -module-name Test -module-cache-path %t/clang-module-cache -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: %t/main.swift -o %t/deps.json -sdk %sdk -swift-version 5 -cache-compile-job -cas-path %t/cas -I %t/include > %t/deps.json + +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json A | %FileCheck %s --check-prefix=INTERFACE_A +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:B | %FileCheck %s --check-prefix=PCM_B +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test | %FileCheck %s --check-prefix=TEST + +// INTERFACE_A: -frontend +// INTERFACE_A: -compile-module-from-interface + +// PCM_B: -frontend +// PCM_B: -emit-pcm + +// TEST: -direct-clang-cc1-module-build + +//--- include/module.modulemap +module B { + header "B.h" + export * +} + +//--- include/B.h +void notused(void); + +//--- include/A.swiftinterface +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name A -O -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -user-module-version 1.0 +import B + +public struct A {} + +//--- main.swift +import A