Skip to content

Commit cb587aa

Browse files
committed
[Triple] Fix Apple-OS triple version mapping for the 26-aligned releases
Rewrite `_iOSVersion` along the lines of LLVM's `getiOSVersion` for the version-26 alignment: iOS & tvOS 19 -> 26, xrOS 1/2 -> iOS 17/18, xrOS 3 -> 26, watchOS 12 -> 26. Unlike LLVM, only the last pre-jump release canonicalizes to 26; versions in the unshipped gap below 26 are left unchanged rather than bumped into the 26+ space.
1 parent f70723b commit cb587aa

2 files changed

Lines changed: 65 additions & 6 deletions

File tree

Sources/SwiftDriver/Utilities/Triple.swift

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,32 @@ extension Triple {
15731573
// MARK: - Darwin Versions
15741574

15751575
extension Triple {
1576+
// Version 26 alignment helper. Each Apple OS jumped to version 26, so the
1577+
// last pre-jump release canonicalizes to 26; versions in the unshipped gap
1578+
// below 26 are left unchanged. Only `_iOSVersion` consumes this.
1579+
1580+
/// Canonicalize the last pre-26 release to the year-aligned version 26.
1581+
/// Gap versions (between the pre-jump release and 26) pass through unchanged.
1582+
static func _canonicalVersion(_ version: Version, for os: OS) -> Version {
1583+
func isExactly(_ major: Int) -> Bool {
1584+
version.major == major && version.minor == 0 && version.micro == 0
1585+
}
1586+
switch os {
1587+
case .macosx:
1588+
if version.major == 10 && version.minor == 16 { return Version(11, 0, 0) }
1589+
if isExactly(16) { return Version(26, 0, 0) }
1590+
case .ios, .tvos:
1591+
if isExactly(19) { return Version(26, 0, 0) }
1592+
case .visionos:
1593+
if isExactly(3) { return Version(26, 0, 0) }
1594+
case .watchos:
1595+
if isExactly(12) { return Version(26, 0, 0) }
1596+
default:
1597+
break
1598+
}
1599+
return version
1600+
}
1601+
15761602
/// Parse the version number as with getOSVersion and then
15771603
/// translate generic "darwin" versions to the corresponding OS X versions.
15781604
/// This may also be called with IOS triples but the OS X version number is
@@ -1649,19 +1675,29 @@ extension Triple {
16491675
// toolchain that wants to know the iOS version number even when targeting
16501676
// OS X.
16511677
return Version(5, 0, 0)
1652-
case .ios:
1678+
case .ios, .tvos:
16531679
var version = self.osVersion
16541680
// Default to 5.0 (or 7.0 for arm64).
16551681
if version.major == 0 {
16561682
version.major = arch == .aarch64 ? 7 : 5
16571683
}
1658-
return version
1659-
case .tvos:
1660-
return osVersion
1684+
// iOS & tvOS 19 correspond to iOS 26.
1685+
if version.major == 19 {
1686+
return Version(26, 0, 0)
1687+
}
1688+
return Triple._canonicalVersion(version, for: .ios)
16611689
case .visionos:
1662-
return Version(15, 0, 0)
1690+
let version = self.osVersion
1691+
// xrOS 1/2 are aligned with iOS 17/18.
1692+
if version.major < 3 {
1693+
return Version(version.major + 16, version.minor, version.micro)
1694+
}
1695+
// visionOS 3 corresponds to iOS 26.
1696+
return Triple._canonicalVersion(version, for: .visionos)
16631697
case .watchos:
1664-
fatalError("conflicting triple info")
1698+
let version = self.osVersion
1699+
// watchOS 12 corresponds to iOS 26.
1700+
return Triple._canonicalVersion(version, for: .watchos)
16651701
default:
16661702
fatalError("unexpected OS for Darwin triple")
16671703
}

Tests/SwiftDriverTests/TripleTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,29 @@ import class TSCBasic.DiagnosticsEngine
11801180
#expect(!T.isMacCatalyst)
11811181
}
11821182

1183+
/// Mirrors LLVM `getiOSVersion` / `getCanonicalVersionForOS` version-26 alignment.
1184+
@Test func iOSVersionAlignment() {
1185+
func iOSVersion(_ triple: String) -> Triple.Version { Triple(triple)._iOSVersion }
1186+
1187+
// iOS / tvOS 19 -> iOS 26; already-aligned and pre-jump values pass through;
1188+
// a gap version (20-25) passes through unchanged.
1189+
#expect(iOSVersion("arm64-apple-ios19.0") == Triple.Version(26, 0, 0))
1190+
#expect(iOSVersion("arm64-apple-ios26.0") == Triple.Version(26, 0, 0))
1191+
#expect(iOSVersion("arm64-apple-ios18.0") == Triple.Version(18, 0, 0))
1192+
#expect(iOSVersion("arm64-apple-ios21.0") == Triple.Version(21, 0, 0))
1193+
#expect(iOSVersion("arm64-apple-tvos19.0") == Triple.Version(26, 0, 0))
1194+
1195+
// visionOS (xrOS): 1/2 align with iOS 17/18, 3 -> iOS 26.
1196+
#expect(iOSVersion("arm64-apple-xros1.0") == Triple.Version(17, 0, 0))
1197+
#expect(iOSVersion("arm64-apple-xros2.0") == Triple.Version(18, 0, 0))
1198+
#expect(iOSVersion("arm64-apple-xros3.0") == Triple.Version(26, 0, 0))
1199+
#expect(iOSVersion("arm64-apple-xros26.0") == Triple.Version(26, 0, 0))
1200+
1201+
// watchOS 12 -> iOS 26.
1202+
#expect(iOSVersion("arm64-apple-watchos12.0") == Triple.Version(26, 0, 0))
1203+
#expect(iOSVersion("arm64-apple-watchos11.0") == Triple.Version(11, 0, 0))
1204+
}
1205+
11831206
@Test func fileFormat() {
11841207
#expect(.elf == Triple("i686-unknown-linux-gnu").objectFormat)
11851208
#expect(.elf == Triple("x86_64-unknown-linux-gnu").objectFormat)

0 commit comments

Comments
 (0)