From ace1d073c488a84cc8b3d97695daa9498d63212d Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 19 Dec 2025 17:38:59 -0500 Subject: [PATCH 1/5] Don't install the SL SDK into the user account When building the release binary for swiftly it uses the static linux SDK with musl to create a system independent binary. The SDK was being installed by the build-swiftly-release tool into the user's home directory with "swift sdk install" command and it tries to uninstall it afterwards. This can pollute a user's system or remove the SDK if they installed it already. In this approach the SDK is extracted into a scratch directory and that directory is provided to the "swift build" command so that it can find it there. --- .../BuildSwiftlyRelease.swift | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift index d4c7bbe6..41deccab 100644 --- a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift +++ b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift @@ -205,12 +205,37 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { throw Error(message: "Swift release \(swiftVersion) has no Static SDK offering") } - try await sys.swift().sdk().install(.checksum(sdkPlatform.checksum ?? "deadbeef"), bundle_path_or_url: "https://download.swift.org/swift-\(swiftVersion)-release/static-sdk/swift-\(swiftVersion)-RELEASE/swift-\(swiftVersion)-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz").runEcho() + // try await sys.swift().sdk().install(.checksum(sdkPlatform.checksum ?? "deadbeef"), bundle_path_or_url: "https://download.swift.org/swift-\(swiftVersion)-release/static-sdk/swift-\(swiftVersion)-RELEASE/swift-\(swiftVersion)-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz").runEcho() + + // Download and extract SDK into the build checkouts directory + let sdkRequest = HTTPClientRequest(url: "https://download.swift.org/swift-\(swiftVersion)-release/static-sdk/swift-\(swiftVersion)-RELEASE/swift-\(swiftVersion)-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz") + let sdkResponse = try await httpExecutor.httpClient.execute(sdkRequest, timeout: .seconds(60)) + guard sdkResponse.status == .ok else { + throw Error(message: "Download failed with status: \(sdkResponse.status)") + } + + try await NIOFileSystem.FileSystem.shared.withFileHandle(forWritingAt: buildCheckoutsDir / "static-linux-sdk.tar.gz", options: .newFile(replaceExisting: true)) { fileHandle in + var pos: Int64 = 0 + + for try await buffer in sdkResponse.body { + pos += try await fileHandle.write(contentsOf: buffer, toAbsoluteOffset: pos) + } + } + + guard let sdkShaActual = try await sys.sha256sum(files: buildCheckoutsDir / "static-linux-sdk.tar.gz").output(limit: 1024) else { throw Error(message: "Unable to calculate sha256sum of static-linux-sdk.tar.gz") } + guard sdkShaActual.starts(with: sdkPlatform.checksum ?? "beefdead") else { + throw Error(message: "The static linux sdk tar.gz file sha256sum is \(sdkShaActual), but expected \(sdkPlatform.checksum)") + } + + let sdkDir = fs.mktemp() + try await fs.mkdir(atPath: sdkDir) + + try await sys.tar(.directory(sdkDir)).extract(.compressed, .archive(buildCheckoutsDir / "static-linux-sdk.tar.gz")).runEcho() var customEnv: Environment = .inherit customEnv = customEnv.updating([ "CC": "\(cwd)/Tools/build-swiftly-release/musl-clang", - "MUSL_PREFIX": "\(fs.home / ".swiftpm/swift-sdks/\(sdkName).artifactbundle/\(sdkName)/swift-linux-musl/musl-1.2.5.sdk/\(arch)/usr")", + "MUSL_PREFIX": "\(sdkDir / "\(sdkName).artifactbundle/\(sdkName)/swift-linux-musl/musl-1.2.5.sdk/\(arch)/usr")", ]) let configCmd = Configuration( @@ -254,7 +279,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { FileManager.default.changeCurrentDirectoryPath(cwd.string) - try await sys.swift().build(.swift_sdk("\(arch)-swift-linux-musl"), .product("swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .static_swift_stdlib, .configuration("release")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() let releaseDir = cwd / ".build/release" @@ -263,11 +288,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { try await self.collectLicenses(releaseDir) -#if arch(arm64) - let releaseArchive = releaseDir / "swiftly-\(version)-aarch64.tar.gz" -#else - let releaseArchive = releaseDir / "swiftly-\(version)-x86_64.tar.gz" -#endif + let releaseArchive = releaseDir / "swiftly-\(version)-\(arch).tar.gz" try await sys.tar(.directory(releaseDir)).create(.compressed, .archive(releaseArchive), files: ["swiftly", "LICENSE.txt"]).runEcho() @@ -288,7 +309,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { print(testArchive) } - try await sys.swift().sdk().remove(sdk_id_or_bundle_name: sdkName).runEcho() + try await fs.remove(atPath: sdkDir) } func buildMacOSRelease(cert: String?, identifier: String) async throws { From f3a19e0e9137f2e0c1d5cad39e302057c8c2638f Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 19 Dec 2025 17:59:09 -0500 Subject: [PATCH 2/5] Fix warnings, and fix building the test linux product --- Tools/build-swiftly-release/BuildSwiftlyRelease.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift index 41deccab..bea29b8f 100644 --- a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift +++ b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift @@ -173,7 +173,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { try await sys.tar(.directory(buildCheckoutsDir)).extract(.compressed, .archive(buildCheckoutsDir / "libarchive-\(libArchiveVersion).tar.gz")).runEcho() let cwd = fs.cwd - FileManager.default.changeCurrentDirectoryPath(libArchivePath.string) + _ = FileManager.default.changeCurrentDirectoryPath(libArchivePath.string) let swiftVerRegex: Regex<(Substring, Substring)> = try! Regex("Swift version (\\d+\\.\\d+\\.?\\d*) ") @@ -205,8 +205,6 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { throw Error(message: "Swift release \(swiftVersion) has no Static SDK offering") } - // try await sys.swift().sdk().install(.checksum(sdkPlatform.checksum ?? "deadbeef"), bundle_path_or_url: "https://download.swift.org/swift-\(swiftVersion)-release/static-sdk/swift-\(swiftVersion)-RELEASE/swift-\(swiftVersion)-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz").runEcho() - // Download and extract SDK into the build checkouts directory let sdkRequest = HTTPClientRequest(url: "https://download.swift.org/swift-\(swiftVersion)-release/static-sdk/swift-\(swiftVersion)-RELEASE/swift-\(swiftVersion)-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz") let sdkResponse = try await httpExecutor.httpClient.execute(sdkRequest, timeout: .seconds(60)) @@ -224,7 +222,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { guard let sdkShaActual = try await sys.sha256sum(files: buildCheckoutsDir / "static-linux-sdk.tar.gz").output(limit: 1024) else { throw Error(message: "Unable to calculate sha256sum of static-linux-sdk.tar.gz") } guard sdkShaActual.starts(with: sdkPlatform.checksum ?? "beefdead") else { - throw Error(message: "The static linux sdk tar.gz file sha256sum is \(sdkShaActual), but expected \(sdkPlatform.checksum)") + throw Error(message: "The static linux sdk tar.gz file sha256sum is \(sdkShaActual), but expected \(sdkPlatform.checksum ?? "none")") } let sdkDir = fs.mktemp() @@ -277,7 +275,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { try await sys.make().install().runEcho() - FileManager.default.changeCurrentDirectoryPath(cwd.string) + _ = FileManager.default.changeCurrentDirectoryPath(cwd.string) try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() @@ -303,7 +301,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { let testArchive = debugDir / "test-swiftly-linux-x86_64.tar.gz" #endif - try await sys.swift().build(.swift_sdk("\(arch)-swift-linux-musl"), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .static_swift_stdlib, .configuration("debug")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string),.swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("debug")).runEcho() try await sys.tar(.directory(debugDir)).create(.compressed, .archive(testArchive), files: ["test-swiftly"]).runEcho() print(testArchive) From 9e77e24a84b8d4faa31e68f6ebc49754ce7f9713 Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 19 Dec 2025 18:06:33 -0500 Subject: [PATCH 3/5] Formatting fix --- Tools/build-swiftly-release/BuildSwiftlyRelease.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift index bea29b8f..51d15e39 100644 --- a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift +++ b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift @@ -301,7 +301,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { let testArchive = debugDir / "test-swiftly-linux-x86_64.tar.gz" #endif - try await sys.swift().build(.swift_sdks_path(sdkDir.string),.swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("debug")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("debug")).runEcho() try await sys.tar(.directory(debugDir)).create(.compressed, .archive(testArchive), files: ["test-swiftly"]).runEcho() print(testArchive) From 8cb4764bb37e3be289eae6aaab34cf29a6e8c6fa Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 19 Dec 2025 18:16:44 -0500 Subject: [PATCH 4/5] Force the test swiftly into release mode to resolve compilation error --- Tools/build-swiftly-release/BuildSwiftlyRelease.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift index 51d15e39..41496c05 100644 --- a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift +++ b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift @@ -295,13 +295,9 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { if self.test { let debugDir = cwd / ".build/debug" -#if arch(arm64) - let testArchive = debugDir / "test-swiftly-linux-aarch64.tar.gz" -#else - let testArchive = debugDir / "test-swiftly-linux-x86_64.tar.gz" -#endif + let testArchive = debugDir / "test-swiftly-linux-\(arch).tar.gz" - try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("debug")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() try await sys.tar(.directory(debugDir)).create(.compressed, .archive(testArchive), files: ["test-swiftly"]).runEcho() print(testArchive) From 621db960798253da6eeec67de9c6283fbbe42d6e Mon Sep 17 00:00:00 2001 From: Chris McGee Date: Fri, 19 Dec 2025 18:52:08 -0500 Subject: [PATCH 5/5] Restore swift sdk selection by triple instead of id --- Tools/build-swiftly-release/BuildSwiftlyRelease.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift index 41496c05..219cf71f 100644 --- a/Tools/build-swiftly-release/BuildSwiftlyRelease.swift +++ b/Tools/build-swiftly-release/BuildSwiftlyRelease.swift @@ -277,7 +277,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { _ = FileManager.default.changeCurrentDirectoryPath(cwd.string) - try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("\(arch)-swift-linux-musl"), .arch(arch), .product("swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() let releaseDir = cwd / ".build/release" @@ -297,7 +297,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand { let testArchive = debugDir / "test-swiftly-linux-\(arch).tar.gz" - try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("swift-\(swiftVersion)-RELEASE_static-linux-0.0.1"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("release")).runEcho() + try await sys.swift().build(.swift_sdks_path(sdkDir.string), .swift_sdk("\(arch)-swift-linux-musl"), .arch(arch), .product("test-swiftly"), .pkg_config_path(pkgConfigPath / "lib/pkgconfig"), .configuration("debug")).runEcho() try await sys.tar(.directory(debugDir)).create(.compressed, .archive(testArchive), files: ["test-swiftly"]).runEcho() print(testArchive)