Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 48 additions & 34 deletions lib/DependencyScan/ModuleDependencyScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 \"<module-" << fromModule.ModuleName << ">/"
<< llvm::sys::path::filename(buffer.getBufferIdentifier()) << "\" 1\n";
OS << buffer.getBuffer();
}

llvm::Error ModuleDependencyScanner::performBridgingHeaderChaining(
const ModuleDependencyID &rootModuleID, ModuleDependenciesCache &cache,
ModuleDependencyIDSetVector &allModules) {
Expand All @@ -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 \"<module-" << moduleName
<< "-embedded-bridging-header>\" 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;
}
}

Expand All @@ -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(
Expand Down
11 changes: 11 additions & 0 deletions test/CAS/bridging-header-prefix-map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 "<module-Test-embedded-bridging-header>" 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 \
Expand Down
11 changes: 6 additions & 5 deletions test/ScanDependencies/bridging-header-autochaining.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 "<module-Test>/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
Expand Down Expand Up @@ -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 "<module-Test>/Bridging.h" 1
// HEADER2: # 1 "<module-User>/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":
Expand Down