@napi-rs/cli 3.0.0-alpha.7 → 3.0.0-alpha.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +1 -1
- package/dist/api/artifacts.js +28 -7
- package/dist/api/artifacts.js.map +1 -1
- package/dist/api/build.js +243 -47
- package/dist/api/build.js.map +1 -1
- package/dist/api/create-npm-dirs.js +46 -9
- package/dist/api/create-npm-dirs.js.map +1 -1
- package/dist/api/new.js +57 -20
- package/dist/api/new.js.map +1 -1
- package/dist/api/pre-publish.js +9 -7
- package/dist/api/pre-publish.js.map +1 -1
- package/dist/api/rename.js +9 -1
- package/dist/api/rename.js.map +1 -1
- package/dist/api/templates/cargo.toml.js +1 -0
- package/dist/api/templates/cargo.toml.js.map +1 -1
- package/dist/api/templates/ci-template.d.ts +3 -1
- package/dist/api/templates/ci-template.js +144 -131
- package/dist/api/templates/ci-template.js.map +1 -1
- package/dist/api/templates/ci.yml.d.ts +3 -1
- package/dist/api/templates/ci.yml.js +21 -5
- package/dist/api/templates/ci.yml.js.map +1 -1
- package/dist/api/templates/js-binding.d.ts +1 -0
- package/dist/api/templates/js-binding.js +129 -221
- package/dist/api/templates/js-binding.js.map +1 -1
- package/dist/api/templates/lib.rs.js +1 -4
- package/dist/api/templates/lib.rs.js.map +1 -1
- package/dist/api/templates/load-wasi-template.d.ts +2 -0
- package/dist/api/templates/load-wasi-template.js +166 -0
- package/dist/api/templates/load-wasi-template.js.map +1 -0
- package/dist/api/templates/package.json.d.ts +9 -2
- package/dist/api/templates/package.json.js +26 -4
- package/dist/api/templates/package.json.js.map +1 -1
- package/dist/api/templates/wasi-worker-template.d.ts +2 -0
- package/dist/api/templates/wasi-worker-template.js +122 -0
- package/dist/api/templates/wasi-worker-template.js.map +1 -0
- package/dist/api/universalize.js +5 -5
- package/dist/api/universalize.js.map +1 -1
- package/dist/api/version.js +2 -2
- package/dist/api/version.js.map +1 -1
- package/dist/commands/artifacts.js +2 -2
- package/dist/commands/artifacts.js.map +1 -1
- package/dist/commands/build.js +1 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/new.js +34 -34
- package/dist/commands/new.js.map +1 -1
- package/dist/def/artifacts.d.ts +21 -1
- package/dist/def/artifacts.js +10 -2
- package/dist/def/artifacts.js.map +1 -1
- package/dist/def/build.d.ts +155 -4
- package/dist/def/build.js +30 -4
- package/dist/def/build.js.map +1 -1
- package/dist/def/create-npm-dirs.d.ts +10 -0
- package/dist/def/create-npm-dirs.js +4 -0
- package/dist/def/create-npm-dirs.js.map +1 -1
- package/dist/def/new.d.ts +25 -7
- package/dist/def/new.js +11 -1
- package/dist/def/new.js.map +1 -1
- package/dist/def/pre-publish.d.ts +12 -2
- package/dist/def/pre-publish.js +7 -3
- package/dist/def/pre-publish.js.map +1 -1
- package/dist/def/rename.d.ts +16 -6
- package/dist/def/rename.js +5 -1
- package/dist/def/rename.js.map +1 -1
- package/dist/def/universalize.d.ts +10 -0
- package/dist/def/universalize.js +4 -0
- package/dist/def/universalize.js.map +1 -1
- package/dist/def/version.d.ts +10 -0
- package/dist/def/version.js +4 -0
- package/dist/def/version.js.map +1 -1
- package/dist/index.cjs +8007 -14675
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/__tests__/config.spec.d.ts +1 -0
- package/dist/utils/__tests__/config.spec.js +63 -0
- package/dist/utils/__tests__/config.spec.js.map +1 -0
- package/dist/utils/__tests__/typegen.spec.js +8 -4
- package/dist/utils/__tests__/typegen.spec.js.map +1 -1
- package/dist/utils/cargo.js +2 -2
- package/dist/utils/cargo.js.map +1 -1
- package/dist/utils/config.d.ts +48 -4
- package/dist/utils/config.js +37 -5
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/metadata.js +2 -2
- package/dist/utils/metadata.js.map +1 -1
- package/dist/utils/misc.d.ts +1 -2
- package/dist/utils/misc.js +3 -3
- package/dist/utils/misc.js.map +1 -1
- package/dist/utils/target.d.ts +7 -5
- package/dist/utils/target.js +17 -3
- package/dist/utils/target.js.map +1 -1
- package/dist/utils/typegen.d.ts +1 -1
- package/dist/utils/typegen.js +51 -17
- package/dist/utils/typegen.js.map +1 -1
- package/dist/utils/version.d.ts +2 -1
- package/dist/utils/version.js +10 -8
- package/dist/utils/version.js.map +1 -1
- package/package.json +27 -26
- package/src/api/artifacts.ts +81 -9
- package/src/api/build.ts +398 -66
- package/src/api/create-npm-dirs.ts +57 -9
- package/src/api/new.ts +89 -31
- package/src/api/pre-publish.ts +13 -7
- package/src/api/rename.ts +10 -1
- package/src/api/templates/cargo.toml.ts +1 -0
- package/src/api/templates/ci-template.ts +154 -131
- package/src/api/templates/ci.yml.ts +27 -6
- package/src/api/templates/js-binding.ts +135 -219
- package/src/api/templates/lib.rs.ts +1 -4
- package/src/api/templates/load-wasi-template.ts +180 -0
- package/src/api/templates/package.json.ts +47 -5
- package/src/api/templates/wasi-worker-template.ts +122 -0
- package/src/api/universalize.ts +13 -8
- package/src/api/version.ts +5 -2
- package/src/commands/artifacts.ts +2 -2
- package/src/commands/build.ts +1 -1
- package/src/commands/new.ts +46 -45
- package/src/def/artifacts.ts +22 -3
- package/src/def/build.ts +64 -8
- package/src/def/create-npm-dirs.ts +9 -0
- package/src/def/new.ts +28 -3
- package/src/def/pre-publish.ts +12 -3
- package/src/def/rename.ts +11 -2
- package/src/def/universalize.ts +9 -0
- package/src/def/version.ts +9 -0
- package/src/index.ts +2 -0
- package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
- package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
- package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +28 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +711 -158
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/version.spec.ts.md +8 -7
- package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
- package/src/utils/__tests__/config.spec.ts +81 -0
- package/src/utils/__tests__/typegen.spec.ts +18 -3
- package/src/utils/cargo.ts +2 -2
- package/src/utils/config.ts +112 -10
- package/src/utils/index.ts +0 -1
- package/src/utils/metadata.ts +2 -2
- package/src/utils/misc.ts +11 -3
- package/src/utils/target.ts +22 -4
- package/src/utils/typegen.ts +81 -36
- package/src/utils/version.ts +10 -8
- package/dist/api/load-wasi-template.d.ts +0 -1
- package/dist/api/load-wasi-template.js +0 -63
- package/dist/api/load-wasi-template.js.map +0 -1
- package/dist/api/wasi-worker-template.d.ts +0 -1
- package/dist/api/wasi-worker-template.js +0 -53
- package/dist/api/wasi-worker-template.js.map +0 -1
- package/dist/utils/ci.d.ts +0 -11
- package/dist/utils/ci.js +0 -96
- package/dist/utils/ci.js.map +0 -1
- package/src/api/load-wasi-template.ts +0 -65
- package/src/api/wasi-worker-template.ts +0 -52
- package/src/utils/ci.ts +0 -111
package/src/api/build.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
2
|
import { createHash } from 'node:crypto'
|
|
3
|
+
import { existsSync, mkdirSync, unlinkSync } from 'node:fs'
|
|
3
4
|
import { createRequire } from 'node:module'
|
|
4
|
-
import { tmpdir } from 'node:os'
|
|
5
|
+
import { tmpdir, homedir } from 'node:os'
|
|
5
6
|
import { parse, join, resolve } from 'node:path'
|
|
6
7
|
|
|
7
8
|
import * as colors from 'colorette'
|
|
9
|
+
import { include as setjmpInclude, lib as setjmpLib } from 'wasm-sjlj'
|
|
8
10
|
|
|
9
11
|
import { BuildOptions as RawBuildOptions } from '../def/build.js'
|
|
10
12
|
import {
|
|
@@ -30,9 +32,15 @@ import {
|
|
|
30
32
|
writeFileAsync,
|
|
31
33
|
} from '../utils/index.js'
|
|
32
34
|
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
|
|
35
|
+
import { createCjsBinding, createEsmBinding } from './templates/index.js'
|
|
36
|
+
import {
|
|
37
|
+
createWasiBinding,
|
|
38
|
+
createWasiBrowserBinding,
|
|
39
|
+
} from './templates/load-wasi-template.js'
|
|
40
|
+
import {
|
|
41
|
+
createWasiBrowserWorkerBinding,
|
|
42
|
+
WASI_WORKER_TEMPLATE,
|
|
43
|
+
} from './templates/wasi-worker-template.js'
|
|
36
44
|
|
|
37
45
|
const debug = debugFactory('build')
|
|
38
46
|
const require = createRequire(import.meta.url)
|
|
@@ -81,15 +89,18 @@ export async function buildProject(options: BuildOptions) {
|
|
|
81
89
|
options.target
|
|
82
90
|
? parseTriple(options.target)
|
|
83
91
|
: process.env.CARGO_BUILD_TARGET
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
|
93
|
+
: getSystemDefaultTarget(),
|
|
86
94
|
crateDir,
|
|
87
95
|
resolvePath(options.outputDir ?? crateDir),
|
|
88
96
|
options.targetDir ??
|
|
89
97
|
process.env.CARGO_BUILD_TARGET_DIR ??
|
|
90
98
|
metadata.target_directory,
|
|
91
99
|
await readNapiConfig(
|
|
92
|
-
resolvePath(
|
|
100
|
+
resolvePath(
|
|
101
|
+
options.configPath ?? options.packageJsonPath ?? 'package.json',
|
|
102
|
+
),
|
|
103
|
+
options.configPath ? resolvePath(options.configPath) : undefined,
|
|
93
104
|
),
|
|
94
105
|
)
|
|
95
106
|
|
|
@@ -143,11 +154,138 @@ class Builder {
|
|
|
143
154
|
.setPackage()
|
|
144
155
|
.setFeatures()
|
|
145
156
|
.setTarget()
|
|
157
|
+
.pickCrossToolchain()
|
|
146
158
|
.setEnvs()
|
|
147
159
|
.setBypassArgs()
|
|
148
160
|
.exec()
|
|
149
161
|
}
|
|
150
162
|
|
|
163
|
+
private pickCrossToolchain() {
|
|
164
|
+
if (!this.options.useNapiCross) {
|
|
165
|
+
return this
|
|
166
|
+
}
|
|
167
|
+
if (this.options.useCross) {
|
|
168
|
+
debug.warn(
|
|
169
|
+
'You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.',
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (this.options.crossCompile) {
|
|
174
|
+
debug.warn(
|
|
175
|
+
'You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.',
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const { version, download } = require('@napi-rs/cross-toolchain')
|
|
181
|
+
|
|
182
|
+
const alias: Record<string, string> = {
|
|
183
|
+
's390x-unknown-linux-gnu': 's390x-ibm-linux-gnu',
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const toolchainPath = join(
|
|
187
|
+
homedir(),
|
|
188
|
+
'.napi-rs',
|
|
189
|
+
'cross-toolchain',
|
|
190
|
+
version,
|
|
191
|
+
this.target.triple,
|
|
192
|
+
)
|
|
193
|
+
mkdirSync(toolchainPath, { recursive: true })
|
|
194
|
+
if (existsSync(join(toolchainPath, 'package.json'))) {
|
|
195
|
+
debug(`Toolchain ${toolchainPath} exists, skip extracting`)
|
|
196
|
+
} else {
|
|
197
|
+
const tarArchive = download(process.arch, this.target.triple)
|
|
198
|
+
tarArchive.unpack(toolchainPath)
|
|
199
|
+
}
|
|
200
|
+
const upperCaseTarget = targetToEnvVar(this.target.triple)
|
|
201
|
+
const crossTargetName = alias[this.target.triple] ?? this.target.triple
|
|
202
|
+
const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`
|
|
203
|
+
this.envs[linkerEnv] = join(
|
|
204
|
+
toolchainPath,
|
|
205
|
+
'bin',
|
|
206
|
+
`${crossTargetName}-gcc`,
|
|
207
|
+
)
|
|
208
|
+
if (!process.env.TARGET_SYSROOT) {
|
|
209
|
+
this.envs[`TARGET_SYSROOT`] = join(
|
|
210
|
+
toolchainPath,
|
|
211
|
+
crossTargetName,
|
|
212
|
+
'sysroot',
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
if (!process.env.TARGET_AR) {
|
|
216
|
+
this.envs[`TARGET_AR`] = join(
|
|
217
|
+
toolchainPath,
|
|
218
|
+
'bin',
|
|
219
|
+
`${crossTargetName}-ar`,
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
if (!process.env.TARGET_RANLIB) {
|
|
223
|
+
this.envs[`TARGET_RANLIB`] = join(
|
|
224
|
+
toolchainPath,
|
|
225
|
+
'bin',
|
|
226
|
+
`${crossTargetName}-ranlib`,
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
if (!process.env.TARGET_READELF) {
|
|
230
|
+
this.envs[`TARGET_READELF`] = join(
|
|
231
|
+
toolchainPath,
|
|
232
|
+
'bin',
|
|
233
|
+
`${crossTargetName}-readelf`,
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
if (!process.env.TARGET_C_INCLUDE_PATH) {
|
|
237
|
+
this.envs[`TARGET_C_INCLUDE_PATH`] = join(
|
|
238
|
+
toolchainPath,
|
|
239
|
+
crossTargetName,
|
|
240
|
+
'sysroot',
|
|
241
|
+
'usr',
|
|
242
|
+
'include/',
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
if (!process.env.CC && !process.env.TARGET_CC) {
|
|
246
|
+
this.envs[`CC`] = join(toolchainPath, 'bin', `${crossTargetName}-gcc`)
|
|
247
|
+
this.envs[`TARGET_CC`] = join(
|
|
248
|
+
toolchainPath,
|
|
249
|
+
'bin',
|
|
250
|
+
`${crossTargetName}-gcc`,
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
if (!process.env.CXX && !process.env.TARGET_CXX) {
|
|
254
|
+
this.envs[`CXX`] = join(
|
|
255
|
+
toolchainPath,
|
|
256
|
+
'bin',
|
|
257
|
+
`${this.target.triple}-g++`,
|
|
258
|
+
)
|
|
259
|
+
this.envs[`TARGET_CXX`] = join(
|
|
260
|
+
toolchainPath,
|
|
261
|
+
'bin',
|
|
262
|
+
`${this.target.triple}-g++`,
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
if (
|
|
266
|
+
(process.env.CC === 'clang' &&
|
|
267
|
+
(process.env.TARGET_CC === 'clang' || !process.env.TARGET_CC)) ||
|
|
268
|
+
process.env.TARGET_CC === 'clang'
|
|
269
|
+
) {
|
|
270
|
+
this.envs.CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath}`
|
|
271
|
+
}
|
|
272
|
+
if (
|
|
273
|
+
(process.env.CXX === 'clang++' &&
|
|
274
|
+
(process.env.TARGET_CXX === 'clang++' || !process.env.TARGET_CXX)) ||
|
|
275
|
+
process.env.TARGET_CXX === 'clang++'
|
|
276
|
+
) {
|
|
277
|
+
this.envs.CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath}`
|
|
278
|
+
}
|
|
279
|
+
this.envs.PATH = this.envs.PATH
|
|
280
|
+
? `${toolchainPath}/bin:${this.envs.PATH}:${process.env.PATH}`
|
|
281
|
+
: `${toolchainPath}/bin:${process.env.PATH}`
|
|
282
|
+
} catch (e) {
|
|
283
|
+
debug.warn('Pick cross toolchain failed', e as Error)
|
|
284
|
+
// ignore, do nothing
|
|
285
|
+
}
|
|
286
|
+
return this
|
|
287
|
+
}
|
|
288
|
+
|
|
151
289
|
private exec() {
|
|
152
290
|
debug(`Start building crate: ${this.crate.name}`)
|
|
153
291
|
debug(' %i', `cargo ${this.args.join(' ')}`)
|
|
@@ -156,6 +294,11 @@ class Builder {
|
|
|
156
294
|
|
|
157
295
|
const watch = this.options.watch
|
|
158
296
|
const buildTask = new Promise<void>((resolve, reject) => {
|
|
297
|
+
if (this.options.useCross && this.options.crossCompile) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
'`--use-cross` and `--cross-compile` can not be used together',
|
|
300
|
+
)
|
|
301
|
+
}
|
|
159
302
|
const command =
|
|
160
303
|
process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
|
|
161
304
|
const buildProcess = spawn(command, this.args, {
|
|
@@ -189,7 +332,7 @@ class Builder {
|
|
|
189
332
|
buildProcess.stderr?.on('data', (data) => {
|
|
190
333
|
const output = data.toString()
|
|
191
334
|
console.error(output)
|
|
192
|
-
if (/Finished\s(dev
|
|
335
|
+
if (/Finished\s(`dev`|`release`)/.test(output)) {
|
|
193
336
|
this.postBuild().catch(() => {})
|
|
194
337
|
}
|
|
195
338
|
})
|
|
@@ -352,7 +495,7 @@ class Builder {
|
|
|
352
495
|
const linkerEnv = `CARGO_TARGET_${targetToEnvVar(
|
|
353
496
|
this.target.triple,
|
|
354
497
|
)}_LINKER`
|
|
355
|
-
if (linker && !process.env[linkerEnv]) {
|
|
498
|
+
if (linker && !process.env[linkerEnv] && !this.envs[linkerEnv]) {
|
|
356
499
|
this.envs[linkerEnv] = linker
|
|
357
500
|
}
|
|
358
501
|
|
|
@@ -373,15 +516,15 @@ class Builder {
|
|
|
373
516
|
process.platform === 'darwin'
|
|
374
517
|
? 'darwin'
|
|
375
518
|
: process.platform === 'win32'
|
|
376
|
-
|
|
377
|
-
|
|
519
|
+
? 'windows'
|
|
520
|
+
: 'linux'
|
|
378
521
|
Object.assign(this.envs, {
|
|
379
522
|
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
380
523
|
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
524
|
+
TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
525
|
+
TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
526
|
+
TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
527
|
+
TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
385
528
|
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
386
529
|
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
|
|
387
530
|
})
|
|
@@ -396,6 +539,47 @@ class Builder {
|
|
|
396
539
|
'wasm32-wasi-threads',
|
|
397
540
|
)
|
|
398
541
|
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
542
|
+
this.envs.SETJMP_LINK_DIR = setjmpLib
|
|
543
|
+
const { WASI_SDK_PATH } = process.env
|
|
544
|
+
|
|
545
|
+
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
546
|
+
this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
|
|
547
|
+
WASI_SDK_PATH,
|
|
548
|
+
'bin',
|
|
549
|
+
'wasm-ld',
|
|
550
|
+
)
|
|
551
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
|
|
552
|
+
WASI_SDK_PATH,
|
|
553
|
+
'bin',
|
|
554
|
+
'wasm-ld',
|
|
555
|
+
)
|
|
556
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
|
|
557
|
+
WASI_SDK_PATH,
|
|
558
|
+
'bin',
|
|
559
|
+
'wasm-ld',
|
|
560
|
+
)
|
|
561
|
+
this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
|
|
562
|
+
WASI_SDK_PATH,
|
|
563
|
+
'bin',
|
|
564
|
+
'wasm-ld',
|
|
565
|
+
)
|
|
566
|
+
this.setEnvIfNotExists('CC', join(WASI_SDK_PATH, 'bin', 'clang'))
|
|
567
|
+
this.setEnvIfNotExists('CXX', join(WASI_SDK_PATH, 'bin', 'clang++'))
|
|
568
|
+
this.setEnvIfNotExists('AR', join(WASI_SDK_PATH, 'bin', 'ar'))
|
|
569
|
+
this.setEnvIfNotExists('RANLIB', join(WASI_SDK_PATH, 'bin', 'ranlib'))
|
|
570
|
+
this.setEnvIfNotExists(
|
|
571
|
+
'CFLAGS',
|
|
572
|
+
`--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
|
|
573
|
+
)
|
|
574
|
+
this.setEnvIfNotExists(
|
|
575
|
+
'CXXFLAGS',
|
|
576
|
+
`--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
|
|
577
|
+
)
|
|
578
|
+
this.setEnvIfNotExists(
|
|
579
|
+
`LDFLAGS`,
|
|
580
|
+
`-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
|
|
581
|
+
)
|
|
582
|
+
}
|
|
399
583
|
}
|
|
400
584
|
|
|
401
585
|
debug('Set envs: ')
|
|
@@ -408,11 +592,17 @@ class Builder {
|
|
|
408
592
|
|
|
409
593
|
private setFeatures() {
|
|
410
594
|
const args = []
|
|
595
|
+
if (this.options.allFeatures && this.options.noDefaultFeatures) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
'Cannot specify --all-features and --no-default-features together',
|
|
598
|
+
)
|
|
599
|
+
}
|
|
411
600
|
if (this.options.allFeatures) {
|
|
412
601
|
args.push('--all-features')
|
|
413
602
|
} else if (this.options.noDefaultFeatures) {
|
|
414
603
|
args.push('--no-default-features')
|
|
415
|
-
}
|
|
604
|
+
}
|
|
605
|
+
if (this.options.features) {
|
|
416
606
|
args.push('--features', ...this.options.features)
|
|
417
607
|
}
|
|
418
608
|
|
|
@@ -440,6 +630,10 @@ class Builder {
|
|
|
440
630
|
this.args.push('--profile', this.options.profile)
|
|
441
631
|
}
|
|
442
632
|
|
|
633
|
+
if (this.options.manifestPath) {
|
|
634
|
+
this.args.push('--manifest-path', this.options.manifestPath)
|
|
635
|
+
}
|
|
636
|
+
|
|
443
637
|
if (this.options.cargoOptions?.length) {
|
|
444
638
|
this.args.push(...this.options.cargoOptions)
|
|
445
639
|
}
|
|
@@ -448,14 +642,21 @@ class Builder {
|
|
|
448
642
|
}
|
|
449
643
|
|
|
450
644
|
private getIntermediateTypeFile() {
|
|
451
|
-
|
|
645
|
+
const dtsPath = join(
|
|
452
646
|
tmpdir(),
|
|
453
647
|
`${this.crate.name}-${createHash('sha256')
|
|
454
648
|
.update(this.crate.manifest_path)
|
|
455
649
|
.update(CLI_VERSION)
|
|
456
650
|
.digest('hex')
|
|
457
|
-
.substring(0, 8)}.napi_type_def
|
|
651
|
+
.substring(0, 8)}.napi_type_def`,
|
|
458
652
|
)
|
|
653
|
+
if (!this.options.dtsCache) {
|
|
654
|
+
try {
|
|
655
|
+
unlinkSync(dtsPath)
|
|
656
|
+
} catch {}
|
|
657
|
+
return `${dtsPath}_${Date.now()}.tmp`
|
|
658
|
+
}
|
|
659
|
+
return `${dtsPath}.tmp`
|
|
459
660
|
}
|
|
460
661
|
|
|
461
662
|
private getIntermediateWasiRegisterFile() {
|
|
@@ -481,38 +682,48 @@ class Builder {
|
|
|
481
682
|
})
|
|
482
683
|
}
|
|
483
684
|
|
|
484
|
-
const
|
|
685
|
+
const wasmBinaryName = await this.copyArtifact()
|
|
485
686
|
|
|
486
687
|
// only for cdylib
|
|
487
688
|
if (this.cdyLibName) {
|
|
488
689
|
const idents = await this.generateTypeDef()
|
|
489
690
|
const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH
|
|
490
|
-
const wasiRegisterFunctions =
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
},
|
|
502
|
-
)
|
|
503
|
-
|
|
504
|
-
|
|
691
|
+
const wasiRegisterFunctions = this.config.targets.some(
|
|
692
|
+
(t) => t.platform === 'wasi',
|
|
693
|
+
)
|
|
694
|
+
? await (async function readIntermediateWasiRegisterFile() {
|
|
695
|
+
const fileContent = await readFileAsync(
|
|
696
|
+
intermediateWasiRegisterFile,
|
|
697
|
+
'utf8',
|
|
698
|
+
).catch((err) => {
|
|
699
|
+
console.warn(
|
|
700
|
+
`Read ${colors.yellowBright(
|
|
701
|
+
intermediateWasiRegisterFile,
|
|
702
|
+
)} failed, reason: ${err.message}`,
|
|
703
|
+
)
|
|
704
|
+
return ``
|
|
705
|
+
})
|
|
706
|
+
return fileContent
|
|
707
|
+
.split('\n')
|
|
708
|
+
.map((l) => l.trim())
|
|
709
|
+
.filter((l) => l.length)
|
|
710
|
+
.map((line) => {
|
|
711
|
+
const [_, fn] = line.split(':')
|
|
712
|
+
return fn.trim()
|
|
713
|
+
})
|
|
714
|
+
})()
|
|
715
|
+
: []
|
|
505
716
|
const jsOutput = await this.writeJsBinding(idents)
|
|
506
|
-
const
|
|
717
|
+
const wasmBindingsOutput = await this.writeWasiBinding(
|
|
507
718
|
wasiRegisterFunctions,
|
|
508
|
-
|
|
719
|
+
wasmBinaryName ?? 'index.wasm',
|
|
509
720
|
idents,
|
|
510
721
|
)
|
|
511
722
|
if (jsOutput) {
|
|
512
723
|
this.outputs.push(jsOutput)
|
|
513
724
|
}
|
|
514
|
-
if (
|
|
515
|
-
this.outputs.push(
|
|
725
|
+
if (wasmBindingsOutput) {
|
|
726
|
+
this.outputs.push(...wasmBindingsOutput)
|
|
516
727
|
}
|
|
517
728
|
}
|
|
518
729
|
|
|
@@ -520,7 +731,7 @@ class Builder {
|
|
|
520
731
|
}
|
|
521
732
|
|
|
522
733
|
private async copyArtifact() {
|
|
523
|
-
const [srcName, destName] = this.getArtifactNames()
|
|
734
|
+
const [srcName, destName, wasmBinaryName] = this.getArtifactNames()
|
|
524
735
|
if (!srcName || !destName) {
|
|
525
736
|
return
|
|
526
737
|
}
|
|
@@ -530,6 +741,7 @@ class Builder {
|
|
|
530
741
|
const src = join(this.targetDir, this.target.triple, profile, srcName)
|
|
531
742
|
debug(`Copy artifact from: [${src}]`)
|
|
532
743
|
const dest = join(this.outputDir, destName)
|
|
744
|
+
const isWasm = dest.endsWith('.wasm')
|
|
533
745
|
|
|
534
746
|
try {
|
|
535
747
|
if (await fileExists(dest)) {
|
|
@@ -538,12 +750,47 @@ class Builder {
|
|
|
538
750
|
}
|
|
539
751
|
debug('Copy artifact to:')
|
|
540
752
|
debug(' %i', dest)
|
|
541
|
-
|
|
753
|
+
if (isWasm) {
|
|
754
|
+
const { ModuleConfig } = await import('@napi-rs/wasm-tools')
|
|
755
|
+
debug('Generate debug wasm module')
|
|
756
|
+
try {
|
|
757
|
+
const debugWasmModule = new ModuleConfig()
|
|
758
|
+
.generateDwarf(true)
|
|
759
|
+
.generateNameSection(true)
|
|
760
|
+
.generateProducersSection(true)
|
|
761
|
+
.preserveCodeTransform(true)
|
|
762
|
+
.strictValidate(false)
|
|
763
|
+
.parse(await readFileAsync(src))
|
|
764
|
+
const debugWasmBinary = debugWasmModule.emitWasm(true)
|
|
765
|
+
await writeFileAsync(
|
|
766
|
+
dest.replace('.wasm', '.debug.wasm'),
|
|
767
|
+
debugWasmBinary,
|
|
768
|
+
)
|
|
769
|
+
debug('Generate release wasm module')
|
|
770
|
+
const releaseWasmModule = new ModuleConfig()
|
|
771
|
+
.generateDwarf(false)
|
|
772
|
+
.generateNameSection(false)
|
|
773
|
+
.generateProducersSection(false)
|
|
774
|
+
.preserveCodeTransform(false)
|
|
775
|
+
.strictValidate(false)
|
|
776
|
+
.onlyStableFeatures(false)
|
|
777
|
+
.parse(debugWasmBinary)
|
|
778
|
+
const releaseWasmBinary = releaseWasmModule.emitWasm(false)
|
|
779
|
+
await writeFileAsync(dest, releaseWasmBinary)
|
|
780
|
+
} catch (e) {
|
|
781
|
+
debug.warn(
|
|
782
|
+
`Failed to generate debug wasm module: ${(e as any).message ?? e}`,
|
|
783
|
+
)
|
|
784
|
+
await copyFileAsync(src, dest)
|
|
785
|
+
}
|
|
786
|
+
} else {
|
|
787
|
+
await copyFileAsync(src, dest)
|
|
788
|
+
}
|
|
542
789
|
this.outputs.push({
|
|
543
|
-
kind: dest.endsWith('.node') ? 'node' : 'exe',
|
|
790
|
+
kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe',
|
|
544
791
|
path: dest,
|
|
545
792
|
})
|
|
546
|
-
return
|
|
793
|
+
return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null
|
|
547
794
|
} catch (e) {
|
|
548
795
|
throw new Error('Failed to copy artifact', {
|
|
549
796
|
cause: e,
|
|
@@ -554,15 +801,16 @@ class Builder {
|
|
|
554
801
|
private getArtifactNames() {
|
|
555
802
|
if (this.cdyLibName) {
|
|
556
803
|
const cdyLib = this.cdyLibName.replace(/-/g, '_')
|
|
804
|
+
const wasiTarget = this.config.targets.find((t) => t.platform === 'wasi')
|
|
557
805
|
|
|
558
806
|
const srcName =
|
|
559
807
|
this.target.platform === 'darwin'
|
|
560
808
|
? `lib${cdyLib}.dylib`
|
|
561
809
|
: this.target.platform === 'win32'
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
810
|
+
? `${cdyLib}.dll`
|
|
811
|
+
: this.target.platform === 'wasi' || this.target.platform === 'wasm'
|
|
812
|
+
? `${cdyLib}.wasm`
|
|
813
|
+
: `lib${cdyLib}.so`
|
|
566
814
|
|
|
567
815
|
let destName = this.config.binaryName
|
|
568
816
|
// add platform suffix to binary name
|
|
@@ -572,12 +820,18 @@ class Builder {
|
|
|
572
820
|
destName += `.${this.target.platformArchABI}`
|
|
573
821
|
}
|
|
574
822
|
if (srcName.endsWith('.wasm')) {
|
|
575
|
-
destName += '.
|
|
823
|
+
destName += '.wasm'
|
|
576
824
|
} else {
|
|
577
825
|
destName += '.node'
|
|
578
826
|
}
|
|
579
827
|
|
|
580
|
-
return [
|
|
828
|
+
return [
|
|
829
|
+
srcName,
|
|
830
|
+
destName,
|
|
831
|
+
wasiTarget
|
|
832
|
+
? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm`
|
|
833
|
+
: null,
|
|
834
|
+
]
|
|
581
835
|
} else if (this.binName) {
|
|
582
836
|
const srcName =
|
|
583
837
|
this.target.platform === 'win32' ? `${this.binName}.exe` : this.binName
|
|
@@ -597,8 +851,22 @@ class Builder {
|
|
|
597
851
|
|
|
598
852
|
const { dts, exports } = await processTypeDef(
|
|
599
853
|
this.envs.TYPE_DEF_TMP_PATH,
|
|
854
|
+
this.options.constEnum ?? this.config.constEnum ?? true,
|
|
600
855
|
!this.options.noDtsHeader
|
|
601
|
-
? this.options.dtsHeader ??
|
|
856
|
+
? (this.options.dtsHeader ??
|
|
857
|
+
(this.config.dtsHeaderFile
|
|
858
|
+
? await readFileAsync(
|
|
859
|
+
join(this.cwd, this.config.dtsHeaderFile),
|
|
860
|
+
'utf-8',
|
|
861
|
+
).catch(() => {
|
|
862
|
+
debug.warn(
|
|
863
|
+
`Failed to read dts header file ${this.config.dtsHeaderFile}`,
|
|
864
|
+
)
|
|
865
|
+
return null
|
|
866
|
+
})
|
|
867
|
+
: null) ??
|
|
868
|
+
this.config.dtsHeader ??
|
|
869
|
+
DEFAULT_TYPE_DEF_HEADER)
|
|
602
870
|
: '',
|
|
603
871
|
)
|
|
604
872
|
|
|
@@ -628,19 +896,20 @@ class Builder {
|
|
|
628
896
|
return
|
|
629
897
|
}
|
|
630
898
|
|
|
631
|
-
const name =
|
|
899
|
+
const name = this.options.jsBinding ?? 'index.js'
|
|
632
900
|
|
|
633
|
-
const
|
|
901
|
+
const createBinding = this.options.esm ? createEsmBinding : createCjsBinding
|
|
902
|
+
const binding = createBinding(
|
|
634
903
|
this.config.binaryName,
|
|
635
904
|
this.config.packageName,
|
|
636
905
|
idents,
|
|
637
906
|
)
|
|
638
907
|
|
|
639
908
|
try {
|
|
640
|
-
const dest = join(this.outputDir,
|
|
909
|
+
const dest = join(this.outputDir, name)
|
|
641
910
|
debug('Writing js binding to:')
|
|
642
911
|
debug(' %i', dest)
|
|
643
|
-
await writeFileAsync(dest,
|
|
912
|
+
await writeFileAsync(dest, binding, 'utf-8')
|
|
644
913
|
return {
|
|
645
914
|
kind: 'js',
|
|
646
915
|
path: dest,
|
|
@@ -657,26 +926,89 @@ class Builder {
|
|
|
657
926
|
) {
|
|
658
927
|
if (distFileName && wasiRegisterFunctions.length) {
|
|
659
928
|
const { name, dir } = parse(distFileName)
|
|
660
|
-
const
|
|
929
|
+
const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`)
|
|
930
|
+
const browserBindingPath = join(
|
|
931
|
+
dir,
|
|
932
|
+
`${this.config.binaryName}.wasi-browser.js`,
|
|
933
|
+
)
|
|
661
934
|
const workerPath = join(dir, 'wasi-worker.mjs')
|
|
662
|
-
const
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
.
|
|
935
|
+
const browserWorkerPath = join(dir, 'wasi-worker-browser.mjs')
|
|
936
|
+
const browserEntryPath = join(dir, 'browser.js')
|
|
937
|
+
const exportsCode = idents
|
|
938
|
+
.map(
|
|
939
|
+
(ident) => `module.exports.${ident} = __napiModule.exports.${ident}`,
|
|
940
|
+
)
|
|
941
|
+
.join('\n')
|
|
666
942
|
await writeFileAsync(
|
|
667
|
-
|
|
668
|
-
createWasiBinding(
|
|
669
|
-
|
|
943
|
+
bindingPath,
|
|
944
|
+
createWasiBinding(
|
|
945
|
+
name,
|
|
946
|
+
this.config.packageName,
|
|
947
|
+
wasiRegisterFunctions,
|
|
948
|
+
this.config.wasm?.initialMemory,
|
|
949
|
+
this.config.wasm?.maximumMemory,
|
|
950
|
+
) +
|
|
670
951
|
exportsCode +
|
|
671
952
|
'\n',
|
|
672
953
|
'utf8',
|
|
673
954
|
)
|
|
955
|
+
await writeFileAsync(
|
|
956
|
+
browserBindingPath,
|
|
957
|
+
createWasiBrowserBinding(
|
|
958
|
+
name,
|
|
959
|
+
wasiRegisterFunctions,
|
|
960
|
+
this.config.wasm?.initialMemory,
|
|
961
|
+
this.config.wasm?.maximumMemory,
|
|
962
|
+
this.config.wasm?.browser?.fs,
|
|
963
|
+
) +
|
|
964
|
+
idents
|
|
965
|
+
.map(
|
|
966
|
+
(ident) =>
|
|
967
|
+
`export const ${ident} = __napiModule.exports.${ident}`,
|
|
968
|
+
)
|
|
969
|
+
.join('\n') +
|
|
970
|
+
'\n',
|
|
971
|
+
'utf8',
|
|
972
|
+
)
|
|
674
973
|
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
974
|
+
await writeFileAsync(
|
|
975
|
+
browserWorkerPath,
|
|
976
|
+
createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false),
|
|
977
|
+
'utf8',
|
|
978
|
+
)
|
|
979
|
+
await writeFileAsync(
|
|
980
|
+
browserEntryPath,
|
|
981
|
+
`export * from '${this.config.packageName}-wasm32-wasi'\n`,
|
|
982
|
+
)
|
|
983
|
+
return [
|
|
984
|
+
{
|
|
985
|
+
kind: 'js',
|
|
986
|
+
path: bindingPath,
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
kind: 'js',
|
|
990
|
+
path: browserBindingPath,
|
|
991
|
+
},
|
|
992
|
+
{
|
|
993
|
+
kind: 'js',
|
|
994
|
+
path: workerPath,
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
kind: 'js',
|
|
998
|
+
path: browserWorkerPath,
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
kind: 'js',
|
|
1002
|
+
path: browserEntryPath,
|
|
1003
|
+
},
|
|
1004
|
+
] satisfies Output[]
|
|
1005
|
+
}
|
|
1006
|
+
return []
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
private setEnvIfNotExists(env: string, value: string) {
|
|
1010
|
+
if (!process.env[env]) {
|
|
1011
|
+
this.envs[env] = value
|
|
679
1012
|
}
|
|
680
|
-
return null
|
|
681
1013
|
}
|
|
682
1014
|
}
|