Skip to content

Commit c8c2090

Browse files
committed
SwiftBuild: Support Module aliasing
Ensure the SwiftBuild integratation support the same Module Aliasing feature set as the native build system. Fixes: #8987 Issue: rdar://157315793
1 parent ec2a626 commit c8c2090

File tree

4 files changed

+95
-58
lines changed

4 files changed

+95
-58
lines changed

Fixtures/ModuleAliasing/DirectDeps2/AppPkg/Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ let package = Package(
1919
package: "Bpkg",
2020
moduleAliases: ["Utils": "BUtils"]
2121
)
22-
]),
22+
]
23+
),
2324
]
2425
)
2526

Sources/PackageGraph/Resolution/ResolvedProduct.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public struct ResolvedProduct {
179179

180180
extension ResolvedProduct: CustomStringConvertible {
181181
public var description: String {
182-
"<ResolvedProduct: \(self.name), \(self.type)>"
182+
"<ResolvedProduct: \(self.packageIdentity), \(self.name), \(self.type)>"
183183
}
184184
}
185185

Sources/SwiftBuildSupport/PackagePIFBuilder+Helpers.swift

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ extension PackageModel.Product {
104104
var pifTargetGUID: GUID { pifTargetGUID(suffix: nil) }
105105

106106
func pifTargetGUID(suffix: TargetSuffix?) -> GUID {
107-
PackagePIFBuilder.targetGUID(forProductName: self.name, suffix: suffix)
107+
PackagePIFBuilder.targetGUID(forProductName: self.name, withId:self.identity, suffix: suffix)
108108
}
109109
}
110110

@@ -134,11 +134,11 @@ extension PackagePIFBuilder {
134134
///
135135
/// This format helps make sure that there is no collision with any other PIF targets,
136136
/// and in particular that a PIF target and a PIF product can have the same name (as they often do).
137-
static func targetGUID(forProductName name: String, suffix: TargetSuffix? = nil) -> GUID {
138-
let suffixDescription = suffix.uniqueDescription(forName: name)
139-
return "PACKAGE-PRODUCT:\(name)\(suffixDescription)"
137+
static func targetGUID(forProductName name: String, withId id: String, suffix: TargetSuffix? = nil) -> GUID {
138+
let suffixDescription: String = suffix.uniqueDescription(forName: name)
139+
return "PACKAGE-PRODUCT:\(id).\(name)\(suffixDescription)"
140140
}
141-
141+
142142
/// Helper function to consistently generate a target name string for a product in a package.
143143
///
144144
/// This format helps make sure that modules and products with the same name (as they often have)
@@ -775,13 +775,13 @@ extension Collection<PackageGraph.ResolvedModule> {
775775
/// Recursively applies a block to each of the *dependencies* of the given module, in topological sort order.
776776
/// Each module or product dependency is visited only once.
777777
func recursivelyTraverseDependencies(with block: (ResolvedModule.Dependency) -> Void) {
778-
var moduleNamesSeen: Set<String> = []
779-
var productNamesSeen: Set<String> = []
778+
var moduleGuidsSeen: Set<ResolvedModule.ID> = []
779+
var productGuidsSeen: Set<ResolvedProduct.ID> = []
780780

781781
func visitDependency(_ dependency: ResolvedModule.Dependency) {
782782
switch dependency {
783783
case .module(let moduleDependency, _):
784-
let (unseenModule, _) = moduleNamesSeen.insert(moduleDependency.name)
784+
let (unseenModule, _) = moduleGuidsSeen.insert(moduleDependency.id)
785785
guard unseenModule else { return }
786786

787787
if moduleDependency.underlying.type != .macro {
@@ -792,15 +792,15 @@ extension Collection<PackageGraph.ResolvedModule> {
792792
block(dependency)
793793

794794
case .product(let productDependency, let conditions):
795-
let (unseenProduct, _) = productNamesSeen.insert(productDependency.name)
795+
let (unseenProduct, _) = productGuidsSeen.insert(productDependency.id)
796796
guard unseenProduct && !productDependency.isBinaryOnlyExecutableProduct else { return }
797797
block(dependency)
798798

799799
// We need to visit any binary modules to be able to add direct references to them to any client
800800
// targets.
801801
// This is needed so that XCFramework processing always happens *prior* to building any client targets.
802802
for moduleDependency in productDependency.modules where moduleDependency.isBinary {
803-
if moduleNamesSeen.contains(moduleDependency.name) { continue }
803+
if moduleGuidsSeen.contains(moduleDependency.id) { continue }
804804
block(.module(moduleDependency, conditions: conditions))
805805
}
806806
}
@@ -848,12 +848,13 @@ extension ProjectModel.BuildSettings {
848848
extension ProjectModel.Project {
849849
@discardableResult
850850
public mutating func addTarget(
851+
packageProductId: String,
851852
packageProductName: String,
852853
productType: ProjectModel.Target.ProductType
853854
) throws -> WritableKeyPath<ProjectModel.Project, ProjectModel.Target> {
854855
let targetKeyPath = try self.addTarget { _ in
855856
ProjectModel.Target(
856-
id: PackagePIFBuilder.targetGUID(forProductName: packageProductName),
857+
id: PackagePIFBuilder.targetGUID(forProductName: packageProductName, withId: packageProductId),
857858
productType: productType,
858859
name: packageProductName,
859860
productName: packageProductName

Tests/FunctionalTests/ModuleAliasingFixtureTests.swift

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,39 @@ struct ModuleAliasingFixtureTests {
3030
.tags(
3131
Tag.Feature.Command.Build,
3232
),
33-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
33+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
3434
)
3535
func moduleDirectDeps1(
36-
buildSystem: BuildSystemProvider.Kind,
37-
configuration: BuildConfiguration,
36+
data: BuildData,
3837
) async throws {
38+
let buildSystem = data.buildSystem
39+
let configuration = data.config
40+
3941
try await withKnownIssue(isIntermittent: true) {
4042
try await fixture(name: "ModuleAliasing/DirectDeps1") { fixturePath in
4143
let pkgPath = fixturePath.appending(components: "AppPkg")
4244
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
45+
let expectedModules = [
46+
"GameUtils.swiftmodule",
47+
"Utils.swiftmodule",
48+
]
4349
try await executeSwiftBuild(
4450
pkgPath,
4551
configuration: configuration,
4652
extraArgs: ["--vv"],
4753
buildSystem: buildSystem,
4854
)
55+
4956
expectFileExists(at: buildPath.appending(components: executableName("App")))
50-
switch buildSystem {
57+
for file in expectedModules {
58+
switch buildSystem {
5159
case .native:
52-
expectFileExists(at: buildPath.appending(components: "Modules", "GameUtils.swiftmodule"))
53-
expectFileExists(at: buildPath.appending(components: "Modules", "Utils.swiftmodule"))
60+
expectFileExists(at: buildPath.appending(components: "Modules", file))
5461
case .swiftbuild:
55-
expectFileExists(at: buildPath.appending(components: "GameUtils.swiftmodule"))
56-
expectFileExists(at: buildPath.appending(components: "Utils.swiftmodule"))
62+
expectFileExists(at: buildPath.appending(components: file))
5763
case .xcode:
58-
#expect(Bool(false), "expectations are not implemented")
64+
Issue.record("expectations are not implemented")
65+
}
5966
}
6067
_ = try await executeSwiftBuild(
6168
pkgPath,
@@ -67,93 +74,112 @@ struct ModuleAliasingFixtureTests {
6774
ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild
6875
}
6976
}
70-
77+
7178
@Test(
7279
.issue("https://github.com/swiftlang/swift-package-manager/issues/8987", relationship: .defect),
7380
.tags(
7481
Tag.Feature.Command.Build,
7582
),
76-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
83+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
7784
)
7885
func moduleDirectDeps2(
79-
buildSystem: BuildSystemProvider.Kind,
80-
configuration: BuildConfiguration,
86+
data: BuildData
8187
) async throws {
82-
try await withKnownIssue {
88+
let buildSystem = data.buildSystem
89+
let configuration = data.config
8390
try await fixture(name: "ModuleAliasing/DirectDeps2") { fixturePath in
8491
let pkgPath = fixturePath.appending(components: "AppPkg")
8592
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
93+
let expectedModules = [
94+
"AUtils.swiftmodule",
95+
"BUtils.swiftmodule",
96+
]
8697
try await executeSwiftBuild(
8798
pkgPath,
8899
configuration: configuration,
89100
extraArgs: ["--vv"],
90101
buildSystem: buildSystem,
91102
)
92103
expectFileExists(at: buildPath.appending(components: executableName("App")))
93-
expectFileExists(at: buildPath.appending(components: "Modules", "AUtils.swiftmodule"))
94-
expectFileExists(at: buildPath.appending(components: "Modules", "BUtils.swiftmodule"))
104+
for file in expectedModules {
105+
switch buildSystem {
106+
case .native:
107+
expectFileExists(at: buildPath.appending(components: "Modules", file))
108+
case .swiftbuild:
109+
expectFileExists(at: buildPath.appending(components: file))
110+
case .xcode:
111+
Issue.record("expectations are not implemented")
112+
}
113+
}
95114
_ = try await executeSwiftBuild(
96115
pkgPath,
97116
configuration: configuration,
98117
buildSystem: buildSystem,
99118
)
100119
}
101-
} when: {
102-
buildSystem == .swiftbuild
103-
}
104120
}
105-
121+
106122
@Test(
107123
.issue("https://github.com/swiftlang/swift-package-manager/issues/8987", relationship: .defect),
108124
.tags(
109125
Tag.Feature.Command.Build,
110126
),
111-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
127+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
112128
)
113129
func moduleNestedDeps1(
114-
buildSystem: BuildSystemProvider.Kind,
115-
configuration: BuildConfiguration,
130+
data: BuildData,
116131
) async throws {
117-
try await withKnownIssue {
132+
let buildSystem = data.buildSystem
133+
let configuration = data.config
118134
try await fixture(name: "ModuleAliasing/NestedDeps1") { fixturePath in
119135
let pkgPath = fixturePath.appending(components: "AppPkg")
120136
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
137+
let expectedModules = [
138+
"A.swiftmodule",
139+
"AFooUtils.swiftmodule",
140+
"CarUtils.swiftmodule",
141+
"X.swiftmodule",
142+
"XFooUtils.swiftmodule",
143+
"XUtils.swiftmodule",
144+
]
121145
try await executeSwiftBuild(
122146
pkgPath,
123147
configuration: configuration,
124148
extraArgs: ["--vv"],
125149
buildSystem: buildSystem,
126150
)
127151
expectFileExists(at: buildPath.appending(components: executableName("App")))
128-
expectFileExists(at: buildPath.appending(components: "Modules", "A.swiftmodule"))
129-
expectFileExists(at: buildPath.appending(components: "Modules", "AFooUtils.swiftmodule"))
130-
expectFileExists(at: buildPath.appending(components: "Modules", "CarUtils.swiftmodule"))
131-
expectFileExists(at: buildPath.appending(components: "Modules", "X.swiftmodule"))
132-
expectFileExists(at: buildPath.appending(components: "Modules", "XFooUtils.swiftmodule"))
133-
expectFileExists(at: buildPath.appending(components: "Modules", "XUtils.swiftmodule"))
152+
for file in expectedModules {
153+
switch buildSystem {
154+
case .native:
155+
expectFileExists(at: buildPath.appending(components: "Modules", file))
156+
case .swiftbuild:
157+
expectFileExists(at: buildPath.appending(components: file))
158+
case .xcode:
159+
Issue.record("expectations are not implemented")
160+
}
161+
}
162+
134163
_ = try await executeSwiftBuild(
135164
pkgPath,
136165
configuration: configuration,
137166
buildSystem: buildSystem,
138167
)
139168
}
140-
} when: {
141-
buildSystem == .swiftbuild
142-
}
143169
}
144-
170+
145171
@Test(
146172
.issue("https://github.com/swiftlang/swift-package-manager/issues/8987", relationship: .defect),
147173
.tags(
148174
Tag.Feature.Command.Build,
149175
),
150-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
176+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
151177
)
152178
func moduleNestedDeps2(
153-
buildSystem: BuildSystemProvider.Kind,
154-
configuration: BuildConfiguration,
179+
data: BuildData,
155180
) async throws {
156-
try await withKnownIssue {
181+
let buildSystem = data.buildSystem
182+
let configuration = data.config
157183
try await fixture(name: "ModuleAliasing/NestedDeps2") { fixturePath in
158184
let pkgPath = fixturePath.appending(components: "AppPkg")
159185
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
@@ -163,19 +189,28 @@ struct ModuleAliasingFixtureTests {
163189
extraArgs: ["--vv"],
164190
buildSystem: buildSystem,
165191
)
192+
let expectedModules = [
193+
"A.swiftmodule",
194+
"BUtils.swiftmodule",
195+
"CUtils.swiftmodule",
196+
"XUtils.swiftmodule",
197+
]
166198
expectFileExists(at: buildPath.appending(components: executableName("App")))
167-
expectFileExists(at: buildPath.appending(components: "Modules", "A.swiftmodule"))
168-
expectFileExists(at: buildPath.appending(components: "Modules", "BUtils.swiftmodule"))
169-
expectFileExists(at: buildPath.appending(components: "Modules", "CUtils.swiftmodule"))
170-
expectFileExists(at: buildPath.appending(components: "Modules", "XUtils.swiftmodule"))
199+
for file in expectedModules {
200+
switch buildSystem {
201+
case .native:
202+
expectFileExists(at: buildPath.appending(components: "Modules", file))
203+
case .swiftbuild:
204+
expectFileExists(at: buildPath.appending(components: file))
205+
case .xcode:
206+
Issue.record("expectations are not implemented")
207+
}
208+
}
171209
_ = try await executeSwiftBuild(
172210
pkgPath,
173211
configuration: configuration,
174212
buildSystem: buildSystem,
175213
)
176214
}
177-
} when: {
178-
buildSystem == .swiftbuild
179-
}
180215
}
181216
}

0 commit comments

Comments
 (0)