@@ -29,16 +29,6 @@ extension Runnable {
2929 }
3030}
3131
32- public struct SwiftPlatform : Codable {
33- public var name : String ?
34- public var checksum : String ?
35- }
36-
37- public struct SwiftRelease : Codable {
38- public var name : String ?
39- public var platforms : [ SwiftPlatform ] ?
40- }
41-
4232// These functions are cloned and adapted from SwiftlyCore until we can do better bootstrapping
4333public struct Error : LocalizedError , CustomStringConvertible {
4434 public let message : String
@@ -51,93 +41,6 @@ public struct Error: LocalizedError, CustomStringConvertible {
5141 public var description : String { self . message }
5242}
5343
54- public func runProgramEnv( _ args: String ... , quiet: Bool = false , env: [ String : String ] ? ) throws {
55- if !quiet { print ( " \( args. joined ( separator: " " ) ) " ) }
56-
57- let process = Process ( )
58- process. executableURL = URL ( fileURLWithPath: " /usr/bin/env " )
59- process. arguments = args
60-
61- if let env = env {
62- process. environment = env
63- }
64-
65- if quiet {
66- process. standardOutput = nil
67- process. standardError = nil
68- }
69-
70- try process. run ( )
71- // Attach this process to our process group so that Ctrl-C and other signals work
72- let pgid = tcgetpgrp ( STDOUT_FILENO)
73- if pgid != - 1 {
74- tcsetpgrp ( STDOUT_FILENO, process. processIdentifier)
75- }
76- process. waitUntilExit ( )
77-
78- guard process. terminationStatus == 0 else {
79- throw Error ( message: " \( args. first!) exited with non-zero status: \( process. terminationStatus) " )
80- }
81- }
82-
83- public func runProgram( _ args: String ... , quiet: Bool = false ) throws {
84- if !quiet { print ( " \( args. joined ( separator: " " ) ) " ) }
85-
86- let process = Process ( )
87- process. executableURL = URL ( fileURLWithPath: " /usr/bin/env " )
88- process. arguments = args
89-
90- if quiet {
91- process. standardOutput = nil
92- process. standardError = nil
93- }
94-
95- try process. run ( )
96- // Attach this process to our process group so that Ctrl-C and other signals work
97- let pgid = tcgetpgrp ( STDOUT_FILENO)
98- if pgid != - 1 {
99- tcsetpgrp ( STDOUT_FILENO, process. processIdentifier)
100- }
101- process. waitUntilExit ( )
102-
103- guard process. terminationStatus == 0 else {
104- throw Error ( message: " \( args. first!) exited with non-zero status: \( process. terminationStatus) " )
105- }
106- }
107-
108- public func runProgramOutput( _ program: String , _ args: String ... ) async throws -> String ? {
109- print ( " \( program) \( args. joined ( separator: " " ) ) " )
110-
111- let process = Process ( )
112- process. executableURL = URL ( fileURLWithPath: " /usr/bin/env " )
113- process. arguments = [ program] + args
114-
115- let outPipe = Pipe ( )
116- process. standardInput = FileHandle . nullDevice
117- process. standardOutput = outPipe
118-
119- try process. run ( )
120- // Attach this process to our process group so that Ctrl-C and other signals work
121- let pgid = tcgetpgrp ( STDOUT_FILENO)
122- if pgid != - 1 {
123- tcsetpgrp ( STDOUT_FILENO, process. processIdentifier)
124- }
125- let outData = try outPipe. fileHandleForReading. readToEnd ( )
126-
127- process. waitUntilExit ( )
128-
129- guard process. terminationStatus == 0 else {
130- print ( " \( args. first!) exited with non-zero status: \( process. terminationStatus) " )
131- throw Error ( message: " \( args. first!) exited with non-zero status: \( process. terminationStatus) " )
132- }
133-
134- if let outData {
135- return String ( data: outData, encoding: . utf8)
136- } else {
137- return nil
138- }
139- }
140-
14144@main
14245struct BuildSwiftlyRelease : AsyncParsableCommand {
14346 static let configuration = CommandConfiguration (
@@ -178,11 +81,11 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
17881 }
17982
18083 func assertTool( _ name: String , message: String ) async throws -> String {
181- guard let _ = try ? await runProgramOutput ( currentPlatform. getShell ( ) , " -c " , " which which " ) else {
84+ guard let _ = try ? await currentPlatform . runProgramOutput ( currentPlatform. getShell ( ) , " -c " , " which which " ) else {
18285 throw Error ( message: " The which command could not be found. Please install it with your package manager. " )
18386 }
18487
185- guard let location = try ? await runProgramOutput ( currentPlatform. getShell ( ) , " -c " , " which \( name) " ) else {
88+ guard let location = try ? await currentPlatform . runProgramOutput ( currentPlatform. getShell ( ) , " -c " , " which \( name) " ) else {
18689 throw Error ( message: message)
18790 }
18891
@@ -229,7 +132,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
229132 let swift = try await self . assertTool ( " swift " , message: " Please install swift \( requiredSwiftVersion) and make sure that it is added to your path. " )
230133
231134 // We also need a swift toolchain with the correct version
232- guard let swiftVersion = try await runProgramOutput ( swift, " --version " ) , swiftVersion. contains ( " Swift version \( requiredSwiftVersion) " ) else {
135+ guard let swiftVersion = try await currentPlatform . runProgramOutput ( swift, " --version " ) , swiftVersion. contains ( " Swift version \( requiredSwiftVersion) " ) else {
233136 throw Error ( message: " Swiftly releases require a Swift \( requiredSwiftVersion) toolchain available on the path " )
234137 }
235138
@@ -275,7 +178,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
275178 try await self . checkGitRepoStatus ( git)
276179
277180 // Start with a fresh SwiftPM package
278- try runProgram ( swift, " package " , " reset " )
181+ try currentPlatform . runProgram ( swift, " package " , " reset " )
279182
280183 // Build a specific version of libarchive with a check on the tarball's SHA256
281184 let libArchiveVersion = " 3.7.9 "
@@ -289,26 +192,31 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
289192 try ? FileManager . default. createDirectory ( atPath: pkgConfigPath, withIntermediateDirectories: true )
290193
291194 try ? FileManager . default. removeItem ( atPath: libArchivePath)
292- try runProgram ( curl, " -L " , " -o " , " \( buildCheckoutsDir + " /libarchive- \( libArchiveVersion) .tar.gz " ) " , " --remote-name " , " --location " , " https://github.com/libarchive/libarchive/releases/download/v \( libArchiveVersion) /libarchive- \( libArchiveVersion) .tar.gz " )
293- let libArchiveTarShaActual = try await runProgramOutput ( sha256sum, " \( buildCheckoutsDir) /libarchive- \( libArchiveVersion) .tar.gz " )
195+ try currentPlatform . runProgram ( curl, " -L " , " -o " , " \( buildCheckoutsDir + " /libarchive- \( libArchiveVersion) .tar.gz " ) " , " --remote-name " , " --location " , " https://github.com/libarchive/libarchive/releases/download/v \( libArchiveVersion) /libarchive- \( libArchiveVersion) .tar.gz " )
196+ let libArchiveTarShaActual = try await currentPlatform . runProgramOutput ( sha256sum, " \( buildCheckoutsDir) /libarchive- \( libArchiveVersion) .tar.gz " )
294197 guard let libArchiveTarShaActual, libArchiveTarShaActual. starts ( with: libArchiveTarSha) else {
295198 let shaActual = libArchiveTarShaActual ?? " none "
296199 throw Error ( message: " The libarchive tar.gz file sha256sum is \( shaActual) , but expected \( libArchiveTarSha) " )
297200 }
298- try runProgram ( tar, " --directory= \( buildCheckoutsDir) " , " -xzf " , " \( buildCheckoutsDir) /libarchive- \( libArchiveVersion) .tar.gz " )
201+ try currentPlatform . runProgram ( tar, " --directory= \( buildCheckoutsDir) " , " -xzf " , " \( buildCheckoutsDir) /libarchive- \( libArchiveVersion) .tar.gz " )
299202
300203 let cwd = FileManager . default. currentDirectoryPath
301204 FileManager . default. changeCurrentDirectoryPath ( libArchivePath)
302205
303206 let swiftVerRegex : Regex < ( Substring , Substring ) > = try ! Regex ( " Swift version ( \\ d+ \\ . \\ d+ \\ .? \\ d*) " )
304207
305- let swiftVerOutput = ( try await runProgramOutput ( swift, " --version " ) ) ?? " "
208+ let swiftVerOutput = ( try await currentPlatform . runProgramOutput ( swift, " --version " ) ) ?? " "
306209 guard let swiftVerMatch = try swiftVerRegex. firstMatch ( in: swiftVerOutput) else {
307210 throw Error ( message: " Unable to detect swift version " )
308211 }
309212
310213 let swiftVersion = swiftVerMatch. output. 1
311214
215+ let httpExecutor = HTTPRequestExecutorImpl ( )
216+ guard let swiftRelease = ( try await httpExecutor. getReleaseToolchains ( ) ) . first ( where: { $0. name == swiftVersion } ) else {
217+ throw Error ( message: " Unable to find swift release using swift.org API: \( swiftVersion) " )
218+ }
219+
312220 let sdkName = " swift- \( swiftVersion) -RELEASE_static-linux-0.0.1 "
313221
314222#if arch(arm64)
@@ -317,24 +225,17 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
317225 let arch = " x86_64 "
318226#endif
319227
320- let swiftReleasesJson = ( try await runProgramOutput ( curl, " https://www.swift.org/api/v1/install/releases.json " ) ) ?? " [] "
321- let swiftReleases = try JSONDecoder ( ) . decode ( [ SwiftRelease ] . self, from: swiftReleasesJson. data ( using: . utf8) !)
322-
323- guard let swiftRelease = swiftReleases. first ( where: { ( $0. name ?? " " ) == swiftVersion } ) else {
324- throw Error ( message: " Unable to find swift release using swift.org API: \( swiftVersion) " )
325- }
326-
327- guard let sdkPlatform = ( swiftRelease. platforms ?? [ SwiftPlatform] ( ) ) . first ( where: { ( $0. name ?? " " ) == " Static SDK " } ) else {
228+ guard let sdkPlatform = swiftRelease. platforms. first ( where: { $0. name == " Static SDK " } ) else {
328229 throw Error ( message: " Swift release \( swiftVersion) has no Static SDK offering " )
329230 }
330231
331- try runProgram ( swift, " sdk " , " install " , " https://download.swift.org/swift- \( swiftVersion) -release/static-sdk/swift- \( swiftVersion) -RELEASE/swift- \( swiftVersion) -RELEASE_static-linux-0.0.1.artifactbundle.tar.gz " , " --checksum " , sdkPlatform. checksum ?? " deadbeef " )
232+ try currentPlatform . runProgram ( swift, " sdk " , " install " , " https://download.swift.org/swift- \( swiftVersion) -release/static-sdk/swift- \( swiftVersion) -RELEASE/swift- \( swiftVersion) -RELEASE_static-linux-0.0.1.artifactbundle.tar.gz " , " --checksum " , sdkPlatform. checksum ?? " deadbeef " )
332233
333234 var customEnv = ProcessInfo . processInfo. environment
334235 customEnv [ " CC " ] = " \( cwd) /Tools/build-swiftly-release/musl-clang "
335236 customEnv [ " MUSL_PREFIX " ] = " \( FileManager . default. homeDirectoryForCurrentUser. path) /.swiftpm/swift-sdks/ \( sdkName) .artifactbundle/ \( sdkName) /swift-linux-musl/musl-1.2.5.sdk/ \( arch) /usr "
336237
337- try runProgramEnv (
238+ try currentPlatform . runProgram (
338239 " ./configure " ,
339240 " --prefix= \( pkgConfigPath) " ,
340241 " --enable-shared=no " ,
@@ -356,18 +257,18 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
356257 env: customEnv
357258 )
358259
359- try runProgramEnv ( make, env: customEnv)
260+ try currentPlatform . runProgram ( make, env: customEnv)
360261
361- try runProgram ( make, " install " )
262+ try currentPlatform . runProgram ( make, " install " )
362263
363264 FileManager . default. changeCurrentDirectoryPath ( cwd)
364265
365- try runProgram ( swift, " build " , " --swift-sdk " , " \( arch) -swift-linux-musl " , " --product=swiftly " , " --pkg-config-path= \( pkgConfigPath) /lib/pkgconfig " , " --static-swift-stdlib " , " --configuration=release " )
266+ try currentPlatform . runProgram ( swift, " build " , " --swift-sdk " , " \( arch) -swift-linux-musl " , " --product=swiftly " , " --pkg-config-path= \( pkgConfigPath) /lib/pkgconfig " , " --static-swift-stdlib " , " --configuration=release " )
366267
367268 let releaseDir = cwd + " /.build/release "
368269
369270 // Strip the symbols from the binary to decrease its size
370- try runProgram ( strip, releaseDir + " /swiftly " )
271+ try currentPlatform . runProgram ( strip, releaseDir + " /swiftly " )
371272
372273 try await self . collectLicenses ( releaseDir)
373274
@@ -377,7 +278,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
377278 let releaseArchive = " \( releaseDir) /swiftly- \( version) -x86_64.tar.gz "
378279#endif
379280
380- try runProgram ( tar, " --directory= \( releaseDir) " , " -czf " , releaseArchive, " swiftly " , " LICENSE.txt " )
281+ try currentPlatform . runProgram ( tar, " --directory= \( releaseDir) " , " -czf " , releaseArchive, " swiftly " , " LICENSE.txt " )
381282
382283 print ( releaseArchive)
383284
@@ -390,13 +291,13 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
390291 let testArchive = " \( debugDir) /test-swiftly-linux-x86_64.tar.gz "
391292#endif
392293
393- try runProgram ( swift, " build " , " --swift-sdk " , " \( arch) -swift-linux-musl " , " --product=test-swiftly " , " --pkg-config-path= \( pkgConfigPath) /lib/pkgconfig " , " --static-swift-stdlib " , " --configuration=debug " )
394- try runProgram ( tar, " --directory= \( debugDir) " , " -czf " , testArchive, " test-swiftly " )
294+ try currentPlatform . runProgram ( swift, " build " , " --swift-sdk " , " \( arch) -swift-linux-musl " , " --product=test-swiftly " , " --pkg-config-path= \( pkgConfigPath) /lib/pkgconfig " , " --static-swift-stdlib " , " --configuration=debug " )
295+ try currentPlatform . runProgram ( tar, " --directory= \( debugDir) " , " -czf " , testArchive, " test-swiftly " )
395296
396297 print ( testArchive)
397298 }
398299
399- try runProgram ( swift, " sdk " , " remove " , sdkName)
300+ try currentPlatform . runProgram ( swift, " sdk " , " remove " , sdkName)
400301 }
401302
402303 func buildMacOSRelease( cert: String ? , identifier: String ) async throws {
@@ -411,11 +312,11 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
411312
412313 let tar = try await self . assertTool ( " tar " , message: " In order to produce archives there needs to be the `tar` tool that is installed on macOS. " )
413314
414- try runProgram ( swift, " package " , " clean " )
315+ try currentPlatform . runProgram ( swift, " package " , " clean " )
415316
416317 for arch in [ " x86_64 " , " arm64 " ] {
417- try runProgram ( swift, " build " , " --product=swiftly " , " --configuration=release " , " --arch= \( arch) " )
418- try runProgram ( strip, " .build/ \( arch) -apple-macosx/release/swiftly " )
318+ try currentPlatform . runProgram ( swift, " build " , " --product=swiftly " , " --configuration=release " , " --arch= \( arch) " )
319+ try currentPlatform . runProgram ( strip, " .build/ \( arch) -apple-macosx/release/swiftly " )
419320 }
420321
421322 let swiftlyBinDir = fs. cwd / " .build/release/.swiftly/bin "
@@ -461,16 +362,16 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
461362 let pkgFileReconfigured = releaseDir. appendingPathComponent ( " swiftly- \( self . version) -reconfigured.pkg " )
462363 let distFile = releaseDir. appendingPathComponent ( " distribution.plist " )
463364
464- try runProgram ( " productbuild " , " --synthesize " , " --package " , pkgFile. path, distFile. path)
365+ try currentPlatform . runProgram ( " productbuild " , " --synthesize " , " --package " , pkgFile. path, distFile. path)
465366
466367 var distFileContents = try String ( contentsOf: distFile, encoding: . utf8)
467368 distFileContents = distFileContents. replacingOccurrences ( of: " <choices-outline> " , with: " <title>swiftly</title><domains enable_anywhere= \" false \" enable_currentUserHome= \" true \" enable_localSystem= \" false \" /><choices-outline> " )
468369 try distFileContents. write ( to: distFile, atomically: true , encoding: . utf8)
469370
470371 if let cert = cert {
471- try runProgram ( " productbuild " , " --distribution " , distFile. path, " --package-path " , pkgFile. deletingLastPathComponent ( ) . path, " --sign " , cert, pkgFileReconfigured. path)
372+ try currentPlatform . runProgram ( " productbuild " , " --distribution " , distFile. path, " --package-path " , pkgFile. deletingLastPathComponent ( ) . path, " --sign " , cert, pkgFileReconfigured. path)
472373 } else {
473- try runProgram ( " productbuild " , " --distribution " , distFile. path, " --package-path " , pkgFile. deletingLastPathComponent ( ) . path, pkgFileReconfigured. path)
374+ try currentPlatform . runProgram ( " productbuild " , " --distribution " , distFile. path, " --package-path " , pkgFile. deletingLastPathComponent ( ) . path, pkgFileReconfigured. path)
474375 }
475376 try FileManager . default. removeItem ( at: pkgFile)
476377 try FileManager . default. copyItem ( atPath: pkgFileReconfigured. path, toPath: pkgFile. path)
@@ -479,8 +380,8 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
479380
480381 if self . test {
481382 for arch in [ " x86_64 " , " arm64 " ] {
482- try runProgram ( swift, " build " , " --product=test-swiftly " , " --configuration=debug " , " --arch= \( arch) " )
483- try runProgram ( strip, " .build/ \( arch) -apple-macosx/release/swiftly " )
383+ try currentPlatform . runProgram ( swift, " build " , " --product=test-swiftly " , " --configuration=debug " , " --arch= \( arch) " )
384+ try currentPlatform . runProgram ( strip, " .build/ \( arch) -apple-macosx/release/swiftly " )
484385 }
485386
486387 let testArchive = releaseDir. appendingPathComponent ( " test-swiftly-macos.tar.gz " )
@@ -491,7 +392,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
491392 . create ( output: swiftlyBinDir / " swiftly " )
492393 . runEcho ( currentPlatform)
493394
494- try runProgram ( tar, " --directory=.build/x86_64-apple-macosx/debug " , " -czf " , testArchive. path, " test-swiftly " )
395+ try currentPlatform . runProgram ( tar, " --directory=.build/x86_64-apple-macosx/debug " , " -czf " , testArchive. path, " test-swiftly " )
495396
496397 print ( testArchive. path)
497398 }
0 commit comments