From 7e33eb729fdb6347c27ed1e1d99d4ac10ec3ee77 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Wed, 17 Apr 2024 20:13:02 +0800 Subject: [PATCH] feat(cli): optimize wasm output binary (#2049) --- cli/esbuild.mjs | 2 +- cli/package.json | 1 + cli/src/api/build.ts | 32 ++++- cli/src/api/templates/load-wasi-template.ts | 5 +- examples/napi/example.wasi.cjs | 5 +- yarn.lock | 144 +++++++++++++++++++- 6 files changed, 183 insertions(+), 6 deletions(-) diff --git a/cli/esbuild.mjs b/cli/esbuild.mjs index 1f048a13..24eddaca 100644 --- a/cli/esbuild.mjs +++ b/cli/esbuild.mjs @@ -5,7 +5,7 @@ await esbuild.build({ outfile: './dist/index.cjs', bundle: true, platform: 'node', - external: ['@napi-rs/lzma', '@napi-rs/tar'], + external: ['@napi-rs/lzma', '@napi-rs/tar', '@napi-rs/wasm-tools'], define: { 'import.meta.url': '__filename', }, diff --git a/cli/package.json b/cli/package.json index 502eea5d..16706155 100644 --- a/cli/package.json +++ b/cli/package.json @@ -68,6 +68,7 @@ }, "dependencies": { "@napi-rs/cross-toolchain": "^0.0.14", + "@napi-rs/wasm-tools": "^0.0.1", "@octokit/rest": "^20.0.2", "clipanion": "^3.2.1", "colorette": "^2.0.20", diff --git a/cli/src/api/build.ts b/cli/src/api/build.ts index 821fb17f..4cd35757 100644 --- a/cli/src/api/build.ts +++ b/cli/src/api/build.ts @@ -729,6 +729,7 @@ class Builder { const src = join(this.targetDir, this.target.triple, profile, srcName) debug(`Copy artifact from: [${src}]`) const dest = join(this.outputDir, destName) + const isWasm = dest.endsWith('.wasm') try { if (await fileExists(dest)) { @@ -737,9 +738,36 @@ class Builder { } debug('Copy artifact to:') debug(' %i', dest) - await copyFileAsync(src, dest) + if (isWasm) { + const { ModuleConfig } = await import('@napi-rs/wasm-tools') + debug('Generate debug wasm module') + const debugWasmModule = new ModuleConfig() + .generateDwarf(true) + .generateNameSection(true) + .generateProducersSection(true) + .preserveCodeTransform(true) + .strictValidate(false) + .parse(await readFileAsync(src)) + const debugWasmBinary = debugWasmModule.emitWasm(true) + await writeFileAsync( + dest.replace('.wasm', '.debug.wasm'), + debugWasmBinary, + ) + debug('Generate release wasm module') + const releaseWasmModule = new ModuleConfig() + .generateDwarf(false) + .generateNameSection(false) + .generateProducersSection(false) + .preserveCodeTransform(false) + .strictValidate(false) + .parse(debugWasmBinary) + const releaseWasmBinary = releaseWasmModule.emitWasm(false) + await writeFileAsync(dest, releaseWasmBinary) + } else { + await copyFileAsync(src, dest) + } this.outputs.push({ - kind: dest.endsWith('.node') ? 'node' : 'exe', + kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe', path: dest, }) return dest diff --git a/cli/src/api/templates/load-wasi-template.ts b/cli/src/api/templates/load-wasi-template.ts index 9592def8..3ce98a70 100644 --- a/cli/src/api/templates/load-wasi-template.ts +++ b/cli/src/api/templates/load-wasi-template.ts @@ -105,8 +105,11 @@ const __sharedMemory = new WebAssembly.Memory({ }) let __wasmFilePath = __nodePath.join(__dirname, '${wasmFileName}.wasm') +const __wasmDebugFilePath = __nodePath.join(__dirname, '${wasmFileName}.debug.wasm') -if (!__nodeFs.existsSync(__wasmFilePath)) { +if (__nodeFs.existsSync(__wasmDebugFilePath)) { + __wasmFilePath = __wasmDebugFilePath +} else if (!__nodeFs.existsSync(__wasmFilePath)) { try { __wasmFilePath = __nodePath.resolve('${packageName}-wasm32-wasi') } catch { diff --git a/examples/napi/example.wasi.cjs b/examples/napi/example.wasi.cjs index e1dbf30a..9ccef9bc 100644 --- a/examples/napi/example.wasi.cjs +++ b/examples/napi/example.wasi.cjs @@ -30,8 +30,11 @@ const __sharedMemory = new WebAssembly.Memory({ }) let __wasmFilePath = __nodePath.join(__dirname, 'example.wasm32-wasi.wasm') +const __wasmDebugFilePath = __nodePath.join(__dirname, 'example.wasm32-wasi.debug.wasm') -if (!__nodeFs.existsSync(__wasmFilePath)) { +if (__nodeFs.existsSync(__wasmDebugFilePath)) { + __wasmFilePath = __wasmDebugFilePath +} else if (!__nodeFs.existsSync(__wasmFilePath)) { try { __wasmFilePath = __nodePath.resolve('@examples/napi-wasm32-wasi') } catch { diff --git a/yarn.lock b/yarn.lock index 12bfe4a2..a817290f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -520,6 +520,7 @@ __metadata: "@emnapi/core": "npm:^1.1.0" "@emnapi/runtime": "npm:^1.1.0" "@napi-rs/cross-toolchain": "npm:^0.0.14" + "@napi-rs/wasm-tools": "npm:^0.0.1" "@octokit/rest": "npm:^20.0.2" "@types/debug": "npm:^4.1.12" "@types/inquirer": "npm:^9.0.7" @@ -880,7 +881,7 @@ __metadata: languageName: unknown linkType: soft -"@napi-rs/wasm-runtime@workspace:*, @napi-rs/wasm-runtime@workspace:wasm-runtime": +"@napi-rs/wasm-runtime@npm:^0.1.2, @napi-rs/wasm-runtime@workspace:*, @napi-rs/wasm-runtime@workspace:wasm-runtime": version: 0.0.0-use.local resolution: "@napi-rs/wasm-runtime@workspace:wasm-runtime" dependencies: @@ -905,6 +906,147 @@ __metadata: languageName: unknown linkType: soft +"@napi-rs/wasm-tools-android-arm-eabi@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-android-arm-eabi@npm:0.0.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-android-arm64@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-android-arm64@npm:0.0.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-darwin-arm64@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-darwin-arm64@npm:0.0.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-darwin-x64@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-darwin-x64@npm:0.0.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-freebsd-x64@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-freebsd-x64@npm:0.0.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-linux-arm64-gnu@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-linux-arm64-gnu@npm:0.0.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-linux-arm64-musl@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-linux-arm64-musl@npm:0.0.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-linux-x64-gnu@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-linux-x64-gnu@npm:0.0.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-linux-x64-musl@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-linux-x64-musl@npm:0.0.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-wasm32-wasi@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-wasm32-wasi@npm:0.0.1" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.1.2" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-win32-arm64-msvc@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-win32-arm64-msvc@npm:0.0.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-win32-ia32-msvc@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-win32-ia32-msvc@npm:0.0.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools-win32-x64-msvc@npm:0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools-win32-x64-msvc@npm:0.0.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@napi-rs/wasm-tools@npm:^0.0.1": + version: 0.0.1 + resolution: "@napi-rs/wasm-tools@npm:0.0.1" + dependencies: + "@napi-rs/wasm-tools-android-arm-eabi": "npm:0.0.1" + "@napi-rs/wasm-tools-android-arm64": "npm:0.0.1" + "@napi-rs/wasm-tools-darwin-arm64": "npm:0.0.1" + "@napi-rs/wasm-tools-darwin-x64": "npm:0.0.1" + "@napi-rs/wasm-tools-freebsd-x64": "npm:0.0.1" + "@napi-rs/wasm-tools-linux-arm64-gnu": "npm:0.0.1" + "@napi-rs/wasm-tools-linux-arm64-musl": "npm:0.0.1" + "@napi-rs/wasm-tools-linux-x64-gnu": "npm:0.0.1" + "@napi-rs/wasm-tools-linux-x64-musl": "npm:0.0.1" + "@napi-rs/wasm-tools-wasm32-wasi": "npm:0.0.1" + "@napi-rs/wasm-tools-win32-arm64-msvc": "npm:0.0.1" + "@napi-rs/wasm-tools-win32-ia32-msvc": "npm:0.0.1" + "@napi-rs/wasm-tools-win32-x64-msvc": "npm:0.0.1" + dependenciesMeta: + "@napi-rs/wasm-tools-android-arm-eabi": + optional: true + "@napi-rs/wasm-tools-android-arm64": + optional: true + "@napi-rs/wasm-tools-darwin-arm64": + optional: true + "@napi-rs/wasm-tools-darwin-x64": + optional: true + "@napi-rs/wasm-tools-freebsd-x64": + optional: true + "@napi-rs/wasm-tools-linux-arm64-gnu": + optional: true + "@napi-rs/wasm-tools-linux-arm64-musl": + optional: true + "@napi-rs/wasm-tools-linux-x64-gnu": + optional: true + "@napi-rs/wasm-tools-linux-x64-musl": + optional: true + "@napi-rs/wasm-tools-wasm32-wasi": + optional: true + "@napi-rs/wasm-tools-win32-arm64-msvc": + optional: true + "@napi-rs/wasm-tools-win32-ia32-msvc": + optional: true + "@napi-rs/wasm-tools-win32-x64-msvc": + optional: true + checksum: 10c0/1b57d008db13168378a305cb197acc6e43ff530f8eef98627d1332d4c268a50347e0660a05d7db709106738e20a3c8dc5050063ea8677abb6dd4e939d59d2545 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5"