Skip to content

Commit beff331

Browse files
committed
Model lipo invocations with a modeled command structure with a test
1 parent b81c9cc commit beff331

File tree

4 files changed

+103
-10
lines changed

4 files changed

+103
-10
lines changed

Sources/SwiftlyCore/Commands.swift

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ extension SystemCommand {
4848
self.read(path: path, keys: keys)
4949
}
5050

51-
public struct ReadCommand: Output {
51+
public struct ReadCommand {
5252
var dscl: DsclCommand
5353
var path: FilePath?
5454
var keys: [String]
@@ -76,7 +76,7 @@ extension SystemCommand {
7676
}
7777
}
7878

79-
extension SystemCommand.DsclCommand.ReadCommand {
79+
extension SystemCommand.DsclCommand.ReadCommand: Output {
8080
public func properties(_ p: Platform) async throws -> [(key: String, value: String)] {
8181
let output = try await self.output(p)
8282
guard let output else { return [] }
@@ -90,3 +90,79 @@ extension SystemCommand.DsclCommand.ReadCommand {
9090
return props
9191
}
9292
}
93+
94+
extension SystemCommand {
95+
public static func lipo(executable: Executable = LipoCommand.defaultExecutable, inputFiles: FilePath...) -> LipoCommand {
96+
Self.lipo(executable: executable, inputFiles: inputFiles)
97+
}
98+
99+
public static func lipo(executable: Executable = LipoCommand.defaultExecutable, inputFiles: [FilePath]) -> LipoCommand {
100+
LipoCommand(executable: executable, inputFiles: inputFiles)
101+
}
102+
103+
public struct LipoCommand {
104+
public static var defaultExecutable: Executable { .name("lipo") }
105+
106+
var executable: Executable
107+
var inputFiles: [FilePath]
108+
109+
public init(executable: Executable, inputFiles: [FilePath]) {
110+
self.executable = executable
111+
self.inputFiles = inputFiles
112+
}
113+
114+
func config() -> Configuration {
115+
var args: [String] = []
116+
117+
args += self.inputFiles.map(\.string)
118+
119+
return Configuration(
120+
executable: self.executable,
121+
arguments: Arguments(args),
122+
environment: .inherit
123+
)
124+
}
125+
126+
public func create(_ options: CreateCommand.Option...) -> CreateCommand {
127+
CreateCommand(self, options)
128+
}
129+
130+
public struct CreateCommand {
131+
var lipo: LipoCommand
132+
133+
var options: [Option]
134+
135+
init(_ lipo: LipoCommand, _ options: [Option]) {
136+
self.lipo = lipo
137+
self.options = options
138+
}
139+
140+
public enum Option {
141+
case output(FilePath)
142+
143+
func args() -> [String] {
144+
switch self {
145+
case let .output(output):
146+
return ["-output", output.string]
147+
}
148+
}
149+
}
150+
151+
public func config() -> Configuration {
152+
var c = self.lipo.config()
153+
154+
var args = c.arguments.storage.map(\.description) + ["-create"]
155+
156+
for opt in self.options {
157+
args += opt.args()
158+
}
159+
160+
c.arguments = .init(args)
161+
162+
return c
163+
}
164+
}
165+
}
166+
}
167+
168+
extension SystemCommand.LipoCommand.CreateCommand: Runnable {}

Sources/SwiftlyCore/ModeledCommandLine.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public protocol Runnable {
126126
}
127127

128128
extension Runnable {
129-
public func run(_ p: Platform, quiet: Bool) async throws {
129+
public func run(_ p: Platform, quiet: Bool = false) async throws {
130130
let c = self.config()
131131
let executable = switch c.executable.storage {
132132
case let .executable(name):

Tests/SwiftlyTests/CommandLineTests.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,11 @@ public struct CommandLineTests {
2828
#expect(properties.count == 1) // Only one shell for the current user
2929
#expect(properties[0].key == "UserShell") // The one property key should be the one that is requested
3030
}
31+
32+
@Test func testLipo() {
33+
var config = sys.lipo(inputFiles: FilePath("swiftly1"), FilePath("swiftly2")).create(.output(FilePath("swiftly-universal"))).config()
34+
35+
#expect(config.executable == .name("lipo"))
36+
#expect(config.arguments.storage.map(\.description) == ["swiftly1", "swiftly2", "-create", "-output", "swiftly-universal"])
37+
}
3138
}

Tools/build-swiftly-release/BuildSwiftlyRelease.swift

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ArgumentParser
22
import Foundation
33
import SwiftlyCore
4+
import SystemPackage
45

56
#if os(macOS)
67
import MacOSPlatform
@@ -14,6 +15,9 @@ let currentPlatform = MacOS()
1415
let currentPlatform = Linux()
1516
#endif
1617

18+
typealias fs = FileSystem
19+
typealias sys = SystemCommand
20+
1721
public struct SwiftPlatform: Codable {
1822
public var name: String?
1923
public var checksum: String?
@@ -392,7 +396,6 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
392396

393397
try await self.checkGitRepoStatus(git)
394398

395-
let lipo = try await self.assertTool("lipo", message: "In order to make a universal binary there needs to be the `lipo` tool that is installed on macOS.")
396399
let pkgbuild = try await self.assertTool("pkgbuild", message: "In order to make pkg installers there needs to be the `pkgbuild` tool that is installed on macOS.")
397400
let strip = try await self.assertTool("strip", message: "In order to strip binaries there needs to be the `strip` tool that is installed on macOS.")
398401

@@ -405,10 +408,13 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
405408
try runProgram(strip, ".build/\(arch)-apple-macosx/release/swiftly")
406409
}
407410

408-
let swiftlyBinDir = FileManager.default.currentDirectoryPath + "/.build/release/.swiftly/bin"
409-
try? FileManager.default.createDirectory(atPath: swiftlyBinDir, withIntermediateDirectories: true)
411+
let swiftlyBinDir = fs.cwd / ".build/release/.swiftly/bin"
412+
try? await fs.mkdir(.parents, atPath: swiftlyBinDir)
410413

411-
try runProgram(lipo, ".build/x86_64-apple-macosx/release/swiftly", ".build/arm64-apple-macosx/release/swiftly", "-create", "-o", "\(swiftlyBinDir)/swiftly")
414+
try await sys.lipo(
415+
inputFiles: FilePath(".build/x86_64-apple-macosx/release/swiftly"), FilePath(".build/arm64-apple-macosx/release/swiftly"))
416+
.create(.output(swiftlyBinDir / "swiftly"))
417+
.run(currentPlatform)
412418

413419
let swiftlyLicenseDir = FileManager.default.currentDirectoryPath + "/.build/release/.swiftly/license"
414420
try? FileManager.default.createDirectory(atPath: swiftlyLicenseDir, withIntermediateDirectories: true)
@@ -423,7 +429,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
423429
try runProgram(
424430
pkgbuild,
425431
"--root",
426-
swiftlyBinDir + "/..",
432+
"\(swiftlyBinDir.removingLastComponent)",
427433
"--install-location",
428434
".swiftly",
429435
"--version",
@@ -438,7 +444,7 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
438444
try runProgram(
439445
pkgbuild,
440446
"--root",
441-
swiftlyBinDir + "/..",
447+
"\(swiftlyBinDir.removingLastComponent)",
442448
"--install-location",
443449
".swiftly",
444450
"--version",
@@ -479,7 +485,11 @@ struct BuildSwiftlyRelease: AsyncParsableCommand {
479485

480486
let testArchive = releaseDir.appendingPathComponent("test-swiftly-macos.tar.gz")
481487

482-
try runProgram(lipo, ".build/x86_64-apple-macosx/debug/test-swiftly", ".build/arm64-apple-macosx/debug/test-swiftly", "-create", "-o", "\(swiftlyBinDir)/swiftly")
488+
try await sys.lipo(
489+
inputFiles: FilePath(".build/x86_64-apple-macosx/debug/test-swiftly"), FilePath(".build/arm64-apple-macosx/debug/test-swiftly"))
490+
.create(.output(swiftlyBinDir / "swiftly"))
491+
.run(currentPlatform)
492+
483493
try runProgram(tar, "--directory=.build/x86_64-apple-macosx/debug", "-czf", testArchive.path, "test-swiftly")
484494

485495
print(testArchive.path)

0 commit comments

Comments
 (0)