@@ -6,26 +6,38 @@ struct PackageToJS: CommandPlugin {
6
6
struct Options {
7
7
/// Product to build (default: executable target if there's only one)
8
8
var product : String ?
9
+ /// Path to the output directory
10
+ var outputPath : String ?
9
11
/// Name of the package (default: lowercased Package.swift name)
10
12
var packageName : String ?
11
13
/// Whether to explain the build plan
12
14
var explain : Bool = false
13
15
14
16
static func parse( from extractor: inout ArgumentExtractor ) -> Options {
15
17
let product = extractor. extractOption ( named: " product " ) . last
18
+ let outputPath = extractor. extractOption ( named: " output " ) . last
16
19
let packageName = extractor. extractOption ( named: " package-name " ) . last
17
20
let explain = extractor. extractFlag ( named: " explain " )
18
- return Options ( product: product, packageName: packageName, explain: explain != 0 )
21
+ return Options (
22
+ product: product, outputPath: outputPath, packageName: packageName,
23
+ explain: explain != 0
24
+ )
19
25
}
20
26
21
27
static func help( ) -> String {
22
28
return """
23
- Usage: swift package --swift-sdk <swift-sdk> plugin run PackageToJS [options]
29
+ Usage: swift package --swift-sdk <swift-sdk> [swift-package options] plugin run PackageToJS [options]
24
30
25
31
Options:
26
- --product <product> Product to build (default: executable target if there's only one)
27
- --package-name <name> Name of the package (default: lowercased Package.swift name)
28
- --explain Whether to explain the build plan
32
+ --product <product> Product to build (default: executable target if there's only one)
33
+ --output <path> Path to the output directory (default: .build/plugins/PackageToJS/outputs/Package)
34
+ --package-name <name> Name of the package (default: lowercased Package.swift name)
35
+ --explain Whether to explain the build plan
36
+
37
+ Examples:
38
+ $ swift package --swift-sdk wasm32-unknown-wasi plugin js
39
+ $ swift package --swift-sdk wasm32-unknown-wasi plugin js --product Example
40
+ $ swift package --swift-sdk wasm32-unknown-wasi -c release plugin js
29
41
"""
30
42
}
31
43
}
@@ -74,26 +86,38 @@ struct PackageToJS: CommandPlugin {
74
86
75
87
func performCommand( context: PluginContext , arguments: [ String ] ) throws {
76
88
if arguments. contains ( where: { [ " -h " , " --help " ] . contains ( $0) } ) {
77
- print ( Options . help ( ) )
89
+ printStderr ( Options . help ( ) )
78
90
return
79
91
}
80
92
81
93
var extractor = ArgumentExtractor ( arguments)
82
94
let options = Options . parse ( from: & extractor)
83
95
96
+ if extractor. remainingArguments. count > 0 {
97
+ printStderr (
98
+ " Unexpected arguments: \( extractor. remainingArguments. joined ( separator: " " ) ) " )
99
+ printStderr ( Options . help ( ) )
100
+ exit ( 1 )
101
+ }
102
+
84
103
// Build products
85
104
let ( build, productName) = try buildWasm ( options: options, context: context)
86
105
guard build. succeeded else {
87
106
for diagnostic in Self . friendlyBuildDiagnostics {
88
107
if let message = diagnostic ( build, arguments) {
89
- fputs ( " \n " + message + " \n " , stderr )
108
+ printStderr ( " \n " + message)
90
109
}
91
110
}
92
111
exit ( 1 )
93
112
}
94
113
95
114
let productArtifact = try build. findWasmArtifact ( for: productName)
96
- let outputDir = context. pluginWorkDirectory. appending ( subpath: " Package " )
115
+ let outputDir =
116
+ if let outputPath = options. outputPath {
117
+ URL ( fileURLWithPath: outputPath)
118
+ } else {
119
+ context. pluginWorkDirectoryURL. appending ( path: " Package " )
120
+ }
97
121
guard
98
122
let selfPackage = findPackageInDependencies (
99
123
package : context. package , id: " javascriptkit " )
@@ -128,7 +152,9 @@ struct PackageToJS: CommandPlugin {
128
152
parameters. otherSwiftcFlags = [
129
153
" -static-stdlib " , " -Xclang-linker " , " -mexec-model=reactor " ,
130
154
]
131
- parameters. otherLinkerFlags = [ " --export-if-defined=__main_argc_argv " ]
155
+ parameters. otherLinkerFlags = [
156
+ " --export-if-defined=__main_argc_argv "
157
+ ]
132
158
}
133
159
let productName = try options. product ?? deriveDefaultProduct ( package : context. package )
134
160
let build = try self . packageManager. build ( . product( productName) , parameters: parameters)
@@ -142,14 +168,14 @@ struct PackageToJS: CommandPlugin {
142
168
context: PluginContext ,
143
169
wasmProductArtifact: PackageManager . BuildResult . BuiltArtifact ,
144
170
selfPackage: Package ,
145
- outputDir: Path
171
+ outputDir: URL
146
172
) -> MiniMake . TaskKey {
147
- let selfPackageURL = selfPackage. directory
173
+ let selfPackageURL = selfPackage. directoryURL
148
174
let selfPath = String ( #filePath)
149
175
150
176
// Prepare output directory
151
177
let outputDirTask = make. addTask (
152
- inputFiles: [ selfPath] , output: outputDir. string , attributes: [ . silent]
178
+ inputFiles: [ selfPath] , output: outputDir. path , attributes: [ . silent]
153
179
) {
154
180
guard !FileManager. default. fileExists ( atPath: $0. output) else { return }
155
181
try FileManager . default. createDirectory (
@@ -169,7 +195,7 @@ struct PackageToJS: CommandPlugin {
169
195
let wasmFilename = " main.wasm "
170
196
let wasm = make. addTask (
171
197
inputFiles: [ selfPath, wasmProductArtifact. path. string] , inputTasks: [ outputDirTask] ,
172
- output: outputDir. appending ( subpath : wasmFilename) . string
198
+ output: outputDir. appending ( path : wasmFilename) . path
173
199
) {
174
200
try syncFile ( from: wasmProductArtifact. path. string, to: $0. output)
175
201
}
@@ -178,7 +204,7 @@ struct PackageToJS: CommandPlugin {
178
204
// Write package.json
179
205
let packageJSON = make. addTask (
180
206
inputFiles: [ selfPath] , inputTasks: [ outputDirTask] ,
181
- output: outputDir. appending ( subpath : " package.json " ) . string
207
+ output: outputDir. appending ( path : " package.json " ) . path
182
208
) {
183
209
let packageJSON = """
184
210
{
@@ -207,12 +233,12 @@ struct PackageToJS: CommandPlugin {
207
233
( " Plugins/PackageToJS/Templates/index.d.ts " , " index.d.ts " ) ,
208
234
( " Sources/JavaScriptKit/Runtime/index.mjs " , " runtime.js " ) ,
209
235
] {
210
- let inputPath = selfPackageURL. appending ( subpath : file) . string
236
+ let inputPath = selfPackageURL. appending ( path : file)
211
237
let copied = make. addTask (
212
- inputFiles: [ selfPath, inputPath] , inputTasks: [ outputDirTask] ,
213
- output: outputDir. appending ( subpath : output) . string
238
+ inputFiles: [ selfPath, inputPath. path ] , inputTasks: [ outputDirTask] ,
239
+ output: outputDir. appending ( path : output) . path
214
240
) {
215
- var content = try String ( contentsOfFile : inputPath)
241
+ var content = try String ( contentsOf : inputPath)
216
242
for (key, value) in substitutions {
217
243
content = content. replacingOccurrences ( of: key, with: value)
218
244
}
@@ -306,6 +332,10 @@ private func findPackageInDependencies(package: Package, id: Package.ID) -> Pack
306
332
return visit ( package : package )
307
333
}
308
334
335
+ private func printStderr( _ message: String ) {
336
+ fputs ( message + " \n " , stderr)
337
+ }
338
+
309
339
private struct PackageToJSError : Swift . Error , CustomStringConvertible {
310
340
let description : String
311
341
0 commit comments