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
14 changes: 14 additions & 0 deletions Sources/Basics/Triple+Basics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,20 @@ extension Triple {
return ".resources"
}
}

/// Returns `true` if code compiled for `triple` can run on `self` value of ``Triple``.
public func isRuntimeCompatible(with triple: Triple) -> Bool {
if
self.arch == triple.arch &&
self.vendor == triple.vendor &&
self.os == triple.os &&
self.environment == triple.environment
{
return self.osVersion >= triple.osVersion
} else {
return false
}
}
}

extension Triple: CustomStringConvertible {
Expand Down
10 changes: 6 additions & 4 deletions Sources/PackageModel/SwiftSDKBundle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public struct SwiftSDKBundle {
guard let swiftSDKsDirectory else {
throw StringError(
"""
No directory found for installed Swift SDKs, specify one
No directory found for installed Swift SDKs, specify one \
with `--experimental-swift-sdks-path` option.
"""
)
Expand All @@ -110,8 +110,8 @@ public struct SwiftSDKBundle {
) else {
throw StringError(
"""
No Swift SDK found matching query `\(selector)` and host triple
`\(hostTriple.tripleString)`. Use `swift experimental-sdk list` command to see
No Swift SDK found matching query `\(selector)` and host triple \
`\(hostTriple.tripleString)`. Use `swift experimental-sdk list` command to see \
available Swift SDKs.
"""
)
Expand Down Expand Up @@ -429,7 +429,9 @@ extension [SwiftSDKBundle] {
for bundle in self {
for (artifactID, variants) in bundle.artifacts {
for variant in variants {
guard variant.metadata.supportedTriples.contains(hostTriple) else {
guard variant.metadata.supportedTriples.contains(where: { variantTriple in
hostTriple.isRuntimeCompatible(with: variantTriple)
}) else {
continue
}

Expand Down
7 changes: 7 additions & 0 deletions Tests/BasicsTests/TripleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,11 @@ final class TripleTests: XCTestCase {
XCTAssertTriple("x86_64-unknown-windows-msvc", matches: (.x86_64, nil, nil, .win32, .msvc, .coff))
XCTAssertTriple("wasm32-unknown-wasi", matches: (.wasm32, nil, nil, .wasi, nil, .wasm))
}

func testIsRuntimeCompatibleWith() throws {
try XCTAssertTrue(Triple("x86_64-apple-macosx").isRuntimeCompatible(with: Triple("x86_64-apple-macosx")))
try XCTAssertTrue(Triple("x86_64-unknown-linux").isRuntimeCompatible(with: Triple("x86_64-unknown-linux")))
try XCTAssertFalse(Triple("x86_64-apple-macosx").isRuntimeCompatible(with: Triple("x86_64-apple-linux")))
try XCTAssertTrue(Triple("x86_64-apple-macosx14.0").isRuntimeCompatible(with: Triple("x86_64-apple-macosx13.0")))
}
}
119 changes: 89 additions & 30 deletions Tests/PackageModelTests/SwiftSDKBundleTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//

import Basics
import PackageModel
@testable import PackageModel
import SPMTestSupport
import XCTest

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

private let testArtifactID = "test-artifact"

private func generateInfoJSON(artifacts: [MockArtifact]) -> SerializedJSON {
"""
{
"artifacts" : {
\(artifacts.map {
"""
"\($0.id)" : {
"type" : "swiftSDK",
"version" : "0.0.1",
"variants" : [
{
"path" : "\($0.id)/aarch64-unknown-linux",
"supportedTriples" : \($0.supportedTriples.map(\.tripleString))
private let targetTriple = try! Triple("aarch64-unknown-linux")

private let jsonEncoder = JSONEncoder()

private func generateBundleFiles(bundle: MockBundle) throws -> [(String, ByteString)] {
try [
(
"\(bundle.path)/info.json",
ByteString(json: """
{
"artifacts" : {
\(bundle.artifacts.map {
"""
"\($0.id)" : {
"type" : "swiftSDK",
"version" : "0.0.1",
"variants" : [
{
"path" : "\($0.id)/\(targetTriple.triple)",
"supportedTriples" : \($0.supportedTriples.map(\.tripleString))
}
]
}
]
}
"""
}.joined(separator: ",\n")
)
},
"schemaVersion" : "1.0"
"""
}.joined(separator: ",\n")
)
},
"schemaVersion" : "1.0"
}
""")
),

] + bundle.artifacts.map {
(
"\(bundle.path)/\($0.id)/\(targetTriple.tripleString)/swift-sdk.json",
ByteString(json: try generateSwiftSDKMetadata(jsonEncoder))
)
}
}

private func generateSwiftSDKMetadata(_ encoder: JSONEncoder) throws -> SerializedJSON {
try """
{
"schemaVersion": "4.0",
"targetTriples": \(
String(
bytes: encoder.encode([
targetTriple.tripleString: SwiftSDKMetadataV4.TripleProperties(sdkRootPath: "sdk")
]),
encoding: .utf8
)!
)
}
"""
}
Expand All @@ -63,15 +94,13 @@ private func generateTestFileSystem(bundleArtifacts: [MockArtifact]) throws -> (
return MockBundle(name: "test\(i).artifactbundle", path: "/\(bundleName)", artifacts: [artifacts])
}

let fileSystem = InMemoryFileSystem(
files: Dictionary(uniqueKeysWithValues: bundles.map {
(
"\($0.path)/info.json",
ByteString(
json: generateInfoJSON(artifacts: $0.artifacts)
)
)
})

let fileSystem = try InMemoryFileSystem(
files: Dictionary(
uniqueKeysWithValues: bundles.flatMap {
try generateBundleFiles(bundle: $0)
}
)
)

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

XCTAssertEqual(validBundles.count, bundles.count)
}

func testBundleSelection() async throws {
let (fileSystem, bundles, swiftSDKsDirectory) = try generateTestFileSystem(
bundleArtifacts: [
.init(id: "\(testArtifactID)1", supportedTriples: [arm64Triple]),
.init(id: "\(testArtifactID)2", supportedTriples: [i686Triple])
]
)
let system = ObservabilitySystem.makeForTesting()

for bundle in bundles {
try await SwiftSDKBundle.install(
bundlePathOrURL: bundle.path,
swiftSDKsDirectory: swiftSDKsDirectory,
fileSystem,
MockArchiver(),
system.topScope
)
}

let sdk = try SwiftSDKBundle.selectBundle(
fromBundlesAt: swiftSDKsDirectory,
fileSystem: fileSystem,
matching: "\(testArtifactID)1",
hostTriple: Triple("arm64-apple-macosx14.0"),
observabilityScope: system.topScope
)

XCTAssertEqual(sdk.targetTriple, targetTriple)
}
}