@@ -34,12 +34,24 @@ struct PackagingPlanner {
34
34
)
35
35
}
36
36
37
+ private static func runCommand( _ command: URL , _ arguments: [ String ] ) throws {
38
+ let task = Process ( )
39
+ task. executableURL = command
40
+ task. arguments = arguments
41
+ task. currentDirectoryURL = URL ( fileURLWithPath: FileManager . default. currentDirectoryPath)
42
+ try task. run ( )
43
+ task. waitUntilExit ( )
44
+ guard task. terminationStatus == 0 else {
45
+ throw PackageToJSError ( " Command failed with status \( task. terminationStatus) " )
46
+ }
47
+ }
48
+
37
49
/// Construct the build plan and return the root task key
38
50
func planBuild(
39
51
make: inout MiniMake ,
40
52
wasmProductArtifact: URL
41
- ) -> MiniMake . TaskKey {
42
- let ( allTasks, _) = planBuildInternal ( make: & make, wasmProductArtifact: wasmProductArtifact)
53
+ ) throws -> MiniMake . TaskKey {
54
+ let ( allTasks, _) = try planBuildInternal ( make: & make, wasmProductArtifact: wasmProductArtifact)
43
55
return make. addTask (
44
56
inputTasks: allTasks, output: " all " , attributes: [ . phony, . silent]
45
57
) { _ in }
@@ -48,7 +60,7 @@ struct PackagingPlanner {
48
60
private func planBuildInternal(
49
61
make: inout MiniMake ,
50
62
wasmProductArtifact: URL
51
- ) -> ( allTasks: [ MiniMake . TaskKey ] , outputDirTask: MiniMake . TaskKey ) {
63
+ ) throws -> ( allTasks: [ MiniMake . TaskKey ] , outputDirTask: MiniMake . TaskKey ) {
52
64
// Prepare output directory
53
65
let outputDirTask = make. addTask (
54
66
inputFiles: [ selfPath] , output: outputDir. path, attributes: [ . silent]
@@ -58,12 +70,57 @@ struct PackagingPlanner {
58
70
59
71
var packageInputs : [ MiniMake . TaskKey ] = [ ]
60
72
61
- // Copy the wasm product artifact
62
- let wasm = make. addTask (
63
- inputFiles: [ selfPath, wasmProductArtifact. path] , inputTasks: [ outputDirTask] ,
64
- output: outputDir. appending ( path: wasmFilename) . path
65
- ) {
66
- try Self . syncFile ( from: wasmProductArtifact. path, to: $0. output)
73
+ // Guess the build configuration from the parent directory name of .wasm file
74
+ let buildConfiguration = wasmProductArtifact. deletingLastPathComponent ( ) . lastPathComponent
75
+ let wasm : MiniMake . TaskKey
76
+
77
+ let shouldOptimize : Bool
78
+ let wasmOptPath = try ? which ( " wasm-opt " )
79
+ if buildConfiguration == " debug " {
80
+ shouldOptimize = false
81
+ } else {
82
+ if wasmOptPath != nil {
83
+ shouldOptimize = true
84
+ } else {
85
+ print ( " Warning: wasm-opt not found in PATH, skipping optimizations " )
86
+ shouldOptimize = false
87
+ }
88
+ }
89
+
90
+ if let wasmOptPath = wasmOptPath, shouldOptimize {
91
+ // Optimize the wasm in release mode
92
+ let tmpDir = outputDir. deletingLastPathComponent ( ) . appending ( path: " \( outputDir. lastPathComponent) .tmp " )
93
+ let tmpDirTask = make. addTask (
94
+ inputFiles: [ selfPath] , output: tmpDir. path, attributes: [ . silent]
95
+ ) {
96
+ try Self . createDirectory ( atPath: $0. output)
97
+ }
98
+ let stripWasmPath = tmpDir. appending ( path: wasmFilename + " .strip " ) . path
99
+
100
+ // First, strip DWARF sections as their existence enables DWARF preserving mode in wasm-opt
101
+ let stripWasm = make. addTask (
102
+ inputFiles: [ selfPath, wasmProductArtifact. path] , inputTasks: [ outputDirTask, tmpDirTask] ,
103
+ output: stripWasmPath
104
+ ) {
105
+ print ( " Stripping debug information... " )
106
+ try Self . runCommand ( wasmOptPath, [ wasmProductArtifact. path, " --strip-dwarf " , " --debuginfo " , " -o " , $0. output] )
107
+ }
108
+ // Then, run wasm-opt with all optimizations
109
+ wasm = make. addTask (
110
+ inputFiles: [ selfPath] , inputTasks: [ outputDirTask, stripWasm] ,
111
+ output: outputDir. appending ( path: wasmFilename) . path
112
+ ) {
113
+ print ( " Optimizing the wasm file... " )
114
+ try Self . runCommand ( wasmOptPath, [ stripWasmPath, " --debuginfo " , " -Os " , " -o " , $0. output] )
115
+ }
116
+ } else {
117
+ // Copy the wasm product artifact
118
+ wasm = make. addTask (
119
+ inputFiles: [ selfPath, wasmProductArtifact. path] , inputTasks: [ outputDirTask] ,
120
+ output: outputDir. appending ( path: wasmFilename) . path
121
+ ) {
122
+ try Self . syncFile ( from: wasmProductArtifact. path, to: $0. output)
123
+ }
67
124
}
68
125
packageInputs. append ( wasm)
69
126
@@ -110,8 +167,8 @@ struct PackagingPlanner {
110
167
func planTestBuild(
111
168
make: inout MiniMake ,
112
169
wasmProductArtifact: URL
113
- ) -> ( rootTask: MiniMake . TaskKey , binDir: URL ) {
114
- var ( allTasks, outputDirTask) = planBuildInternal ( make: & make, wasmProductArtifact: wasmProductArtifact)
170
+ ) throws -> ( rootTask: MiniMake . TaskKey , binDir: URL ) {
171
+ var ( allTasks, outputDirTask) = try planBuildInternal ( make: & make, wasmProductArtifact: wasmProductArtifact)
115
172
116
173
let binDir = outputDir. appending ( path: " bin " )
117
174
let binDirTask = make. addTask (
0 commit comments