Skip to content

Commit 11815a3

Browse files
kateinoigakukunfurby-tm
authored andcommitted
Make supportedTriples optional in artifactbundle metadata (swiftlang#7432)
Make `supportedTriples` optional in artifactbundle metadata ### Motivation: We don't have a good way to express a Swift SDK that can be used on any host platform except for listing up all possible platforms. ### Modifications: This change allows `supportedTriples` field to be null or missing to express that the SDK is universally usable. Also this fixes a minor issue around `swift experimental-sdk configuration`, that did not take care of runtime compatibility of OS version in host triples. ### Result: SwiftPM now accepts host-platform independent Swift SDK
1 parent e108674 commit 11815a3

File tree

5 files changed

+140
-10
lines changed

5 files changed

+140
-10
lines changed

Sources/PackageModel/ArtifactsArchiveMetadata.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ public struct ArtifactsArchiveMetadata: Equatable {
5252

5353
public struct Variant: Equatable {
5454
public let path: RelativePath
55-
public let supportedTriples: [Triple]
55+
public let supportedTriples: [Triple]?
5656

57-
public init(path: RelativePath, supportedTriples: [Triple]) {
57+
public init(path: RelativePath, supportedTriples: [Triple]?) {
5858
self.path = path
5959
self.supportedTriples = supportedTriples
6060
}
@@ -121,7 +121,7 @@ extension ArtifactsArchiveMetadata.Variant: Decodable {
121121

122122
public init(from decoder: Decoder) throws {
123123
let container = try decoder.container(keyedBy: CodingKeys.self)
124-
self.supportedTriples = try container.decode([String].self, forKey: .supportedTriples).map { try Triple($0) }
124+
self.supportedTriples = try container.decodeIfPresent([String].self, forKey: .supportedTriples)?.map { try Triple($0) }
125125
self.path = try RelativePath(validating: container.decode(String.self, forKey: .path))
126126
}
127127
}

Sources/PackageModel/SwiftSDKs/SwiftSDKBundle.swift

+15-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ public struct SwiftSDKBundle {
3333
public var name: String { path.basename }
3434
}
3535

36+
extension SwiftSDKBundle.Variant {
37+
/// Whether the given host triple is supported by this SDK variant
38+
internal func isSupporting(hostTriple: Triple) -> Bool {
39+
guard let supportedTriples = metadata.supportedTriples else {
40+
// No supportedTriples means the SDK can be universally usable
41+
return true
42+
}
43+
return supportedTriples.contains(where: { variantTriple in
44+
hostTriple.isRuntimeCompatible(with: variantTriple)
45+
})
46+
}
47+
}
48+
3649
extension [SwiftSDKBundle] {
3750
/// Select a Swift SDK with a given artifact ID from a `self` array of available Swift SDKs.
3851
/// - Parameters:
@@ -48,7 +61,7 @@ extension [SwiftSDKBundle] {
4861
}
4962

5063
for variant in variants {
51-
guard variant.metadata.supportedTriples.contains(hostTriple) else {
64+
guard variant.isSupporting(hostTriple: hostTriple) else {
5265
continue
5366
}
5467

@@ -77,11 +90,7 @@ extension [SwiftSDKBundle] {
7790
for bundle in self {
7891
for (artifactID, variants) in bundle.artifacts {
7992
for variant in variants {
80-
guard variant.metadata.supportedTriples.contains(where: { variantTriple in
81-
hostTriple.isRuntimeCompatible(with: variantTriple)
82-
}) else {
83-
continue
84-
}
93+
guard variant.isSupporting(hostTriple: hostTriple) else { continue }
8594

8695
for swiftSDK in variant.swiftSDKs {
8796
if artifactID == selector {

Sources/SPMBuildCore/BinaryTarget+Extensions.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ extension BinaryTarget {
6969
// Filter supported triples with versionLessTriple and pass into
7070
// ExecutableInfo; empty if non matching triples found.
7171
try entry.value.variants.map {
72-
let filteredSupportedTriples = try $0.supportedTriples
72+
guard let supportedTriples = $0.supportedTriples else {
73+
throw StringError("No \"supportedTriples\" found in the artifact metadata for \(entry.key) in \(self.artifactPath)")
74+
}
75+
let filteredSupportedTriples = try supportedTriples
7376
.filter { try $0.withoutVersion() == versionLessTriple }
7477
return ExecutableInfo(
7578
name: entry.key,

Tests/PackageModelTests/SwiftSDKTests.swift

+61
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ private let bundleRootPath = try! AbsolutePath(validating: "/tmp/cross-toolchain
2121
private let toolchainBinDir = RelativePath("swift.xctoolchain/usr/bin")
2222
private let sdkRootDir = RelativePath("ubuntu-jammy.sdk")
2323
private let hostTriple = try! Triple("arm64-apple-darwin22.1.0")
24+
private let olderHostTriple = try! Triple("arm64-apple-darwin20.1.0")
2425
private let linuxGNUTargetTriple = try! Triple("x86_64-unknown-linux-gnu")
2526
private let linuxMuslTargetTriple = try! Triple("x86_64-unknown-linux-musl")
2627
private let extraFlags = BuildFlags(
@@ -291,6 +292,12 @@ private let parsedDestinationV2Musl = SwiftSDK(
291292
pathsConfiguration: .init(sdkRootPath: sdkRootAbsolutePath)
292293
)
293294

295+
private let parsedDestinationForOlderHost = SwiftSDK(
296+
targetTriple: linuxMuslTargetTriple,
297+
toolset: .init(toolchainBinDir: toolchainBinAbsolutePath, buildFlags: extraFlags),
298+
pathsConfiguration: .init(sdkRootPath: sdkRootAbsolutePath)
299+
)
300+
294301
private let parsedToolsetNoRootDestination = SwiftSDK(
295302
targetTriple: linuxGNUTargetTriple,
296303
toolset: .init(
@@ -520,6 +527,24 @@ final class DestinationTests: XCTestCase {
520527
swiftSDKs: [parsedDestinationV2Musl]
521528
),
522529
],
530+
"id4": [
531+
.init(
532+
metadata: .init(
533+
path: "id4",
534+
supportedTriples: [olderHostTriple]
535+
),
536+
swiftSDKs: [parsedDestinationForOlderHost]
537+
),
538+
],
539+
"id5": [
540+
.init(
541+
metadata: .init(
542+
path: "id5",
543+
supportedTriples: nil
544+
),
545+
swiftSDKs: [parsedDestinationV2GNU]
546+
),
547+
],
523548
]
524549
),
525550
]
@@ -553,5 +578,41 @@ final class DestinationTests: XCTestCase {
553578
),
554579
parsedDestinationV2Musl
555580
)
581+
582+
// Newer hostTriple should match with older supportedTriples
583+
XCTAssertEqual(
584+
bundles.selectSwiftSDK(
585+
id: "id4",
586+
hostTriple: hostTriple,
587+
targetTriple: linuxMuslTargetTriple
588+
),
589+
parsedDestinationForOlderHost
590+
)
591+
XCTAssertEqual(
592+
bundles.selectSwiftSDK(
593+
matching: "id4",
594+
hostTriple: hostTriple,
595+
observabilityScope: system.topScope
596+
),
597+
parsedDestinationForOlderHost
598+
)
599+
600+
// nil supportedTriples should match with any hostTriple
601+
XCTAssertEqual(
602+
bundles.selectSwiftSDK(
603+
id: "id5",
604+
hostTriple: hostTriple,
605+
targetTriple: linuxGNUTargetTriple
606+
),
607+
parsedDestinationV2GNU
608+
)
609+
XCTAssertEqual(
610+
bundles.selectSwiftSDK(
611+
matching: "id5",
612+
hostTriple: hostTriple,
613+
observabilityScope: system.topScope
614+
),
615+
parsedDestinationV2GNU
616+
)
556617
}
557618
}

Tests/SPMBuildCoreTests/ArtifactsArchiveMetadataTests.swift

+57
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,61 @@ final class ArtifactsArchiveMetadataTests: XCTestCase {
6565
]
6666
))
6767
}
68+
func testParseMetadataWithoutSupportedTriple() throws {
69+
let fileSystem = InMemoryFileSystem()
70+
try fileSystem.writeFileContents(
71+
"/info.json",
72+
string: """
73+
{
74+
"schemaVersion": "1.0",
75+
"artifacts": {
76+
"protocol-buffer-compiler": {
77+
"type": "executable",
78+
"version": "3.5.1",
79+
"variants": [
80+
{
81+
"path": "x86_64-apple-macosx/protoc"
82+
},
83+
{
84+
"path": "x86_64-unknown-linux-gnu/protoc",
85+
"supportedTriples": null
86+
}
87+
]
88+
}
89+
}
90+
}
91+
"""
92+
)
93+
94+
let metadata = try ArtifactsArchiveMetadata.parse(fileSystem: fileSystem, rootPath: .root)
95+
XCTAssertEqual(metadata, ArtifactsArchiveMetadata(
96+
schemaVersion: "1.0",
97+
artifacts: [
98+
"protocol-buffer-compiler": ArtifactsArchiveMetadata.Artifact(
99+
type: .executable,
100+
version: "3.5.1",
101+
variants: [
102+
ArtifactsArchiveMetadata.Variant(
103+
path: "x86_64-apple-macosx/protoc",
104+
supportedTriples: nil
105+
),
106+
ArtifactsArchiveMetadata.Variant(
107+
path: "x86_64-unknown-linux-gnu/protoc",
108+
supportedTriples: nil
109+
),
110+
]
111+
),
112+
]
113+
))
114+
115+
let binaryTarget = BinaryTarget(
116+
name: "protoc", kind: .artifactsArchive, path: .root, origin: .local
117+
)
118+
// No supportedTriples with binaryTarget should be rejected
119+
XCTAssertThrowsError(
120+
try binaryTarget.parseArtifactArchives(
121+
for: Triple("x86_64-apple-macosx"), fileSystem: fileSystem
122+
)
123+
)
124+
}
68125
}

0 commit comments

Comments
 (0)