Skip to content

Commit b0ca843

Browse files
committed
Fix some correctness issues in target triple validation and improve test coverage
Fixes "off by one" type error in watchOS validation - 32-bit archs should be blocked for watchOS >= 9.0, not >= 8.7. Fixes an incorrect fallthrough where invalid tvOS archs would issue errors about 32-bit iOS archs not being supported on iOS 11 and later. Fixes labeling of "macOS" as "OS X" in an error. Fixes an issue where arm64_32 would incorrectly be blocked for watchOS >= 8.7. Generally simplifies the validation code. Improves the test coverage to cover all of these scenarios.
1 parent 86d081f commit b0ca843

File tree

3 files changed

+127
-51
lines changed

3 files changed

+127
-51
lines changed

Sources/SwiftDriver/Toolchains/DarwinToolchain.swift

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,18 @@ public final class DarwinToolchain: Toolchain {
154154
}
155155

156156
public enum ToolchainValidationError: Error, DiagnosticData {
157-
case osVersionBelowMinimumDeploymentTarget(String)
157+
case osVersionBelowMinimumDeploymentTarget(platform: DarwinPlatform, version: Triple.Version)
158158
case argumentNotSupported(String)
159-
case invalidDeploymentTargetForIR(String, String)
159+
case invalidDeploymentTargetForIR(platform: DarwinPlatform, version: Triple.Version, archName: String)
160160
case unsupportedTargetVariant(variant: Triple)
161161
case darwinOnlySupportsLibCxx
162162

163163
public var description: String {
164164
switch self {
165-
case .osVersionBelowMinimumDeploymentTarget(let target):
166-
return "Swift requires a minimum deployment target of \(target)"
167-
case .invalidDeploymentTargetForIR(let target, let archName):
168-
return
169-
"\(target) and above does not support emitting binaries or IR for \(archName)"
165+
case .osVersionBelowMinimumDeploymentTarget(let platform, let version):
166+
return "Swift requires a minimum deployment target of \(platform.platformDisplayName) \(version.description)"
167+
case .invalidDeploymentTargetForIR(let platform, let version, let archName):
168+
return "\(platform.platformDisplayName) \(version.description) and above does not support emitting binaries or IR for \(archName)"
170169
case .unsupportedTargetVariant(variant: let variant):
171170
return "unsupported '\(variant.isiOS ? "-target-variant" : "-target")' value '\(variant.triple)'; use 'ios-macabi' instead"
172171
case .argumentNotSupported(let argument):
@@ -215,36 +214,29 @@ public final class DarwinToolchain: Toolchain {
215214

216215
func validateDeploymentTarget(_ parsedOptions: inout ParsedOptions,
217216
targetTriple: Triple, compilerOutputType: FileType?) throws {
218-
// Check minimum supported OS versions.
219-
if targetTriple.isMacOSX,
220-
targetTriple.version(for: .macOS) < Triple.Version(10, 9, 0) {
221-
throw ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("OS X 10.9")
217+
guard let os = targetTriple.os else {
218+
return
222219
}
223-
// tvOS triples are also iOS, so check it first.
224-
else if targetTriple.isTvOS,
225-
targetTriple.version(for: .tvOS(.device)) < Triple.Version(9, 0, 0) {
226-
throw ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("tvOS 9.0")
227-
} else if targetTriple.isiOS {
228-
if targetTriple.version(for: .iOS(.device)) < Triple.Version(7, 0, 0) {
229-
throw ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("iOS 7")
230-
}
231-
if targetTriple.arch?.is32Bit == true,
232-
targetTriple.version(for: .iOS(.device)) >= Triple.Version(11, 0, 0),
233-
compilerOutputType != .swiftModule {
234-
throw
235-
ToolchainValidationError
236-
.invalidDeploymentTargetForIR("iOS 11", targetTriple.archName)
237-
}
238-
} else if targetTriple.isWatchOS {
239-
if targetTriple.version(for: .watchOS(.device)) < Triple.Version(2, 0, 0) {
240-
throw ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("watchOS 2.0")
241-
}
242-
if targetTriple.arch?.is32Bit == true,
243-
targetTriple.version(for: .watchOS(.device)) >= Triple.Version(8, 7, 0),
244-
compilerOutputType != .swiftModule {
245-
throw
246-
ToolchainValidationError
247-
.invalidDeploymentTargetForIR("watchOS 8.7", targetTriple.archName)
220+
221+
// Check minimum supported OS versions. Note that Mac Catalyst falls into the iOS device case. The driver automatically uplevels the deployment target to iOS >= 13.1.
222+
let minVersions: [Triple.OS: (DarwinPlatform, Triple.Version)] = [
223+
.macosx: (.macOS, Triple.Version(10, 9, 0)),
224+
.ios: (.iOS(targetTriple._isSimulatorEnvironment ? .simulator : .device), Triple.Version(7, 0, 0)),
225+
.tvos: (.tvOS(targetTriple._isSimulatorEnvironment ? .simulator : .device), Triple.Version(9, 0, 0)),
226+
.watchos: (.watchOS(targetTriple._isSimulatorEnvironment ? .simulator : .device), Triple.Version(2, 0, 0))
227+
]
228+
if let (platform, minVersion) = minVersions[os], targetTriple.version(for: platform) < minVersion {
229+
throw ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: platform, version: minVersion)
230+
}
231+
232+
// Check 32-bit deprecation. Exclude watchOS's arm64_32, which is 32-bit but not deprecated.
233+
if targetTriple.arch?.is32Bit == true && compilerOutputType != .swiftModule && targetTriple.arch != .aarch64_32 {
234+
let minVersions: [Triple.OS: (DarwinPlatform, Triple.Version)] = [
235+
.ios: (.iOS(targetTriple._isSimulatorEnvironment ? .simulator : .device), Triple.Version(11, 0, 0)),
236+
.watchos: (.watchOS(targetTriple._isSimulatorEnvironment ? .simulator : .device), targetTriple._isSimulatorEnvironment ? Triple.Version(7, 0, 0) : Triple.Version(9, 0, 0)),
237+
]
238+
if let (platform, minVersion) = minVersions[os], targetTriple.version(for: platform) >= minVersion {
239+
throw ToolchainValidationError.invalidDeploymentTargetForIR(platform: platform, version: minVersion, archName: targetTriple.archName)
248240
}
249241
}
250242
}

Sources/SwiftDriver/Utilities/Triple+Platforms.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,27 @@ public enum DarwinPlatform: Hashable {
7979
}
8080
}
8181

82+
public var platformDisplayName: String {
83+
switch self {
84+
case .macOS:
85+
return "macOS"
86+
case .iOS(.device):
87+
return "iOS"
88+
case .iOS(.simulator):
89+
return "iOS Simulator"
90+
case .iOS(.catalyst):
91+
return "Mac Catalyst"
92+
case .tvOS(.device):
93+
return "tvOS"
94+
case .tvOS(.simulator):
95+
return "tvOS Simulator"
96+
case .watchOS(.device):
97+
return "watchOS"
98+
case .watchOS(.simulator):
99+
return "watchOS Simulator"
100+
}
101+
}
102+
82103
/// The platform name, i.e. the name clang uses to identify this platform in its
83104
/// resource directory.
84105
public var platformName: String {

Tests/SwiftDriverTests/SwiftDriverTests.swift

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3460,42 +3460,98 @@ final class SwiftDriverTests: XCTestCase {
34603460
}
34613461

34623462
func testDarwinToolchainArgumentValidation() throws {
3463-
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-ios6.0",
3463+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "arm64-apple-ios6.0",
34643464
"foo.swift"])) { error in
3465-
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("iOS 7") = error else {
3466-
XCTFail()
3465+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .iOS(.device), version: Triple.Version(7, 0, 0)) = error else {
3466+
XCTFail("Unexpected error: \(error)")
3467+
return
3468+
}
3469+
}
3470+
3471+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-ios6.0-simulator",
3472+
"foo.swift"])) { error in
3473+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .iOS(.simulator), version: Triple.Version(7, 0, 0)) = error else {
3474+
XCTFail("Unexpected error: \(error)")
3475+
return
3476+
}
3477+
}
3478+
3479+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "arm64-apple-tvos6.0",
3480+
"foo.swift"])) { error in
3481+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .tvOS(.device), version: Triple.Version(9, 0, 0)) = error else {
3482+
XCTFail("Unexpected error: \(error)")
3483+
return
3484+
}
3485+
}
3486+
3487+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-tvos6.0-simulator",
3488+
"foo.swift"])) { error in
3489+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .tvOS(.simulator), version: Triple.Version(9, 0, 0)) = error else {
3490+
XCTFail("Unexpected error: \(error)")
3491+
return
3492+
}
3493+
}
3494+
3495+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "arm64-apple-watchos1.0",
3496+
"foo.swift"])) { error in
3497+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .watchOS(.device), version: Triple.Version(2, 0, 0)) = error else {
3498+
XCTFail("Unexpected error: \(error)")
3499+
return
3500+
}
3501+
}
3502+
3503+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-watchos1.0-simulator",
3504+
"foo.swift"])) { error in
3505+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .watchOS(.simulator), version: Triple.Version(2, 0, 0)) = error else {
3506+
XCTFail("Unexpected error: \(error)")
34673507
return
34683508
}
34693509
}
34703510

34713511
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-macosx10.4",
34723512
"foo.swift"])) { error in
3473-
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget("OS X 10.9") = error else {
3474-
XCTFail()
3513+
guard case DarwinToolchain.ToolchainValidationError.osVersionBelowMinimumDeploymentTarget(platform: .macOS, version: Triple.Version(10, 9, 0)) = error else {
3514+
XCTFail("Unexpected error: \(error)")
34753515
return
34763516
}
34773517
}
34783518

34793519
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "armv7-apple-ios12.1",
34803520
"foo.swift"])) { error in
3481-
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR("iOS 11", "armv7") = error else {
3482-
XCTFail()
3521+
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR(platform: .iOS(.device), version: Triple.Version(11, 0, 0), archName: "armv7") = error else {
3522+
XCTFail("Unexpected error: \(error)")
34833523
return
34843524
}
34853525
}
34863526

34873527
XCTAssertThrowsError(try Driver(args: ["swiftc", "-emit-module", "-c", "-target",
34883528
"armv7s-apple-ios12.0", "foo.swift"])) { error in
3489-
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR("iOS 11", "armv7s") = error else {
3490-
XCTFail()
3529+
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR(platform: .iOS(.device), version: Triple.Version(11, 0, 0), archName: "armv7s") = error else {
3530+
XCTFail("Unexpected error: \(error)")
3531+
return
3532+
}
3533+
}
3534+
3535+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-emit-module", "-c", "-target",
3536+
"i386-apple-ios12.0-simulator", "foo.swift"])) { error in
3537+
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR(platform: .iOS(.simulator), version: Triple.Version(11, 0, 0), archName: "i386") = error else {
3538+
XCTFail("Unexpected error: \(error)")
34913539
return
34923540
}
34933541
}
34943542

34953543
XCTAssertThrowsError(try Driver(args: ["swiftc", "-emit-module", "-c", "-target",
34963544
"armv7k-apple-watchos12.0", "foo.swift"])) { error in
3497-
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR("watchOS 8.7", "armv7k") = error else {
3498-
XCTFail()
3545+
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR(platform: .watchOS(.device), version: Triple.Version(9, 0, 0), archName: "armv7k") = error else {
3546+
XCTFail("Unexpected error: \(error)")
3547+
return
3548+
}
3549+
}
3550+
3551+
XCTAssertThrowsError(try Driver(args: ["swiftc", "-emit-module", "-c", "-target",
3552+
"i386-apple-watchos12.0", "foo.swift"])) { error in
3553+
guard case DarwinToolchain.ToolchainValidationError.invalidDeploymentTargetForIR(platform: .watchOS(.simulator), version: Triple.Version(7, 0, 0), archName: "i386") = error else {
3554+
XCTFail("Unexpected error: \(error)")
34993555
return
35003556
}
35013557
}
@@ -3504,34 +3560,41 @@ final class SwiftDriverTests: XCTestCase {
35043560
"-target-variant", "x86_64-apple-macosx10.14",
35053561
"foo.swift"])) { error in
35063562
guard case DarwinToolchain.ToolchainValidationError.unsupportedTargetVariant(variant: _) = error else {
3507-
XCTFail()
3563+
XCTFail("Unexpected error: \(error)")
35083564
return
35093565
}
35103566
}
35113567

35123568
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-static-stdlib", "-target", "x86_64-apple-macosx10.14",
35133569
"foo.swift"])) { error in
35143570
guard case DarwinToolchain.ToolchainValidationError.argumentNotSupported("-static-stdlib") = error else {
3515-
XCTFail()
3571+
XCTFail("Unexpected error: \(error)")
35163572
return
35173573
}
35183574
}
35193575

35203576
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-static-executable", "-target", "x86_64-apple-macosx10.14",
35213577
"foo.swift"])) { error in
35223578
guard case DarwinToolchain.ToolchainValidationError.argumentNotSupported("-static-executable") = error else {
3523-
XCTFail()
3579+
XCTFail("Unexpected error: \(error)")
35243580
return
35253581
}
35263582
}
35273583

35283584
XCTAssertThrowsError(try Driver(args: ["swiftc", "-c", "-target", "x86_64-apple-macosx10.14", "-experimental-cxx-stdlib", "libstdc++",
35293585
"foo.swift"])) { error in
35303586
guard case DarwinToolchain.ToolchainValidationError.darwinOnlySupportsLibCxx = error else {
3531-
XCTFail()
3587+
XCTFail("Unexpected error: \(error)")
35323588
return
35333589
}
35343590
}
3591+
3592+
// Not actually a valid arch for tvOS, but we shouldn't fall into the iOS case by mistake and emit a message about iOS >= 11 not supporting armv7.
3593+
XCTAssertNoThrow(try Driver(args: ["swiftc", "-c", "-target", "armv7-apple-tvos9.0", "foo.swift"]))
3594+
3595+
// Ensure arm64_32 is not restricted to back-deployment like other 32-bit archs (armv7k/i386).
3596+
XCTAssertNoThrow(try Driver(args: ["swiftc", "-emit-module", "-c", "-target", "arm64_32-apple-watchos12.0", "foo.swift"]))
3597+
35353598
// On non-darwin hosts, libArcLite won't be found and a warning will be emitted
35363599
#if os(macOS)
35373600
try assertNoDriverDiagnostics(args: "swiftc", "-c", "-target", "x86_64-apple-macosx10.14", "-link-objc-runtime", "foo.swift")

0 commit comments

Comments
 (0)