From aa19c4c8ae65d71bb458b00e47d2127b02608818 Mon Sep 17 00:00:00 2001 From: Paul LeMarquand Date: Fri, 14 Nov 2025 14:29:14 -0500 Subject: [PATCH] Fix setting SPECIALIZATION_SDK_OPTIONS, .ARCHS The code to build up the SPECIALIZATION_SDK_OPTIONS list was appending to the existing list, but the list is not guarenteed to be initialized. If it isn't initialized, the append never happens and the setting is dropped. --- .../Package.swift | 23 ++++++++++++++++ .../Sources/Executable/main.swift | 1 + .../PackageWithSDKSpecialization.swift | 3 +++ .../SwiftBuildSupport/PackagePIFBuilder.swift | 4 +-- .../PIFBuilderTests.swift | 26 +++++++++++++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 Fixtures/PIFBuilder/PackageWithSDKSpecialization/Package.swift create mode 100644 Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/Executable/main.swift create mode 100644 Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/PackageWithSDKSpecialization/PackageWithSDKSpecialization.swift diff --git a/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Package.swift b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Package.swift new file mode 100644 index 00000000000..7388c628606 --- /dev/null +++ b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version: 6.2 + +import PackageDescription + +let package = Package( + name: "PackageWithSDKSpecialization", + platforms: [ .macOS("10.15.foo") ], + products: [ + .library( + name: "PackageWithSDKSpecialization", + targets: ["PackageWithSDKSpecialization"]), + ], + targets: [ + .target( + name: "PackageWithSDKSpecialization", + dependencies: [] + ), + .target( + name: "Executable", + dependencies: ["PackageWithSDKSpecialization"] + ), + ] +) diff --git a/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/Executable/main.swift b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/Executable/main.swift new file mode 100644 index 00000000000..f7cf60e14f9 --- /dev/null +++ b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/Executable/main.swift @@ -0,0 +1 @@ +print("Hello, world!") diff --git a/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/PackageWithSDKSpecialization/PackageWithSDKSpecialization.swift b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/PackageWithSDKSpecialization/PackageWithSDKSpecialization.swift new file mode 100644 index 00000000000..13454213039 --- /dev/null +++ b/Fixtures/PIFBuilder/PackageWithSDKSpecialization/Sources/PackageWithSDKSpecialization/PackageWithSDKSpecialization.swift @@ -0,0 +1,3 @@ +struct PackageWithSDKSpecialization { + var text = "Hello, World!" +} diff --git a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift index 75e813edf31..53c7a428be8 100644 --- a/Sources/SwiftBuildSupport/PackagePIFBuilder.swift +++ b/Sources/SwiftBuildSupport/PackagePIFBuilder.swift @@ -581,7 +581,7 @@ public final class PackagePIFBuilder { log(.warning, "Ignoring options '\(platformOptions.joined(separator: " "))' specified for unknown platform \(platform.name)") continue } - settings[.SPECIALIZATION_SDK_OPTIONS, pifPlatform]?.append(contentsOf: platformOptions) + settings[.SPECIALIZATION_SDK_OPTIONS, pifPlatform] = (settings[.SPECIALIZATION_SDK_OPTIONS, pifPlatform] ?? []) + platformOptions } let deviceFamilyIDs: Set = self.delegate.deviceFamilyIDs() @@ -607,7 +607,7 @@ public final class PackagePIFBuilder { } catch { preconditionFailure("Unhandled arm64e platform: \(error)") } - settings[.ARCHS, pifPlatform]?.append(contentsOf: ["arm64e"]) + settings[.ARCHS, pifPlatform] = (settings[.ARCHS, pifPlatform] ?? []) + ["arm64e"] } } diff --git a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift index 4404468b460..80f00260ee5 100644 --- a/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift +++ b/Tests/SwiftBuildSupportTests/PIFBuilderTests.swift @@ -118,6 +118,19 @@ extension SwiftBuildSupport.PIF.Project { throw StringError("Multiple targets named \(name) in PIF project") } } + + fileprivate func buildConfig(named name: String) throws -> SwiftBuild.ProjectModel.BuildConfig { + let matchingConfigs = underlying.buildConfigs.filter { + $0.name == name + } + if matchingConfigs.isEmpty { + throw StringError("No config named \(name) in PIF project") + } else if matchingConfigs.count > 1 { + throw StringError("Multiple configs named \(name) in PIF project") + } else { + return matchingConfigs[0] + } + } } extension SwiftBuild.ProjectModel.BaseTarget { @@ -177,6 +190,19 @@ struct PIFBuilderTests { } } + @Test func packageWithInternal() async throws { + try await withGeneratedPIF(fromFixture: "PIFBuilder/PackageWithSDKSpecialization") { pif, observabilitySystem in + let errors = observabilitySystem.diagnostics.filter { $0.severity == .error } + #expect(errors.isEmpty, "Expected no errors during PIF generation, but got: \(errors)") + + let releaseConfig = try pif.workspace + .project(named: "PackageWithSDKSpecialization") + .buildConfig(named: "Release") + + #expect(releaseConfig.settings[.SPECIALIZATION_SDK_OPTIONS, .macOS] == ["foo"]) + } + } + @Test func pluginWithBinaryTargetDependency() async throws { try await withGeneratedPIF(fromFixture: "Miscellaneous/Plugins/BinaryTargetExePlugin") { pif, observabilitySystem in // Verify that PIF generation succeeds for a package with a plugin that depends on a binary target