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
21 changes: 14 additions & 7 deletions lib/DependencyScan/ScanDependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,20 @@ static llvm::Error resolveExplicitModuleInputs(
: binaryDepDetails->moduleCacheKey;
commandLine.push_back("-swift-module-file=" + depModuleID.ModuleName + "=" +
path);
// If this binary module was built with a header, the header's module
// dependencies must also specify a .modulemap to the compilation, in
// order to resolve the header's own header include directives.
for (const auto &bridgingHeaderDepName :
binaryDepDetails->headerModuleDependencies) {
auto optionalBridgingHeaderDepModuleInfo = cache.findDependency(
{bridgingHeaderDepName, ModuleDependencyKind::Clang});
assert(optionalDepInfo.has_value());
const auto bridgingHeaderDepModuleDetails =
optionalBridgingHeaderDepModuleInfo.value()->getAsClangModule();
commandLine.push_back(
"-fmodule-map-file=" +
remapPath(bridgingHeaderDepModuleDetails->moduleMapFile));
}
} break;
case swift::ModuleDependencyKind::SwiftPlaceholder: {
auto placeholderDetails = depInfo->getAsPlaceholderDependencyModule();
Expand All @@ -278,13 +292,6 @@ static llvm::Error resolveExplicitModuleInputs(
commandLine.push_back("-Xcc");
commandLine.push_back("-fmodule-file=" + depModuleID.ModuleName + "=" +
clangDepDetails->mappedPCMPath);
if (!instance.getInvocation()
.getClangImporterOptions()
.UseClangIncludeTree) {
commandLine.push_back("-Xcc");
commandLine.push_back("-fmodule-map-file=" +
remapPath(clangDepDetails->moduleMapFile));
}
}
if (!clangDepDetails->moduleCacheKey.empty()) {
commandLine.push_back("-Xcc");
Expand Down
115 changes: 115 additions & 0 deletions test/ScanDependencies/bridging_header_dep_module_map.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/FooInputs)
// RUN: %empty-directory(%t/BridgingHeaderDir)
// RUN: %empty-directory(%t/TestCHeaders)
// RUN: %empty-directory(%t/TestSwiftInterfaces)
// RUN: %empty-directory(%t/FooModuleDir)
// RUN: split-file %s %t

// - Fixup the input module file map
// RUN: sed -e "s|INPUTSDIR|%/t/FooInputs|g" %t/map.json.template > %t/map.json.template1
// RUN: sed -e "s|STDLIBMOD|%/stdlib_module|g" %t/map.json.template1 > %t/map.json.template2
// RUN: sed -e "s|ONONEMOD|%/ononesupport_module|g" %t/map.json.template2 > %t/map.json.template3
// RUN: sed -e "s|SWIFTLIBDIR|%swift-lib-dir|g" %t/map.json.template3 > %t/map.json

// - Set up explicit dependencies for Foo
// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift-lib-dir/swift/shims/module.modulemap -o %t/FooInputs/SwiftShims.pcm
// - Build Foo module dependency, explicitly, non-resiliently
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/FooModuleDir/Foo.swiftmodule %t/foo.swift -module-name Foo -import-objc-header %t/BridgingHeaderDir/foo.h -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -disable-implicit-swift-modules -explicit-swift-module-map-file %t/map.json -I %S/Inputs/CHeaders

// - Scan main module and ensure that the "FooClient" recipe includes the modulemap for Foo's briding header's module dependencies
// but not other dependencies
// RUN: %target-swift-frontend -scan-dependencies %t/bridging_header_dep_module_map.swift -I %t/FooModuleDir -I %t/TestSwiftInterfaces -I %t/TestCHeaders -I %S/Inputs/CHeaders -o %t/deps.json
// RUN: %validate-json %t/deps.json | %FileCheck %s

// Given the following dependency graph:
//
// main
// |
// FooClient (.swiftinterface)
// | \
// Foo(.swiftmodule) Dart (.pcm)
//
// Given that 'Foo.swiftmodule' is built with a bridging header which imports 'X.h' ('X' clang module)
// We expect that 'Foo' will have a dependency on module 'X', and the scanner will ensure that 'FooClient' is built
// with the modulemap file for 'X' as an explicit input. 'Dart' Clang module however, must not result in an
// explicitly-specified modulemap file because no headers of this module will be ingested into the Swift
// compiler.

// Dependency of the main module
// CHECK: "swift": "FooClient"

// Definition of 'FooClient' in the dependency graph
// CHECK: "swift": "FooClient"
// CHECK: "modulePath": "{{.*}}FooClient-{{.*}}.swiftmodule",
// CHECK: "directDependencies": [
// CHECK-DAG: "swiftPrebuiltExternal": "Foo"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK-DAG: "clang": "Dart"
// CHECK: ],
// CHECK: "commandLine": [
// CHECK: "-fmodule-map-file={{.*}}{{/|\\}}CHeaders{{/|\\}}module.modulemap"
// CHECK-NOT: "-fmodule-map-file={{.*}}{{/|\\}}TestCHeaders{{/|\\}}module.modulemap"
// CHECK: ]

// Definition of 'Foo' in the dependency graph
// CHECK: "swiftPrebuiltExternal": "Foo"
// CHECK: "modulePath": "{{.*}}Foo.swiftmodule",
// CHECK-NEXT: "directDependencies": [
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK-DAG: "clang": "X"
// CHECK: ],
// CHECK: "headerDependency": "{{.*}}{{/|\\}}BridgingHeaderDir{{/|\\}}foo.h"
// CHECK: "headerModuleDependencies": [
// CHECK-NEXT: "X"
// CHECK-NEXT: ],
// CHECK: "headerDependenciesSourceFiles": [
// CHECK-NEXT: "{{.*}}{{/|\\}}BridgingHeaderDir{{/|\\}}foo.h"
// CHECK-NEXT: ],

//--- foo.swift
extension Profiler {
public static let count: Int = 42
}

//--- BridgingHeaderDir/foo.h
#include "X.h"
struct Profiler { void* ptr; };

//--- TestCHeaders/Dart.h
struct Dart { void* ptr; };
//--- TestCHeaders/module.modulemap
module Dart {
header "Dart.h"
export *
}

//--- TestSwiftInterfaces/FooClient.swiftinterface
// swift-interface-format-version: 1.0
// swift-module-flags: -module-name FooClient
import Foo
import Dart

//--- map.json.template
[
{
"moduleName": "Swift",
"modulePath": "STDLIBMOD",
"isFramework": false
},
{
"moduleName": "SwiftOnoneSupport",
"modulePath": "ONONEMOD",
"isFramework": false
},
{
"moduleName": "SwiftShims",
"isFramework": false,
"clangModuleMapPath": "SWIFTLIBDIR/swift/shims/module.modulemap",
"clangModulePath": "INPUTSDIR/SwiftShims.pcm"
}]

//--- bridging_header_dep_module_map.swift
import FooClient
4 changes: 2 additions & 2 deletions test/ScanDependencies/explicit-swift-dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,5 @@ import F
// CHECK-NEXT: "{{.*}}{{/|\\}}F-{{.*}}.swiftmodule"
// CHECK-DAG: "-swift-module-file=Swift={{.*}}{{/|\\}}Swift-{{.*}}.swiftmodule"
// CHECK-DAG: "-swift-module-file=SwiftOnoneSupport={{.*}}{{/|\\}}SwiftOnoneSupport-{{.*}}.swiftmodule"
// CHECK-DAG: "-fmodule-file=F={{.*}}{{/|\\}}F-{{.*}}.pcm",
// CHECK-DAG: "-fmodule-file=SwiftShims={{.*}}{{/|\\}}SwiftShims-{{.*}}.pcm",
// CHECK-DAG: "-fmodule-file=F={{.*}}{{/|\\}}F-{{.*}}.pcm"
// CHECK-DAG: "-fmodule-file=SwiftShims={{.*}}{{/|\\}}SwiftShims-{{.*}}.pcm"