Skip to content

Commit 18bc480

Browse files
authored
SwiftBuild: Support Module aliasing (#9135)
Ensure the SwiftBuild integratation support the same Module Aliasing feature set as the native build system. Fixes: #8987 Issue: rdar://157315793
1 parent a9e72ad commit 18bc480

File tree

4 files changed

+110
-52
lines changed

4 files changed

+110
-52
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: 95 additions & 39 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,130 @@ 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),
80+
.issue("https://github.com/swiftlang/swift-package-manager/pull/9130", relationship: .fixedBy),
81+
.IssueWindowsLongPath,
82+
.IssueWindowsCannotSaveAttachment,
7383
.tags(
7484
Tag.Feature.Command.Build,
7585
),
76-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
86+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
7787
)
7888
func moduleDirectDeps2(
79-
buildSystem: BuildSystemProvider.Kind,
80-
configuration: BuildConfiguration,
89+
data: BuildData
8190
) async throws {
82-
try await withKnownIssue {
91+
let buildSystem = data.buildSystem
92+
let configuration = data.config
93+
try await withKnownIssue(isIntermittent: true) {
8394
try await fixture(name: "ModuleAliasing/DirectDeps2") { fixturePath in
8495
let pkgPath = fixturePath.appending(components: "AppPkg")
8596
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
97+
let expectedModules = [
98+
"AUtils.swiftmodule",
99+
"BUtils.swiftmodule",
100+
]
86101
try await executeSwiftBuild(
87102
pkgPath,
88103
configuration: configuration,
89104
extraArgs: ["--vv"],
90105
buildSystem: buildSystem,
91106
)
92107
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"))
108+
for file in expectedModules {
109+
switch buildSystem {
110+
case .native:
111+
expectFileExists(at: buildPath.appending(components: "Modules", file))
112+
case .swiftbuild:
113+
expectFileExists(at: buildPath.appending(components: file))
114+
case .xcode:
115+
Issue.record("expectations are not implemented")
116+
}
117+
}
95118
_ = try await executeSwiftBuild(
96119
pkgPath,
97120
configuration: configuration,
98121
buildSystem: buildSystem,
99122
)
100123
}
101124
} when: {
102-
buildSystem == .swiftbuild
125+
ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild
103126
}
104127
}
105-
128+
106129
@Test(
107130
.issue("https://github.com/swiftlang/swift-package-manager/issues/8987", relationship: .defect),
131+
.issue("https://github.com/swiftlang/swift-package-manager/pull/9130", relationship: .fixedBy),
132+
.IssueWindowsLongPath,
133+
.IssueWindowsCannotSaveAttachment,
108134
.tags(
109135
Tag.Feature.Command.Build,
110136
),
111-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
137+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
112138
)
113139
func moduleNestedDeps1(
114-
buildSystem: BuildSystemProvider.Kind,
115-
configuration: BuildConfiguration,
140+
data: BuildData,
116141
) async throws {
117-
try await withKnownIssue {
142+
let buildSystem = data.buildSystem
143+
let configuration = data.config
144+
try await withKnownIssue(isIntermittent: true) {
118145
try await fixture(name: "ModuleAliasing/NestedDeps1") { fixturePath in
119146
let pkgPath = fixturePath.appending(components: "AppPkg")
120147
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
148+
let expectedModules = [
149+
"A.swiftmodule",
150+
"AFooUtils.swiftmodule",
151+
"CarUtils.swiftmodule",
152+
"X.swiftmodule",
153+
"XFooUtils.swiftmodule",
154+
"XUtils.swiftmodule",
155+
]
121156
try await executeSwiftBuild(
122157
pkgPath,
123158
configuration: configuration,
124159
extraArgs: ["--vv"],
125160
buildSystem: buildSystem,
126161
)
127162
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"))
163+
for file in expectedModules {
164+
switch buildSystem {
165+
case .native:
166+
expectFileExists(at: buildPath.appending(components: "Modules", file))
167+
case .swiftbuild:
168+
expectFileExists(at: buildPath.appending(components: file))
169+
case .xcode:
170+
Issue.record("expectations are not implemented")
171+
}
172+
}
173+
134174
_ = try await executeSwiftBuild(
135175
pkgPath,
136176
configuration: configuration,
137177
buildSystem: buildSystem,
138178
)
139179
}
140180
} when: {
141-
buildSystem == .swiftbuild
181+
ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild
142182
}
143183
}
144-
184+
145185
@Test(
146186
.issue("https://github.com/swiftlang/swift-package-manager/issues/8987", relationship: .defect),
187+
.issue("https://github.com/swiftlang/swift-package-manager/pull/9130", relationship: .fixedBy),
188+
.IssueWindowsLongPath,
189+
.IssueWindowsCannotSaveAttachment,
147190
.tags(
148191
Tag.Feature.Command.Build,
149192
),
150-
arguments: SupportedBuildSystemOnAllPlatforms, BuildConfiguration.allCases,
193+
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
151194
)
152195
func moduleNestedDeps2(
153-
buildSystem: BuildSystemProvider.Kind,
154-
configuration: BuildConfiguration,
196+
data: BuildData,
155197
) async throws {
156-
try await withKnownIssue {
198+
let buildSystem = data.buildSystem
199+
let configuration = data.config
200+
try await withKnownIssue(isIntermittent: true) {
157201
try await fixture(name: "ModuleAliasing/NestedDeps2") { fixturePath in
158202
let pkgPath = fixturePath.appending(components: "AppPkg")
159203
let buildPath = try pkgPath.appending(components: buildSystem.binPath(for: configuration))
@@ -163,19 +207,31 @@ struct ModuleAliasingFixtureTests {
163207
extraArgs: ["--vv"],
164208
buildSystem: buildSystem,
165209
)
210+
let expectedModules = [
211+
"A.swiftmodule",
212+
"BUtils.swiftmodule",
213+
"CUtils.swiftmodule",
214+
"XUtils.swiftmodule",
215+
]
166216
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"))
217+
for file in expectedModules {
218+
switch buildSystem {
219+
case .native:
220+
expectFileExists(at: buildPath.appending(components: "Modules", file))
221+
case .swiftbuild:
222+
expectFileExists(at: buildPath.appending(components: file))
223+
case .xcode:
224+
Issue.record("expectations are not implemented")
225+
}
226+
}
171227
_ = try await executeSwiftBuild(
172228
pkgPath,
173229
configuration: configuration,
174230
buildSystem: buildSystem,
175231
)
176232
}
177233
} when: {
178-
buildSystem == .swiftbuild
234+
ProcessInfo.hostOperatingSystem == .windows && buildSystem == .swiftbuild
179235
}
180236
}
181237
}

0 commit comments

Comments
 (0)