From 8237e1b421726aa4bac2e03e6f3a6c386bcce411 Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Thu, 13 Feb 2025 16:48:29 -0800 Subject: [PATCH] [scanner] setup the clang importer injected redirecting overlay vfs for correct clang dependency scanning This makes its possible to use -explicit-module-build to correctly find 'crt' swift module on windows --- include/swift/ClangImporter/ClangImporter.h | 8 ++++ lib/ClangImporter/ClangImporter.cpp | 35 +--------------- lib/ClangImporter/ClangIncludePaths.cpp | 40 +++++++++++++++++++ .../ModuleDependencyScanner.cpp | 16 +++++++- test/ScanDependencies/win-crt.swift | 11 +++++ 5 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 test/ScanDependencies/win-crt.swift diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index d03ab411a82ab..458db87ec9364 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -767,6 +767,14 @@ ClangInvocationFileMapping getClangInvocationFileMapping( llvm::IntrusiveRefCntPtr vfs = nullptr, bool suppressDiagnostic = false); +/// Construct the clang overlay VFS that's needed for the clang instance +/// used by the clang importer to find injected platform-specific modulemaps +/// that are created by `getClangInvocationFileMapping`. +llvm::IntrusiveRefCntPtr +createClangInvocationFileMappingVFS( + const ClangInvocationFileMapping &fileMapping, ASTContext &ctx, + llvm::IntrusiveRefCntPtr baseVFS); + } // end namespace swift #endif diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 75158605be464..b881e229328f0 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -1333,39 +1333,8 @@ ClangImporter::create(ASTContext &ctx, // Avoid creating indirect file system when using include tree. if (!ctx.ClangImporterOpts.HasClangIncludeTreeRoot) { // Wrap Swift's FS to allow Clang to override the working directory - VFS = llvm::vfs::RedirectingFileSystem::create( - fileMapping.redirectedFiles, true, *ctx.SourceMgr.getFileSystem()); - if (importerOpts.DumpClangDiagnostics) { - llvm::errs() << "clang importer redirected file mappings:\n"; - for (const auto &mapping : fileMapping.redirectedFiles) { - llvm::errs() << " mapping real file '" << mapping.second - << "' to virtual file '" << mapping.first << "'\n"; - } - llvm::errs() << "\n"; - } - - if (!fileMapping.overridenFiles.empty()) { - llvm::IntrusiveRefCntPtr overridenVFS = - new llvm::vfs::InMemoryFileSystem(); - for (const auto &file : fileMapping.overridenFiles) { - if (importerOpts.DumpClangDiagnostics) { - llvm::errs() << "clang importer overriding file '" << file.first - << "' with the following contents:\n"; - llvm::errs() << file.second << "\n"; - } - auto contents = ctx.Allocate(file.second.size() + 1); - std::copy(file.second.begin(), file.second.end(), contents.begin()); - // null terminate the buffer. - contents[contents.size() - 1] = '\0'; - overridenVFS->addFile(file.first, 0, - llvm::MemoryBuffer::getMemBuffer(StringRef( - contents.begin(), contents.size() - 1))); - } - llvm::IntrusiveRefCntPtr overlayVFS = - new llvm::vfs::OverlayFileSystem(VFS); - VFS = overlayVFS; - overlayVFS->pushOverlay(overridenVFS); - } + VFS = createClangInvocationFileMappingVFS(fileMapping, ctx, + ctx.SourceMgr.getFileSystem()); } // Create a new Clang compiler invocation. diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index d2185fd152ded..a35a10d818a6b 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -655,3 +655,43 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( result.requiresBuiltinHeadersInSystemModules); return result; } + +llvm::IntrusiveRefCntPtr +swift::createClangInvocationFileMappingVFS( + const ClangInvocationFileMapping &fileMapping, ASTContext &ctx, + llvm::IntrusiveRefCntPtr baseVFS) { + llvm::IntrusiveRefCntPtr redirectedVFS = + llvm::vfs::RedirectingFileSystem::create(fileMapping.redirectedFiles, + true, *baseVFS); + if (ctx.ClangImporterOpts.DumpClangDiagnostics) { + llvm::errs() << "clang importer redirected file mappings:\n"; + for (const auto &mapping : fileMapping.redirectedFiles) { + llvm::errs() << " mapping real file '" << mapping.second + << "' to virtual file '" << mapping.first << "'\n"; + } + llvm::errs() << "\n"; + } + + if (fileMapping.overridenFiles.empty()) + return redirectedVFS; + llvm::IntrusiveRefCntPtr overridenVFS = + new llvm::vfs::InMemoryFileSystem(); + for (const auto &file : fileMapping.overridenFiles) { + if (ctx.ClangImporterOpts.DumpClangDiagnostics) { + llvm::errs() << "clang importer overriding file '" << file.first + << "' with the following contents:\n"; + llvm::errs() << file.second << "\n"; + } + auto contents = ctx.Allocate(file.second.size() + 1); + std::copy(file.second.begin(), file.second.end(), contents.begin()); + // null terminate the buffer. + contents[contents.size() - 1] = '\0'; + overridenVFS->addFile(file.first, 0, + llvm::MemoryBuffer::getMemBuffer(StringRef( + contents.begin(), contents.size() - 1))); + } + llvm::IntrusiveRefCntPtr overlayVFS = + new llvm::vfs::OverlayFileSystem(redirectedVFS); + overlayVFS->pushOverlay(overridenVFS); + return overlayVFS; +} diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index d56f2ddedd35d..df9a395513e3f 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -179,13 +179,25 @@ static bool isSwiftDependencyKind(ModuleDependencyKind Kind) { Kind == ModuleDependencyKind::SwiftPlaceholder; } +static llvm::IntrusiveRefCntPtr +getClangInvocationOverlayScanningVFS( + ASTContext &ctx, llvm::IntrusiveRefCntPtr baseFS) { + auto fileMapping = swift::getClangInvocationFileMapping( + ctx, baseFS, /*suppressDiagnostic=*/true); + if (fileMapping.redirectedFiles.empty()) + return baseFS; + return createClangInvocationFileMappingVFS(fileMapping, ctx, baseFS); +} + ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( SwiftDependencyScanningService &globalScanningService, const CompilerInvocation &ScanCompilerInvocation, const SILOptions &SILOptions, ASTContext &ScanASTContext, swift::DependencyTracker &DependencyTracker, DiagnosticEngine &Diagnostics) - : clangScanningTool(*globalScanningService.ClangScanningService, - globalScanningService.getClangScanningFS()) { + : clangScanningTool( + *globalScanningService.ClangScanningService, + getClangInvocationOverlayScanningVFS( + ScanASTContext, globalScanningService.getClangScanningFS())) { // Create a scanner-specific Invocation and ASTContext. workerCompilerInvocation = std::make_unique(ScanCompilerInvocation); diff --git a/test/ScanDependencies/win-crt.swift b/test/ScanDependencies/win-crt.swift new file mode 100644 index 0000000000000..0b1055d4087c3 --- /dev/null +++ b/test/ScanDependencies/win-crt.swift @@ -0,0 +1,11 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -scan-dependencies -Xcc -v %s -o - | %validate-json | %FileCheck %s + +// We want to explicitly import WinSDK's CRT. +// REQUIRES: OS=windows-msvc + +import CRT + +// CHECK: "modulePath": "{{.*}}\\ucrt-{{.*}}.pcm", +// CHECK-NEXT: "sourceFiles": [ +// CHECK-NEXT: "{{.*}}\\ucrt\\module.modulemap"