@@ -17,117 +17,24 @@ import SwiftSDKGenerator
17
17
18
18
@main
19
19
struct GeneratorCLI : AsyncParsableCommand {
20
- static let configuration = CommandConfiguration ( commandName: " swift-sdk-generator " )
21
-
22
- @Option ( help: " An arbitrary version number for informational purposes. " )
23
- var bundleVersion = " 0.0.1 "
24
-
25
- @Flag ( help: " Delegate to Docker for copying files for the target triple. " )
26
- var withDocker : Bool = false
27
-
28
- @Option ( help: " Container image from which to copy the target triple. " )
29
- var fromContainerImage : String ? = nil
30
-
31
- @Option (
32
- help: """
33
- Name of the SDK bundle. Defaults to a string composed of Swift version, Linux distribution, Linux release \
34
- and target CPU architecture.
35
- """
36
- )
37
- var sdkName : String ? = nil
38
-
39
- @Flag (
40
- help: " Experimental: avoid cleaning up toolchain and SDK directories and regenerate the SDK bundle incrementally. "
41
- )
42
- var incremental : Bool = false
43
-
44
- @Flag ( name: . shortAndLong, help: " Provide verbose logging output. " )
45
- var verbose = false
46
-
47
- @Option (
48
- help: """
49
- Branch of Swift to use when downloading nightly snapshots. Specify `development` for snapshots off the `main` \
50
- branch of Swift open source project repositories.
51
- """
52
- )
53
- var swiftBranch : String ? = nil
54
-
55
- @Option ( help: " Version of Swift to supply in the bundle. " )
56
- var swiftVersion = " 5.9.2-RELEASE "
57
-
58
- @Option ( help: " Version of LLD linker to supply in the bundle. " )
59
- var lldVersion = " 17.0.5 "
60
-
61
- @Option (
62
- help: """
63
- Linux distribution to use if the target platform is Linux. Available options: `ubuntu`, `rhel`. Default is `ubuntu`.
64
- """ ,
65
- transform: LinuxDistribution . Name. init ( nameString: )
66
- )
67
- var linuxDistributionName = LinuxDistribution . Name. ubuntu
68
-
69
- @Option (
70
- help: """
71
- Version of the Linux distribution used as a target platform. Available options for Ubuntu: `20.04`, \
72
- `22.04` (default when `--linux-distribution-name` is `ubuntu`). Available options for RHEL: `ubi9` (default when \
73
- `--linux-distribution-name` is `rhel`).
74
- """
75
- )
76
- var linuxDistributionVersion : String ?
77
-
78
- @Option (
79
- help: """
80
- CPU architecture of the host triple of the bundle. Defaults to a triple of the machine this generator is \
81
- running on if unspecified. Available options: \(
82
- Triple . CPU. allCases. map { " ` \( $0. rawValue) ` " } . joined ( separator: " , " )
83
- ) .
84
- """
20
+ static let configuration = CommandConfiguration (
21
+ commandName: " swift-sdk-generator " ,
22
+ subcommands: [ MakeLinuxSDK . self] ,
23
+ defaultSubcommand: MakeLinuxSDK . self
85
24
)
86
- var hostArch : Triple . CPU ? = nil
87
-
88
- @Option (
89
- help: """
90
- CPU architecture of the target triple of the bundle. Same as the host triple CPU architecture if unspecified. \
91
- Available options: \( Triple . CPU. allCases. map { " ` \( $0. rawValue) ` " } . joined ( separator: " , " ) ) .
92
- """
93
- )
94
- var targetArch : Triple . CPU ? = nil
95
-
96
- func run( ) async throws {
97
- let linuxDistributionDefaultVersion = switch self . linuxDistributionName {
98
- case . rhel:
99
- " ubi9 "
100
- case . ubuntu:
101
- " 22.04 "
102
- }
103
- let linuxDistributionVersion = self . linuxDistributionVersion ?? linuxDistributionDefaultVersion
104
- let linuxDistribution = try LinuxDistribution ( name: linuxDistributionName, version: linuxDistributionVersion)
105
25
26
+ static func run< Recipe: SwiftSDKRecipe > ( recipe: Recipe , options: GeneratorOptions ) async throws {
106
27
let elapsed = try await ContinuousClock ( ) . measure {
107
28
let logger = Logger ( label: " org.swift.swift-sdk-generator " )
108
- let hostTriple = try await SwiftSDKGenerator . getHostTriple ( explicitArch: hostArch, isVerbose: verbose)
109
- let targetTriple = Triple (
110
- cpu: targetArch ?? hostTriple. cpu,
111
- vendor: . unknown,
112
- os: . linux,
113
- environment: . gnu
114
- )
115
- let recipe = try LinuxRecipe (
116
- targetTriple: targetTriple,
117
- linuxDistribution: linuxDistribution,
118
- swiftVersion: swiftVersion,
119
- swiftBranch: swiftBranch,
120
- lldVersion: lldVersion,
121
- withDocker: withDocker,
122
- fromContainerImage: fromContainerImage
123
- )
29
+
30
+ let ( hostTriple, targetTriple) = try await options. deriveTriples ( )
124
31
let generator = try await SwiftSDKGenerator (
125
- bundleVersion: self . bundleVersion,
32
+ bundleVersion: options . bundleVersion,
126
33
hostTriple: hostTriple,
127
34
targetTriple: targetTriple,
128
- artifactID: self . sdkName ?? recipe. defaultArtifactID,
129
- isIncremental: self . incremental,
130
- isVerbose: self . verbose,
35
+ artifactID: options . sdkName ?? recipe. defaultArtifactID,
36
+ isIncremental: options . incremental,
37
+ isVerbose: options . verbose,
131
38
logger: logger
132
39
)
133
40
@@ -151,6 +58,145 @@ struct GeneratorCLI: AsyncParsableCommand {
151
58
152
59
extension Triple . CPU : ExpressibleByArgument { }
153
60
61
+ extension GeneratorCLI {
62
+ struct GeneratorOptions : ParsableArguments {
63
+ @Option ( help: " An arbitrary version number for informational purposes. " )
64
+ var bundleVersion = " 0.0.1 "
65
+
66
+ @Option (
67
+ help: """
68
+ Name of the SDK bundle. Defaults to a string composed of Swift version, Linux distribution, Linux release \
69
+ and target CPU architecture.
70
+ """
71
+ )
72
+ var sdkName : String ? = nil
73
+
74
+ @Flag (
75
+ help: " Experimental: avoid cleaning up toolchain and SDK directories and regenerate the SDK bundle incrementally. "
76
+ )
77
+ var incremental : Bool = false
78
+
79
+ @Flag ( name: . shortAndLong, help: " Provide verbose logging output. " )
80
+ var verbose = false
81
+
82
+ @Option (
83
+ help: """
84
+ Branch of Swift to use when downloading nightly snapshots. Specify `development` for snapshots off the `main` \
85
+ branch of Swift open source project repositories.
86
+ """
87
+ )
88
+ var swiftBranch : String ? = nil
89
+
90
+ @Option ( help: " Version of Swift to supply in the bundle. " )
91
+ var swiftVersion = " 5.9.2-RELEASE "
92
+
93
+ @Option (
94
+ help: """
95
+ CPU architecture of the host triple of the bundle. Defaults to a triple of the machine this generator is \
96
+ running on if unspecified. Available options: \(
97
+ Triple . CPU. allCases. map { " ` \( $0. rawValue) ` " } . joined ( separator: " , " )
98
+ ) .
99
+ """
100
+ )
101
+ var hostArch : Triple . CPU ? = nil
102
+
103
+ @Option (
104
+ help: """
105
+ CPU architecture of the target triple of the bundle. Same as the host triple CPU architecture if unspecified. \
106
+ Available options: \( Triple . CPU. allCases. map { " ` \( $0. rawValue) ` " } . joined ( separator: " , " ) ) .
107
+ """
108
+ )
109
+ var targetArch : Triple . CPU ? = nil
110
+
111
+ func deriveTriples( ) async throws -> ( hostTriple: Triple , targetTriple: Triple ) {
112
+ let hostTriple = try await SwiftSDKGenerator . getHostTriple ( explicitArch: hostArch, isVerbose: verbose)
113
+ let targetTriple = Triple (
114
+ cpu: targetArch ?? hostTriple. cpu,
115
+ vendor: . unknown,
116
+ os: . linux,
117
+ environment: . gnu
118
+ )
119
+ return ( hostTriple, targetTriple)
120
+ }
121
+ }
122
+
123
+ struct MakeLinuxSDK : AsyncParsableCommand {
124
+ static let configuration = CommandConfiguration (
125
+ commandName: " make-linux-sdk " ,
126
+ abstract: " Generate a Swift SDK bundle for Linux. "
127
+ )
128
+
129
+ @OptionGroup
130
+ var generatorOptions : GeneratorOptions
131
+
132
+ @Flag ( help: " Delegate to Docker for copying files for the target triple. " )
133
+ var withDocker : Bool = false
134
+
135
+ @Option ( help: " Container image from which to copy the target triple. " )
136
+ var fromContainerImage : String ? = nil
137
+
138
+ @Option ( help: " Version of LLD linker to supply in the bundle. " )
139
+ var lldVersion = " 17.0.5 "
140
+
141
+ @Option (
142
+ help: """
143
+ Linux distribution to use if the target platform is Linux. Available options: `ubuntu`, `rhel`. Default is `ubuntu`.
144
+ """ ,
145
+ transform: LinuxDistribution . Name. init ( nameString: )
146
+ )
147
+ var linuxDistributionName = LinuxDistribution . Name. ubuntu
148
+
149
+ @Option (
150
+ help: """
151
+ Version of the Linux distribution used as a target platform. Available options for Ubuntu: `20.04`, \
152
+ `22.04` (default when `--linux-distribution-name` is `ubuntu`). Available options for RHEL: `ubi9` (default when \
153
+ `--linux-distribution-name` is `rhel`).
154
+ """
155
+ )
156
+ var linuxDistributionVersion : String ?
157
+
158
+ func run( ) async throws {
159
+ if isInvokedAsDefaultSubcommand ( ) {
160
+ print ( " deprecated: Please explicity specify the subcommand to run. For example: $ swift-sdk-generator make-linux-sdk " )
161
+ }
162
+ let linuxDistributionDefaultVersion = switch self . linuxDistributionName {
163
+ case . rhel:
164
+ " ubi9 "
165
+ case . ubuntu:
166
+ " 22.04 "
167
+ }
168
+ let linuxDistributionVersion = self . linuxDistributionVersion ?? linuxDistributionDefaultVersion
169
+ let linuxDistribution = try LinuxDistribution ( name: linuxDistributionName, version: linuxDistributionVersion)
170
+ let ( _, targetTriple) = try await generatorOptions. deriveTriples ( )
171
+
172
+ let recipe = try LinuxRecipe (
173
+ targetTriple: targetTriple,
174
+ linuxDistribution: linuxDistribution,
175
+ swiftVersion: generatorOptions. swiftVersion,
176
+ swiftBranch: generatorOptions. swiftBranch,
177
+ lldVersion: lldVersion,
178
+ withDocker: withDocker,
179
+ fromContainerImage: fromContainerImage
180
+ )
181
+ try await GeneratorCLI . run ( recipe: recipe, options: generatorOptions)
182
+ }
183
+
184
+ func isInvokedAsDefaultSubcommand( ) -> Bool {
185
+ let arguments = CommandLine . arguments
186
+ guard arguments. count >= 2 else {
187
+ // No subcommand nor option: $ swift-sdk-generator
188
+ return true
189
+ }
190
+ let maybeSubcommand = arguments [ 1 ]
191
+ guard maybeSubcommand == Self . configuration. commandName else {
192
+ // No subcommand but with option: $ swift-sdk-generator --with-docker
193
+ return true
194
+ }
195
+ return false
196
+ }
197
+ }
198
+ }
199
+
154
200
// FIXME: replace this with a call on `.formatted()` on `Duration` when it's available in swift-foundation.
155
201
import Foundation
156
202
0 commit comments