Skip to content

Commit 074f51d

Browse files
authored
Fix backward compatibility in host triple checks (#6819)
When setting host triple in Swift SDKs to `arm64-apple-macosx13.0` to allow cross-compiling from an older version of macOS, this triple is not recognized as directly matching `arm64-apple-macosx14.0` on a newer version of macOS. We should support backward compatibility with Swift SDKs that were built for older version of macOS. Resolves rdar://113967401.
1 parent 6ba5b96 commit 074f51d

File tree

4 files changed

+116
-34
lines changed

4 files changed

+116
-34
lines changed

Sources/Basics/Triple+Basics.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,20 @@ extension Triple {
183183
return ".resources"
184184
}
185185
}
186+
187+
/// Returns `true` if code compiled for `triple` can run on `self` value of ``Triple``.
188+
public func isRuntimeCompatible(with triple: Triple) -> Bool {
189+
if
190+
self.arch == triple.arch &&
191+
self.vendor == triple.vendor &&
192+
self.os == triple.os &&
193+
self.environment == triple.environment
194+
{
195+
return self.osVersion >= triple.osVersion
196+
} else {
197+
return false
198+
}
199+
}
186200
}
187201

188202
extension Triple: CustomStringConvertible {

Sources/PackageModel/SwiftSDKBundle.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public struct SwiftSDKBundle {
8585
guard let swiftSDKsDirectory else {
8686
throw StringError(
8787
"""
88-
No directory found for installed Swift SDKs, specify one
88+
No directory found for installed Swift SDKs, specify one \
8989
with `--experimental-swift-sdks-path` option.
9090
"""
9191
)
@@ -110,8 +110,8 @@ public struct SwiftSDKBundle {
110110
) else {
111111
throw StringError(
112112
"""
113-
No Swift SDK found matching query `\(selector)` and host triple
114-
`\(hostTriple.tripleString)`. Use `swift experimental-sdk list` command to see
113+
No Swift SDK found matching query `\(selector)` and host triple \
114+
`\(hostTriple.tripleString)`. Use `swift experimental-sdk list` command to see \
115115
available Swift SDKs.
116116
"""
117117
)
@@ -429,7 +429,9 @@ extension [SwiftSDKBundle] {
429429
for bundle in self {
430430
for (artifactID, variants) in bundle.artifacts {
431431
for variant in variants {
432-
guard variant.metadata.supportedTriples.contains(hostTriple) else {
432+
guard variant.metadata.supportedTriples.contains(where: { variantTriple in
433+
hostTriple.isRuntimeCompatible(with: variantTriple)
434+
}) else {
433435
continue
434436
}
435437

Tests/BasicsTests/TripleTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,11 @@ final class TripleTests: XCTestCase {
165165
XCTAssertTriple("x86_64-unknown-windows-msvc", matches: (.x86_64, nil, nil, .win32, .msvc, .coff))
166166
XCTAssertTriple("wasm32-unknown-wasi", matches: (.wasm32, nil, nil, .wasi, nil, .wasm))
167167
}
168+
169+
func testIsRuntimeCompatibleWith() throws {
170+
try XCTAssertTrue(Triple("x86_64-apple-macosx").isRuntimeCompatible(with: Triple("x86_64-apple-macosx")))
171+
try XCTAssertTrue(Triple("x86_64-unknown-linux").isRuntimeCompatible(with: Triple("x86_64-unknown-linux")))
172+
try XCTAssertFalse(Triple("x86_64-apple-macosx").isRuntimeCompatible(with: Triple("x86_64-apple-linux")))
173+
try XCTAssertTrue(Triple("x86_64-apple-macosx14.0").isRuntimeCompatible(with: Triple("x86_64-apple-macosx13.0")))
174+
}
168175
}

Tests/PackageModelTests/SwiftSDKBundleTests.swift

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import Basics
14-
import PackageModel
14+
@testable import PackageModel
1515
import SPMTestSupport
1616
import XCTest
1717

@@ -21,27 +21,58 @@ import class TSCBasic.InMemoryFileSystem
2121

2222
private let testArtifactID = "test-artifact"
2323

24-
private func generateInfoJSON(artifacts: [MockArtifact]) -> SerializedJSON {
25-
"""
26-
{
27-
"artifacts" : {
28-
\(artifacts.map {
29-
"""
30-
"\($0.id)" : {
31-
"type" : "swiftSDK",
32-
"version" : "0.0.1",
33-
"variants" : [
34-
{
35-
"path" : "\($0.id)/aarch64-unknown-linux",
36-
"supportedTriples" : \($0.supportedTriples.map(\.tripleString))
24+
private let targetTriple = try! Triple("aarch64-unknown-linux")
25+
26+
private let jsonEncoder = JSONEncoder()
27+
28+
private func generateBundleFiles(bundle: MockBundle) throws -> [(String, ByteString)] {
29+
try [
30+
(
31+
"\(bundle.path)/info.json",
32+
ByteString(json: """
33+
{
34+
"artifacts" : {
35+
\(bundle.artifacts.map {
36+
"""
37+
"\($0.id)" : {
38+
"type" : "swiftSDK",
39+
"version" : "0.0.1",
40+
"variants" : [
41+
{
42+
"path" : "\($0.id)/\(targetTriple.triple)",
43+
"supportedTriples" : \($0.supportedTriples.map(\.tripleString))
44+
}
45+
]
3746
}
38-
]
39-
}
40-
"""
41-
}.joined(separator: ",\n")
42-
)
43-
},
44-
"schemaVersion" : "1.0"
47+
"""
48+
}.joined(separator: ",\n")
49+
)
50+
},
51+
"schemaVersion" : "1.0"
52+
}
53+
""")
54+
),
55+
56+
] + bundle.artifacts.map {
57+
(
58+
"\(bundle.path)/\($0.id)/\(targetTriple.tripleString)/swift-sdk.json",
59+
ByteString(json: try generateSwiftSDKMetadata(jsonEncoder))
60+
)
61+
}
62+
}
63+
64+
private func generateSwiftSDKMetadata(_ encoder: JSONEncoder) throws -> SerializedJSON {
65+
try """
66+
{
67+
"schemaVersion": "4.0",
68+
"targetTriples": \(
69+
String(
70+
bytes: encoder.encode([
71+
targetTriple.tripleString: SwiftSDKMetadataV4.TripleProperties(sdkRootPath: "sdk")
72+
]),
73+
encoding: .utf8
74+
)!
75+
)
4576
}
4677
"""
4778
}
@@ -63,15 +94,13 @@ private func generateTestFileSystem(bundleArtifacts: [MockArtifact]) throws -> (
6394
return MockBundle(name: "test\(i).artifactbundle", path: "/\(bundleName)", artifacts: [artifacts])
6495
}
6596

66-
let fileSystem = InMemoryFileSystem(
67-
files: Dictionary(uniqueKeysWithValues: bundles.map {
68-
(
69-
"\($0.path)/info.json",
70-
ByteString(
71-
json: generateInfoJSON(artifacts: $0.artifacts)
72-
)
73-
)
74-
})
97+
98+
let fileSystem = try InMemoryFileSystem(
99+
files: Dictionary(
100+
uniqueKeysWithValues: bundles.flatMap {
101+
try generateBundleFiles(bundle: $0)
102+
}
103+
)
75104
)
76105

77106
let swiftSDKsDirectory = try AbsolutePath(validating: "/sdks")
@@ -208,4 +237,34 @@ final class SwiftSDKBundleTests: XCTestCase {
208237

209238
XCTAssertEqual(validBundles.count, bundles.count)
210239
}
240+
241+
func testBundleSelection() async throws {
242+
let (fileSystem, bundles, swiftSDKsDirectory) = try generateTestFileSystem(
243+
bundleArtifacts: [
244+
.init(id: "\(testArtifactID)1", supportedTriples: [arm64Triple]),
245+
.init(id: "\(testArtifactID)2", supportedTriples: [i686Triple])
246+
]
247+
)
248+
let system = ObservabilitySystem.makeForTesting()
249+
250+
for bundle in bundles {
251+
try await SwiftSDKBundle.install(
252+
bundlePathOrURL: bundle.path,
253+
swiftSDKsDirectory: swiftSDKsDirectory,
254+
fileSystem,
255+
MockArchiver(),
256+
system.topScope
257+
)
258+
}
259+
260+
let sdk = try SwiftSDKBundle.selectBundle(
261+
fromBundlesAt: swiftSDKsDirectory,
262+
fileSystem: fileSystem,
263+
matching: "\(testArtifactID)1",
264+
hostTriple: Triple("arm64-apple-macosx14.0"),
265+
observabilityScope: system.topScope
266+
)
267+
268+
XCTAssertEqual(sdk.targetTriple, targetTriple)
269+
}
211270
}

0 commit comments

Comments
 (0)