diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 5430adb2e940a..5cd19423bf489 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -1644,16 +1644,6 @@ void ModuleDependencyScanner::resolveCrossImportOverlayDependencies( allModules.end(), action); } -static void appendHeaderContent(llvm::raw_ostream &OS, - llvm::MemoryBufferRef buffer, - ModuleDependencyID fromModule) { - // Use preprocessor directives to add some clues for where the content is - // coming from. - OS << "# 1 \"/" - << llvm::sys::path::filename(buffer.getBufferIdentifier()) << "\" 1\n"; - OS << buffer.getBuffer(); -} - llvm::Error ModuleDependencyScanner::performBridgingHeaderChaining( const ModuleDependencyID &rootModuleID, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &allModules) { @@ -1663,35 +1653,60 @@ llvm::Error ModuleDependencyScanner::performBridgingHeaderChaining( llvm::SmallString<256> chainedHeaderBuffer; llvm::raw_svector_ostream outOS(chainedHeaderBuffer); + // If prefix mapping is used, don't try to import header since that will add + // a path-relative component into dependency scanning and defeat the purpose + // of prefix mapping. Additionally, if everything is prefix mapped, the + // embedded header path is also prefix mapped, thus it can't be found anyway. + bool useImportHeader = !hasPathMapping(); + auto FS = ScanASTContext.SourceMgr.getFileSystem(); + + auto chainBridgingHeader = [&](StringRef moduleName, StringRef headerPath, + StringRef binaryModulePath) -> llvm::Error { + if (useImportHeader) { + if (auto buffer = FS->getBufferForFile(headerPath)) { + outOS << "#include \"" << headerPath << "\"\n"; + return llvm::Error::success(); + } + } + + if (binaryModulePath.empty()) + return llvm::createStringError("failed to load bridging header " + + headerPath); + + // Extract the embedded bridging header + auto moduleBuf = FS->getBufferForFile(binaryModulePath); + if (!moduleBuf) + return llvm::errorCodeToError(moduleBuf.getError()); + + auto content = extractEmbeddedBridgingHeaderContent( + std::move(*moduleBuf), /*headerPath=*/"", ScanASTContext); + if (!content) + return llvm::createStringError("can't load embedded header from " + + binaryModulePath); + + outOS << "# 1 \"\" 1\n"; + outOS << content->getBuffer() << "\n"; + return llvm::Error::success(); + }; + // Iterate through all the modules and collect all the bridging header // and chain them into a single file. The allModules list is in the order of // discover, thus providing stable ordering for a deterministic generated // buffer. - auto FS = ScanASTContext.SourceMgr.getFileSystem(); for (const auto &moduleID : allModules) { if (moduleID.Kind != ModuleDependencyKind::SwiftBinary) continue; auto moduleDependencyInfo = cache.findKnownDependency(moduleID); if (auto *binaryMod = moduleDependencyInfo.getAsSwiftBinaryModule()) { - if (!binaryMod->headerImport.empty()) { - if (auto buffer= FS->getBufferForFile(binaryMod->headerImport)) { - appendHeaderContent(outOS, (*buffer)->getMemBufferRef(), moduleID); - } else { - // Extract the embedded bridging header - auto moduleBuf = FS->getBufferForFile(binaryMod->compiledModulePath); - if (!moduleBuf) - return llvm::errorCodeToError(moduleBuf.getError()); - - auto content = extractEmbeddedBridgingHeaderContent( - std::move(*moduleBuf), /*headerPath=*/"", ScanASTContext); - if (!content) - return llvm::createStringError("can't load embedded header from " + - binaryMod->compiledModulePath); - - outOS << content->getBuffer() << "\n"; - } - } + if (binaryMod->headerImport.empty()) + continue; + + if (auto E = + chainBridgingHeader(moduleID.ModuleName, binaryMod->headerImport, + binaryMod->compiledModulePath)) + return E; } } @@ -1718,11 +1733,10 @@ llvm::Error ModuleDependencyScanner::performBridgingHeaderChaining( // There are bridging header needed to be chained. Append the bridging // header from main module if needed and create use a new source buffer. if (mainModule->textualModuleDetails.bridgingHeaderFile) { - auto srcBuf = FS->getBufferForFile( - *mainModule->textualModuleDetails.bridgingHeaderFile); - if (!srcBuf) - return llvm::errorCodeToError(srcBuf.getError()); - appendHeaderContent(outOS, (*srcBuf)->getMemBufferRef(), rootModuleID); + if (auto E = chainBridgingHeader( + rootModuleID.ModuleName, + *mainModule->textualModuleDetails.bridgingHeaderFile, "")) + return E; } SmallString<256> outputPath( diff --git a/test/CAS/bridging-header-prefix-map.swift b/test/CAS/bridging-header-prefix-map.swift index 6c8cef9c5e935..fb594e082a08b 100644 --- a/test/CAS/bridging-header-prefix-map.swift +++ b/test/CAS/bridging-header-prefix-map.swift @@ -57,6 +57,17 @@ // RUN: -scanner-prefix-map-paths %t/header-1 /^header \ // RUN: -scanner-output-dir %t/header-1 -I %t +// RUN: %swift-scan-test -action get_chained_bridging_header -- %target-swift-frontend -scan-dependencies\ +// RUN: -module-name User -module-cache-path %t/clang-module-cache -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: %t/user.swift -o %t/deps-3.json -auto-bridging-header-chaining -cache-compile-job -cas-path %t/cas \ +// RUN: -scanner-prefix-map-paths %swift_src_root /^src -scanner-prefix-map-paths %t /^tmp \ +// RUN: -scanner-prefix-map-paths %t/header-1 /^header \ +// RUN: -scanner-output-dir %t/header-1 -I %t > %t/bridging-header1.h +// RUN: %FileCheck %s --input-file=%t/bridging-header1.h --check-prefix=HEADER + +// HEADER: # 1 "" 1 + // RUN: %target-swift-frontend -scan-dependencies -module-name User -module-cache-path %t/clang-module-cache -O \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ // RUN: %t/user.swift -o %t/deps-4.json -auto-bridging-header-chaining -cache-compile-job -cas-path %t/cas \ diff --git a/test/ScanDependencies/bridging-header-autochaining.swift b/test/ScanDependencies/bridging-header-autochaining.swift index edd54b6ff1385..57839b7493cba 100644 --- a/test/ScanDependencies/bridging-header-autochaining.swift +++ b/test/ScanDependencies/bridging-header-autochaining.swift @@ -60,9 +60,8 @@ // RUN: %t/user.swift -auto-bridging-header-chaining -o %t/User.swiftmodule \ // RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t > %t/header1.h // RUN: %FileCheck %s --check-prefix=HEADER1 --input-file=%t/header1.h -// HEADER1: # 1 "/Bridging.h" 1 -// HEADER1: #include "Foo.h" -// HEADER1: #include "Foo2.h" +// HEADER1: #include +// HEADER1-SAME: Bridging.h // RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps2.json bridgingHeader > %t/header1.cmd // RUN: %target-swift-frontend @%t/header1.cmd -disable-implicit-swift-modules -O -o %t/bridging1.pch @@ -94,8 +93,10 @@ // RUN: %t/user.swift -auto-bridging-header-chaining -o %t/User.swiftmodule -import-objc-header %t/Bridging2.h \ // RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t > %t/header2.h // RUN: %FileCheck %s --check-prefix=HEADER2 --input-file=%t/header2.h -// HEADER2: # 1 "/Bridging.h" 1 -// HEADER2: # 1 "/Bridging2.h" 1 +// HEADER2: #include +// HEADER2-SAME: Bridging.h +// HEADER2: #include +// HEADER2-SAME: Bridging2.h // RUN: %FileCheck %s --check-prefix DEPS_JSON --input-file=%t/deps3.json // DEPS_JSON: "chainedBridgingHeaderPath":