mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Dependency Scanning] Scan embedded header content if file doesn't exist
Fallback to scan embedded header content when the bridging header path encoded in the swift binary module doesn't exit on the disk. rdar://144261730
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include "llvm/CAS/CachingOnDiskFileSystem.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/MemoryBufferRef.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
@@ -1063,6 +1064,42 @@ void ModuleDependencyScanner::resolveHeaderDependenciesForModule(
|
||||
if (!isTextualModuleWithABridgingHeader && !isBinaryModuleWithHeaderInput)
|
||||
return;
|
||||
|
||||
|
||||
std::optional<std::string> headerPath;
|
||||
std::unique_ptr<llvm::MemoryBuffer> sourceBuffer;
|
||||
std::optional<llvm::MemoryBufferRef> sourceBufferRef;
|
||||
|
||||
auto extractHeaderContent =
|
||||
[&](const SwiftBinaryModuleDependencyStorage &binaryMod)
|
||||
-> std::unique_ptr<llvm::MemoryBuffer> {
|
||||
auto header = binaryMod.headerImport;
|
||||
// Check to see if the header input exists on disk.
|
||||
auto FS = ScanASTContext.SourceMgr.getFileSystem();
|
||||
if (FS->exists(header))
|
||||
return nullptr;
|
||||
|
||||
auto moduleBuf = FS->getBufferForFile(binaryMod.compiledModulePath);
|
||||
if (!moduleBuf)
|
||||
return nullptr;
|
||||
|
||||
auto content = extractEmbeddedBridgingHeaderContent(std::move(*moduleBuf),
|
||||
ScanASTContext);
|
||||
if (content.empty())
|
||||
return nullptr;
|
||||
|
||||
return llvm::MemoryBuffer::getMemBufferCopy(content, header);
|
||||
};
|
||||
|
||||
if (isBinaryModuleWithHeaderInput) {
|
||||
auto &binaryMod = *moduleDependencyInfo.getAsSwiftBinaryModule();
|
||||
if (auto embeddedHeader = extractHeaderContent(binaryMod)) {
|
||||
sourceBuffer = std::move(embeddedHeader);
|
||||
sourceBufferRef = sourceBuffer->getMemBufferRef();
|
||||
} else
|
||||
headerPath = binaryMod.headerImport;
|
||||
} else
|
||||
headerPath = *moduleDependencyInfo.getBridgingHeader();
|
||||
|
||||
withDependencyScanningWorker(
|
||||
[&](ModuleDependencyScanningWorker *ScanningWorker) {
|
||||
auto clangImporter = static_cast<ClangImporter *>(
|
||||
@@ -1072,12 +1109,9 @@ void ModuleDependencyScanner::resolveHeaderDependenciesForModule(
|
||||
std::optional<std::string> includeTreeID;
|
||||
std::vector<std::string> bridgingHeaderCommandLine;
|
||||
auto headerScan = clangImporter->getHeaderDependencies(
|
||||
moduleID,
|
||||
isTextualModuleWithABridgingHeader
|
||||
? *moduleDependencyInfo.getBridgingHeader()
|
||||
: moduleDependencyInfo.getAsSwiftBinaryModule()->headerImport,
|
||||
/*sourceBuffer=*/std::nullopt, ScanningWorker->clangScanningTool,
|
||||
cache, headerClangModuleDependencies, headerFileInputs,
|
||||
moduleID, headerPath, sourceBufferRef,
|
||||
ScanningWorker->clangScanningTool, cache,
|
||||
headerClangModuleDependencies, headerFileInputs,
|
||||
bridgingHeaderCommandLine, includeTreeID);
|
||||
if (!headerScan) {
|
||||
// Record direct header Clang dependencies
|
||||
|
||||
86
test/ScanDependencies/embedded-header.swift
Normal file
86
test/ScanDependencies/embedded-header.swift
Normal file
@@ -0,0 +1,86 @@
|
||||
// REQUIRES: objc_interop
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
|
||||
// RUN: %target-swift-frontend -emit-module -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/test.swift -o %t/Test.swiftmodule \
|
||||
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -import-objc-header %t/Bridging.h
|
||||
|
||||
// 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.json \
|
||||
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t
|
||||
|
||||
/// Remove bridging header from disk and rescan
|
||||
// RUN: rm -rf %t/Bridging.h %t/Foo.h %t/Foo2.h
|
||||
// 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/deps2.json \
|
||||
// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t
|
||||
|
||||
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps.json swiftPrebuiltExternal:Test headerModuleDependencies | %FileCheck %s --check-prefix=MODULE
|
||||
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps.json swiftPrebuiltExternal:Test headerDependenciesSourceFiles | %FileCheck %s --check-prefix=FILE
|
||||
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json swiftPrebuiltExternal:Test headerModuleDependencies | %FileCheck %s --check-prefix=MODULE
|
||||
// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json swiftPrebuiltExternal:Test headerDependenciesSourceFiles | %FileCheck %s --check-prefix=FILE
|
||||
|
||||
// MODULE: "A"
|
||||
// FILE: Bridging.h
|
||||
|
||||
//--- test.swift
|
||||
public func test() {
|
||||
b()
|
||||
}
|
||||
public class TestB: B {}
|
||||
|
||||
//--- user.swift
|
||||
import Test
|
||||
|
||||
func user() {
|
||||
var b: TestB
|
||||
test()
|
||||
}
|
||||
|
||||
extension A {
|
||||
public func testA() {}
|
||||
}
|
||||
|
||||
//--- Bridging.h
|
||||
#include "Foo.h"
|
||||
#include "Foo2.h"
|
||||
|
||||
//--- Foo.h
|
||||
#import "a.h"
|
||||
#ifndef IMPORT_FOO
|
||||
#define IMPORT_FOO
|
||||
int Foo = 0;
|
||||
#endif
|
||||
|
||||
//--- Foo2.h
|
||||
#ifndef IMPORT_FOO2
|
||||
#define IMPORT_FOO2
|
||||
int Foo2 = 0;
|
||||
#endif
|
||||
|
||||
//--- a.h
|
||||
#include "b.h"
|
||||
struct A {
|
||||
int a;
|
||||
};
|
||||
|
||||
//--- b.h
|
||||
void b(void);
|
||||
@interface B
|
||||
@end
|
||||
|
||||
//--- a.modulemap
|
||||
module A {
|
||||
header "a.h"
|
||||
export *
|
||||
}
|
||||
|
||||
//--- b.modulemap
|
||||
module B {
|
||||
header "b.h"
|
||||
export *
|
||||
}
|
||||
Reference in New Issue
Block a user