@napi-rs/cli 3.0.0-alpha.1 → 3.0.0-alpha.11
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/dist/api/artifacts.js +5 -2
- package/dist/api/artifacts.js.map +1 -0
- package/dist/api/build.d.ts +1 -1
- package/dist/api/build.js +185 -35
- package/dist/api/build.js.map +1 -0
- package/dist/api/create-npm-dirs.js +1 -0
- package/dist/api/create-npm-dirs.js.map +1 -0
- package/dist/api/load-wasi-template.d.ts +1 -0
- package/dist/api/load-wasi-template.js +60 -0
- package/dist/api/load-wasi-template.js.map +1 -0
- package/dist/api/new.js +31 -12
- package/dist/api/new.js.map +1 -0
- package/dist/api/pre-publish.js +1 -0
- package/dist/api/pre-publish.js.map +1 -0
- package/dist/api/rename.js +1 -0
- package/dist/api/rename.js.map +1 -0
- package/dist/api/templates/.gitignore.d.ts +1 -1
- package/dist/api/templates/.gitignore.js +2 -0
- package/dist/api/templates/.gitignore.js.map +1 -0
- package/dist/api/templates/.npmignore.js +1 -0
- package/dist/api/templates/.npmignore.js.map +1 -0
- package/dist/api/templates/build.rs.js +1 -0
- package/dist/api/templates/build.rs.js.map +1 -0
- package/dist/api/templates/cargo.toml.js +1 -0
- package/dist/api/templates/cargo.toml.js.map +1 -0
- package/dist/api/templates/ci-template.js +64 -57
- package/dist/api/templates/ci-template.js.map +1 -0
- package/dist/api/templates/ci.yml.d.ts +1 -1
- package/dist/api/templates/ci.yml.js +10 -3
- package/dist/api/templates/ci.yml.js.map +1 -0
- package/dist/api/templates/index.js +1 -0
- package/dist/api/templates/index.js.map +1 -0
- package/dist/api/templates/js-binding.d.ts +1 -1
- package/dist/api/templates/js-binding.js +278 -109
- package/dist/api/templates/js-binding.js.map +1 -0
- package/dist/api/templates/lib.rs.js +2 -4
- package/dist/api/templates/lib.rs.js.map +1 -0
- package/dist/api/templates/package.json.js +30 -28
- package/dist/api/templates/package.json.js.map +1 -0
- package/dist/api/universalize.js +1 -0
- package/dist/api/universalize.js.map +1 -0
- package/dist/api/version.js +1 -0
- package/dist/api/version.js.map +1 -0
- package/dist/api/wasi-worker-template.d.ts +1 -0
- package/dist/api/wasi-worker-template.js +53 -0
- package/dist/api/wasi-worker-template.js.map +1 -0
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/artifacts.js +1 -0
- package/dist/commands/artifacts.js.map +1 -0
- package/dist/commands/build.js +1 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/create-npm-dirs.js +1 -0
- package/dist/commands/create-npm-dirs.js.map +1 -0
- package/dist/commands/help.js +1 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/new.js +2 -4
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/pre-publish.js +1 -0
- package/dist/commands/pre-publish.js.map +1 -0
- package/dist/commands/rename.js +1 -0
- package/dist/commands/rename.js.map +1 -0
- package/dist/commands/universalize.js +1 -0
- package/dist/commands/universalize.js.map +1 -0
- package/dist/commands/version.js +1 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/def/artifacts.js +1 -0
- package/dist/def/artifacts.js.map +1 -0
- package/dist/def/build.d.ts +24 -0
- package/dist/def/build.js +17 -0
- package/dist/def/build.js.map +1 -0
- package/dist/def/create-npm-dirs.js +1 -0
- package/dist/def/create-npm-dirs.js.map +1 -0
- package/dist/def/new.js +1 -0
- package/dist/def/new.js.map +1 -0
- package/dist/def/pre-publish.js +1 -0
- package/dist/def/pre-publish.js.map +1 -0
- package/dist/def/rename.js +1 -0
- package/dist/def/rename.js.map +1 -0
- package/dist/def/universalize.js +1 -0
- package/dist/def/universalize.js.map +1 -0
- package/dist/def/version.js +1 -0
- package/dist/def/version.js.map +1 -0
- package/dist/index.cjs +3307 -8030
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/__tests__/target.spec.js +1 -0
- package/dist/utils/__tests__/target.spec.js.map +1 -0
- package/dist/utils/__tests__/typegen.spec.js +9 -4
- package/dist/utils/__tests__/typegen.spec.js.map +1 -0
- package/dist/utils/__tests__/version.spec.js +1 -0
- package/dist/utils/__tests__/version.spec.js.map +1 -0
- package/dist/utils/cargo.js +1 -0
- package/dist/utils/cargo.js.map +1 -0
- package/dist/utils/ci.js +10 -0
- package/dist/utils/ci.js.map +1 -0
- package/dist/utils/config.d.ts +14 -2
- package/dist/utils/config.js +4 -3
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/log.js +1 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/metadata.js +1 -0
- package/dist/utils/metadata.js.map +1 -0
- package/dist/utils/misc.js +7 -1
- package/dist/utils/misc.js.map +1 -0
- package/dist/utils/target.d.ts +6 -5
- package/dist/utils/target.js +15 -3
- package/dist/utils/target.js.map +1 -0
- package/dist/utils/typegen.d.ts +4 -1
- package/dist/utils/typegen.js +27 -6
- package/dist/utils/typegen.js.map +1 -0
- package/dist/utils/version.js +3 -2
- package/dist/utils/version.js.map +1 -0
- package/package.json +48 -15
- package/src/api/artifacts.ts +7 -4
- package/src/api/build.ts +278 -44
- package/src/api/load-wasi-template.ts +62 -0
- package/src/api/new.ts +37 -14
- package/src/api/pre-publish.ts +8 -5
- package/src/api/templates/.gitignore.ts +1 -0
- package/src/api/templates/ci-template.ts +63 -57
- package/src/api/templates/ci.yml.ts +9 -6
- package/src/api/templates/js-binding.ts +270 -104
- package/src/api/templates/lib.rs.ts +1 -4
- package/src/api/templates/package.json.ts +31 -27
- package/src/api/wasi-worker-template.ts +52 -0
- package/src/commands/new.ts +1 -5
- package/src/def/build.ts +38 -0
- package/src/index.ts +2 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +7 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +555 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/version.spec.ts.md +7 -7
- package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
- package/src/utils/__tests__/typegen.spec.ts +19 -4
- package/src/utils/ci.ts +9 -0
- package/src/utils/config.ts +21 -5
- package/src/utils/misc.ts +6 -1
- package/src/utils/target.ts +22 -10
- package/src/utils/typegen.ts +30 -5
- package/src/utils/version.ts +1 -1
- package/dist/def/commands/artifacts.d.ts +0 -15
- package/dist/def/commands/artifacts.js +0 -29
- package/dist/def/commands/build.d.ts +0 -53
- package/dist/def/commands/build.js +0 -105
- package/dist/def/commands/create-npm-dirs.d.ts +0 -15
- package/dist/def/commands/create-npm-dirs.js +0 -29
- package/dist/def/commands/new.d.ts +0 -27
- package/dist/def/commands/new.js +0 -53
- package/dist/def/commands/pre-publish.d.ts +0 -23
- package/dist/def/commands/pre-publish.js +0 -45
- package/dist/def/commands/rename.d.ts +0 -25
- package/dist/def/commands/rename.js +0 -49
- package/dist/def/commands/universalize.d.ts +0 -13
- package/dist/def/commands/universalize.js +0 -25
- package/dist/def/commands/version.d.ts +0 -13
- package/dist/def/commands/version.js +0 -25
- package/dist/def/options/artifacts.d.ts +0 -35
- package/dist/def/options/artifacts.js +0 -11
- package/dist/def/options/build.d.ts +0 -97
- package/dist/def/options/build.js +0 -3
- package/dist/def/options/create-npm-dirs.d.ts +0 -35
- package/dist/def/options/create-npm-dirs.js +0 -11
- package/dist/def/options/new.d.ts +0 -79
- package/dist/def/options/new.js +0 -15
- package/dist/def/options/pre-publish.d.ts +0 -65
- package/dist/def/options/pre-publish.js +0 -13
- package/dist/def/options/rename.d.ts +0 -75
- package/dist/def/options/rename.js +0 -11
- package/dist/def/options/universalize.d.ts +0 -28
- package/dist/def/options/universalize.js +0 -10
- package/dist/def/options/version.d.ts +0 -28
- package/dist/def/options/version.js +0 -10
package/src/api/build.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { spawn } from 'child_process'
|
|
2
|
-
import { createHash } from 'crypto'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import { existsSync, mkdirSync } from 'node:fs'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { tmpdir, homedir } from 'node:os'
|
|
6
|
+
import { parse, join, resolve } from 'node:path'
|
|
5
7
|
|
|
6
8
|
import * as colors from 'colorette'
|
|
7
9
|
|
|
@@ -20,6 +22,7 @@ import {
|
|
|
20
22
|
parseMetadata,
|
|
21
23
|
parseTriple,
|
|
22
24
|
processTypeDef,
|
|
25
|
+
readFileAsync,
|
|
23
26
|
readNapiConfig,
|
|
24
27
|
Target,
|
|
25
28
|
targetToEnvVar,
|
|
@@ -28,11 +31,14 @@ import {
|
|
|
28
31
|
writeFileAsync,
|
|
29
32
|
} from '../utils/index.js'
|
|
30
33
|
|
|
31
|
-
import {
|
|
34
|
+
import { createWasiBinding } from './load-wasi-template.js'
|
|
35
|
+
import { createCjsBinding } from './templates/index.js'
|
|
36
|
+
import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.js'
|
|
32
37
|
|
|
33
38
|
const debug = debugFactory('build')
|
|
39
|
+
const require = createRequire(import.meta.url)
|
|
34
40
|
|
|
35
|
-
type OutputKind = 'js' | 'dts' | 'node' | 'exe'
|
|
41
|
+
type OutputKind = 'js' | 'dts' | 'node' | 'exe' | 'wasm'
|
|
36
42
|
type Output = {
|
|
37
43
|
kind: OutputKind
|
|
38
44
|
path: string
|
|
@@ -76,8 +82,8 @@ export async function buildProject(options: BuildOptions) {
|
|
|
76
82
|
options.target
|
|
77
83
|
? parseTriple(options.target)
|
|
78
84
|
: process.env.CARGO_BUILD_TARGET
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
|
86
|
+
: getSystemDefaultTarget(),
|
|
81
87
|
crateDir,
|
|
82
88
|
resolvePath(options.outputDir ?? crateDir),
|
|
83
89
|
options.targetDir ??
|
|
@@ -138,24 +144,124 @@ class Builder {
|
|
|
138
144
|
.setPackage()
|
|
139
145
|
.setFeatures()
|
|
140
146
|
.setTarget()
|
|
147
|
+
.pickCrossToolchain()
|
|
141
148
|
.setEnvs()
|
|
142
149
|
.setBypassArgs()
|
|
143
150
|
.exec()
|
|
144
151
|
}
|
|
145
152
|
|
|
153
|
+
private pickCrossToolchain() {
|
|
154
|
+
if (!this.options.useNapiCross) {
|
|
155
|
+
return this
|
|
156
|
+
}
|
|
157
|
+
if (this.options.useCross) {
|
|
158
|
+
debug.warn(
|
|
159
|
+
'You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.',
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (this.options.crossCompile) {
|
|
164
|
+
debug.warn(
|
|
165
|
+
'You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.',
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const { version, download } = require('@napi-rs/cross-toolchain')
|
|
171
|
+
|
|
172
|
+
const toolchainPath = join(
|
|
173
|
+
homedir(),
|
|
174
|
+
'.napi-rs',
|
|
175
|
+
'cross-toolchain',
|
|
176
|
+
version,
|
|
177
|
+
this.target.triple,
|
|
178
|
+
)
|
|
179
|
+
mkdirSync(toolchainPath, { recursive: true })
|
|
180
|
+
if (existsSync(join(toolchainPath, 'package.json'))) {
|
|
181
|
+
debug(`Toolchain ${toolchainPath} exists, skip extracting`)
|
|
182
|
+
} else {
|
|
183
|
+
const tarArchive = download(process.arch, this.target.triple)
|
|
184
|
+
tarArchive.unpack(toolchainPath)
|
|
185
|
+
}
|
|
186
|
+
const upperCaseTarget = targetToEnvVar(this.target.triple)
|
|
187
|
+
const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`
|
|
188
|
+
this.envs[linkerEnv] = join(
|
|
189
|
+
toolchainPath,
|
|
190
|
+
'bin',
|
|
191
|
+
`${this.target.triple}-gcc`,
|
|
192
|
+
)
|
|
193
|
+
if (!process.env.TARGET_SYSROOT) {
|
|
194
|
+
this.envs[`TARGET_SYSROOT`] = join(
|
|
195
|
+
toolchainPath,
|
|
196
|
+
this.target.triple,
|
|
197
|
+
'sysroot',
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
if (!process.env.TARGET_AR) {
|
|
201
|
+
this.envs[`TARGET_AR`] = join(
|
|
202
|
+
toolchainPath,
|
|
203
|
+
'bin',
|
|
204
|
+
`${this.target.triple}-ar`,
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
if (!process.env.TARGET_RANLIB) {
|
|
208
|
+
this.envs[`TARGET_RANLIB`] = join(
|
|
209
|
+
toolchainPath,
|
|
210
|
+
'bin',
|
|
211
|
+
`${this.target.triple}-ranlib`,
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
if (!process.env.TARGET_READELF) {
|
|
215
|
+
this.envs[`TARGET_READELF`] = join(
|
|
216
|
+
toolchainPath,
|
|
217
|
+
'bin',
|
|
218
|
+
`${this.target.triple}-readelf`,
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
if (!process.env.TARGET_C_INCLUDE_PATH) {
|
|
222
|
+
this.envs[`TARGET_C_INCLUDE_PATH`] = join(
|
|
223
|
+
toolchainPath,
|
|
224
|
+
this.target.triple,
|
|
225
|
+
'sysroot',
|
|
226
|
+
'usr',
|
|
227
|
+
'include/',
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
if (
|
|
231
|
+
(process.env.CC === 'clang' &&
|
|
232
|
+
(process.env.TARGET_CC === 'clang' || !process.env.TARGET_CC)) ||
|
|
233
|
+
process.env.TARGET_CC === 'clang'
|
|
234
|
+
) {
|
|
235
|
+
this.envs.C_FLAGS = `--sysroot=${this.envs.TARGET_SYSROOT}`
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
debug.warn('Pick cross toolchain failed', e as Error)
|
|
239
|
+
// ignore, do nothing
|
|
240
|
+
}
|
|
241
|
+
return this
|
|
242
|
+
}
|
|
243
|
+
|
|
146
244
|
private exec() {
|
|
147
245
|
debug(`Start building crate: ${this.crate.name}`)
|
|
148
246
|
debug(' %i', `cargo ${this.args.join(' ')}`)
|
|
149
247
|
|
|
150
248
|
const controller = new AbortController()
|
|
151
249
|
|
|
250
|
+
const watch = this.options.watch
|
|
152
251
|
const buildTask = new Promise<void>((resolve, reject) => {
|
|
153
|
-
|
|
252
|
+
if (this.options.useCross && this.options.crossCompile) {
|
|
253
|
+
throw new Error(
|
|
254
|
+
'`--use-cross` and `--cross-compile` can not be used together',
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
const command =
|
|
258
|
+
process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
|
|
259
|
+
const buildProcess = spawn(command, this.args, {
|
|
154
260
|
env: {
|
|
155
261
|
...process.env,
|
|
156
262
|
...this.envs,
|
|
157
263
|
},
|
|
158
|
-
stdio: 'inherit',
|
|
264
|
+
stdio: watch ? ['inherit', 'inherit', 'pipe'] : 'inherit',
|
|
159
265
|
cwd: this.cwd,
|
|
160
266
|
signal: controller.signal,
|
|
161
267
|
})
|
|
@@ -176,6 +282,15 @@ class Builder {
|
|
|
176
282
|
}),
|
|
177
283
|
)
|
|
178
284
|
})
|
|
285
|
+
|
|
286
|
+
// watch mode only, they are piped through stderr
|
|
287
|
+
buildProcess.stderr?.on('data', (data) => {
|
|
288
|
+
const output = data.toString()
|
|
289
|
+
console.error(output)
|
|
290
|
+
if (/Finished\s(dev|release)/.test(output)) {
|
|
291
|
+
this.postBuild().catch(() => {})
|
|
292
|
+
}
|
|
293
|
+
})
|
|
179
294
|
})
|
|
180
295
|
|
|
181
296
|
return {
|
|
@@ -205,6 +320,7 @@ class Builder {
|
|
|
205
320
|
this.crateDir,
|
|
206
321
|
'--',
|
|
207
322
|
'cargo',
|
|
323
|
+
'build',
|
|
208
324
|
)
|
|
209
325
|
set = true
|
|
210
326
|
}
|
|
@@ -297,6 +413,10 @@ class Builder {
|
|
|
297
413
|
private setEnvs() {
|
|
298
414
|
// type definition intermediate file
|
|
299
415
|
this.envs.TYPE_DEF_TMP_PATH = this.getIntermediateTypeFile()
|
|
416
|
+
// WASI register intermediate file
|
|
417
|
+
this.envs.WASI_REGISTER_TMP_PATH = this.getIntermediateWasiRegisterFile()
|
|
418
|
+
// TODO:
|
|
419
|
+
// remove after napi-derive@v3 release
|
|
300
420
|
this.envs.CARGO_CFG_NAPI_RS_CLI_VERSION = CLI_VERSION
|
|
301
421
|
|
|
302
422
|
// RUSTFLAGS
|
|
@@ -320,13 +440,18 @@ class Builder {
|
|
|
320
440
|
// END RUSTFLAGS
|
|
321
441
|
|
|
322
442
|
// LINKER
|
|
323
|
-
const linker =
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
443
|
+
const linker = this.options.crossCompile
|
|
444
|
+
? void 0
|
|
445
|
+
: getTargetLinker(this.target.triple)
|
|
446
|
+
// TODO:
|
|
447
|
+
// directly set CARGO_TARGET_<target>_LINKER will cover .cargo/config.toml
|
|
448
|
+
// will detect by cargo config when it becomes stable
|
|
449
|
+
// see: https://github.com/rust-lang/cargo/issues/9301
|
|
450
|
+
const linkerEnv = `CARGO_TARGET_${targetToEnvVar(
|
|
451
|
+
this.target.triple,
|
|
452
|
+
)}_LINKER`
|
|
453
|
+
if (linker && !process.env[linkerEnv]) {
|
|
454
|
+
this.envs[linkerEnv] = linker
|
|
330
455
|
}
|
|
331
456
|
|
|
332
457
|
if (this.target.platform === 'android') {
|
|
@@ -342,18 +467,35 @@ class Builder {
|
|
|
342
467
|
const targetArch = this.target.arch === 'arm' ? 'armv7a' : 'aarch64'
|
|
343
468
|
const targetPlatform =
|
|
344
469
|
this.target.arch === 'arm' ? 'androideabi24' : 'android24'
|
|
470
|
+
const hostPlatform =
|
|
471
|
+
process.platform === 'darwin'
|
|
472
|
+
? 'darwin'
|
|
473
|
+
: process.platform === 'win32'
|
|
474
|
+
? 'windows'
|
|
475
|
+
: 'linux'
|
|
345
476
|
Object.assign(this.envs, {
|
|
346
|
-
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
347
|
-
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
348
|
-
CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
349
|
-
CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
350
|
-
AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
477
|
+
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
478
|
+
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
479
|
+
CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
480
|
+
CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
481
|
+
AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
482
|
+
RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
351
483
|
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
352
|
-
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt
|
|
484
|
+
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
|
|
353
485
|
})
|
|
354
486
|
}
|
|
355
487
|
// END LINKER
|
|
356
488
|
|
|
489
|
+
if (this.target.platform === 'wasi') {
|
|
490
|
+
const emnapi = join(
|
|
491
|
+
require.resolve('emnapi'),
|
|
492
|
+
'..',
|
|
493
|
+
'lib',
|
|
494
|
+
'wasm32-wasi-threads',
|
|
495
|
+
)
|
|
496
|
+
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
497
|
+
}
|
|
498
|
+
|
|
357
499
|
debug('Set envs: ')
|
|
358
500
|
Object.entries(this.envs).forEach(([k, v]) => {
|
|
359
501
|
debug(' %i', `${k}=${v}`)
|
|
@@ -392,6 +534,10 @@ class Builder {
|
|
|
392
534
|
this.args.push('--target-dir', this.options.targetDir)
|
|
393
535
|
}
|
|
394
536
|
|
|
537
|
+
if (this.options.profile) {
|
|
538
|
+
this.args.push('--profile', this.options.profile)
|
|
539
|
+
}
|
|
540
|
+
|
|
395
541
|
if (this.options.cargoOptions?.length) {
|
|
396
542
|
this.args.push(...this.options.cargoOptions)
|
|
397
543
|
}
|
|
@@ -410,6 +556,17 @@ class Builder {
|
|
|
410
556
|
)
|
|
411
557
|
}
|
|
412
558
|
|
|
559
|
+
private getIntermediateWasiRegisterFile() {
|
|
560
|
+
return join(
|
|
561
|
+
tmpdir(),
|
|
562
|
+
`${this.crate.name}-${createHash('sha256')
|
|
563
|
+
.update(this.crate.manifest_path)
|
|
564
|
+
.update(CLI_VERSION)
|
|
565
|
+
.digest('hex')
|
|
566
|
+
.substring(0, 8)}.napi_wasi_register.tmp`,
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
|
|
413
570
|
private async postBuild() {
|
|
414
571
|
try {
|
|
415
572
|
debug(`Try to create output directory:`)
|
|
@@ -422,12 +579,39 @@ class Builder {
|
|
|
422
579
|
})
|
|
423
580
|
}
|
|
424
581
|
|
|
425
|
-
await this.copyArtifact()
|
|
582
|
+
const dest = await this.copyArtifact()
|
|
426
583
|
|
|
427
584
|
// only for cdylib
|
|
428
585
|
if (this.cdyLibName) {
|
|
429
|
-
await this.generateTypeDef()
|
|
430
|
-
|
|
586
|
+
const idents = await this.generateTypeDef()
|
|
587
|
+
const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH
|
|
588
|
+
const wasiRegisterFunctions =
|
|
589
|
+
this.target.arch === 'wasm32'
|
|
590
|
+
? JSON.parse(
|
|
591
|
+
await readFileAsync(intermediateWasiRegisterFile, 'utf8').catch(
|
|
592
|
+
(err) => {
|
|
593
|
+
console.warn(
|
|
594
|
+
`Read ${colors.yellowBright(
|
|
595
|
+
intermediateWasiRegisterFile,
|
|
596
|
+
)} failed, reason: ${err.message}`,
|
|
597
|
+
)
|
|
598
|
+
return `[]`
|
|
599
|
+
},
|
|
600
|
+
),
|
|
601
|
+
)
|
|
602
|
+
: []
|
|
603
|
+
const jsOutput = await this.writeJsBinding(idents)
|
|
604
|
+
const wasmOutput = await this.writeWasiBinding(
|
|
605
|
+
wasiRegisterFunctions,
|
|
606
|
+
dest ?? 'index.wasm',
|
|
607
|
+
idents,
|
|
608
|
+
)
|
|
609
|
+
if (jsOutput) {
|
|
610
|
+
this.outputs.push(jsOutput)
|
|
611
|
+
}
|
|
612
|
+
if (wasmOutput) {
|
|
613
|
+
this.outputs.push(wasmOutput)
|
|
614
|
+
}
|
|
431
615
|
}
|
|
432
616
|
|
|
433
617
|
return this.outputs
|
|
@@ -439,12 +623,10 @@ class Builder {
|
|
|
439
623
|
return
|
|
440
624
|
}
|
|
441
625
|
|
|
442
|
-
const
|
|
443
|
-
this.
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
srcName,
|
|
447
|
-
)
|
|
626
|
+
const profile =
|
|
627
|
+
this.options.profile ?? (this.options.release ? 'release' : 'debug')
|
|
628
|
+
const src = join(this.targetDir, this.target.triple, profile, srcName)
|
|
629
|
+
debug(`Copy artifact from: [${src}]`)
|
|
448
630
|
const dest = join(this.outputDir, destName)
|
|
449
631
|
|
|
450
632
|
try {
|
|
@@ -459,6 +641,7 @@ class Builder {
|
|
|
459
641
|
kind: dest.endsWith('.node') ? 'node' : 'exe',
|
|
460
642
|
path: dest,
|
|
461
643
|
})
|
|
644
|
+
return dest
|
|
462
645
|
} catch (e) {
|
|
463
646
|
throw new Error('Failed to copy artifact', {
|
|
464
647
|
cause: e,
|
|
@@ -474,8 +657,10 @@ class Builder {
|
|
|
474
657
|
this.target.platform === 'darwin'
|
|
475
658
|
? `lib${cdyLib}.dylib`
|
|
476
659
|
: this.target.platform === 'win32'
|
|
477
|
-
|
|
478
|
-
|
|
660
|
+
? `${cdyLib}.dll`
|
|
661
|
+
: this.target.platform === 'wasi' || this.target.platform === 'wasm'
|
|
662
|
+
? `${cdyLib}.wasm`
|
|
663
|
+
: `lib${cdyLib}.so`
|
|
479
664
|
|
|
480
665
|
let destName = this.config.binaryName
|
|
481
666
|
// add platform suffix to binary name
|
|
@@ -484,7 +669,11 @@ class Builder {
|
|
|
484
669
|
if (this.options.platform) {
|
|
485
670
|
destName += `.${this.target.platformArchABI}`
|
|
486
671
|
}
|
|
487
|
-
|
|
672
|
+
if (srcName.endsWith('.wasm')) {
|
|
673
|
+
destName += '.wasi-wasm32.wasm'
|
|
674
|
+
} else {
|
|
675
|
+
destName += '.node'
|
|
676
|
+
}
|
|
488
677
|
|
|
489
678
|
return [srcName, destName]
|
|
490
679
|
} else if (this.binName) {
|
|
@@ -499,13 +688,14 @@ class Builder {
|
|
|
499
688
|
|
|
500
689
|
private async generateTypeDef() {
|
|
501
690
|
if (!(await fileExists(this.envs.TYPE_DEF_TMP_PATH))) {
|
|
502
|
-
return
|
|
691
|
+
return []
|
|
503
692
|
}
|
|
504
693
|
|
|
505
694
|
const dest = join(this.outputDir, this.options.dts ?? 'index.d.ts')
|
|
506
695
|
|
|
507
|
-
const dts = await processTypeDef(
|
|
696
|
+
const { dts, exports } = await processTypeDef(
|
|
508
697
|
this.envs.TYPE_DEF_TMP_PATH,
|
|
698
|
+
this.options.constEnum ?? true,
|
|
509
699
|
!this.options.noDtsHeader
|
|
510
700
|
? this.options.dtsHeader ?? DEFAULT_TYPE_DEF_HEADER
|
|
511
701
|
: '',
|
|
@@ -523,27 +713,71 @@ class Builder {
|
|
|
523
713
|
debug.error('Failed to write type def file')
|
|
524
714
|
debug.error(e as Error)
|
|
525
715
|
}
|
|
716
|
+
|
|
717
|
+
return exports
|
|
526
718
|
}
|
|
527
719
|
|
|
528
|
-
private async writeJsBinding() {
|
|
529
|
-
if (
|
|
720
|
+
private async writeJsBinding(idents: string[]) {
|
|
721
|
+
if (
|
|
722
|
+
!this.options.platform ||
|
|
723
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
724
|
+
this.options.noJsBinding ||
|
|
725
|
+
idents.length === 0
|
|
726
|
+
) {
|
|
530
727
|
return
|
|
531
728
|
}
|
|
532
729
|
|
|
533
|
-
const
|
|
730
|
+
const name = parse(this.options.jsBinding ?? 'index.js').name
|
|
534
731
|
|
|
535
|
-
const
|
|
732
|
+
const cjs = createCjsBinding(
|
|
733
|
+
this.config.binaryName,
|
|
734
|
+
this.config.packageName,
|
|
735
|
+
idents,
|
|
736
|
+
)
|
|
536
737
|
|
|
537
738
|
try {
|
|
739
|
+
const dest = join(this.outputDir, `${name}.js`)
|
|
538
740
|
debug('Writing js binding to:')
|
|
539
741
|
debug(' %i', dest)
|
|
540
|
-
await writeFileAsync(dest,
|
|
541
|
-
|
|
742
|
+
await writeFileAsync(dest, cjs, 'utf-8')
|
|
743
|
+
return {
|
|
542
744
|
kind: 'js',
|
|
543
745
|
path: dest,
|
|
544
|
-
}
|
|
746
|
+
} satisfies Output
|
|
545
747
|
} catch (e) {
|
|
546
748
|
throw new Error('Failed to write js binding file', { cause: e })
|
|
547
749
|
}
|
|
548
750
|
}
|
|
751
|
+
|
|
752
|
+
private async writeWasiBinding(
|
|
753
|
+
wasiRegisterFunctions: string[],
|
|
754
|
+
distFileName: string | undefined,
|
|
755
|
+
idents: string[],
|
|
756
|
+
) {
|
|
757
|
+
if (distFileName && wasiRegisterFunctions.length) {
|
|
758
|
+
const { name, dir } = parse(distFileName)
|
|
759
|
+
const newPath = join(dir, `${this.config.binaryName}.wasi.cjs`)
|
|
760
|
+
const workerPath = join(dir, 'wasi-worker.mjs')
|
|
761
|
+
const declareCodes = `const { ${idents.join(
|
|
762
|
+
', ',
|
|
763
|
+
)} } = __napiModule.exports\n`
|
|
764
|
+
const exportsCode = idents
|
|
765
|
+
.map((ident) => `module.exports.${ident} = ${ident}`)
|
|
766
|
+
.join(',\n')
|
|
767
|
+
await writeFileAsync(
|
|
768
|
+
newPath,
|
|
769
|
+
createWasiBinding(name, wasiRegisterFunctions) +
|
|
770
|
+
declareCodes +
|
|
771
|
+
exportsCode +
|
|
772
|
+
'\n',
|
|
773
|
+
'utf8',
|
|
774
|
+
)
|
|
775
|
+
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
|
|
776
|
+
return {
|
|
777
|
+
kind: 'wasm',
|
|
778
|
+
path: newPath,
|
|
779
|
+
} satisfies Output
|
|
780
|
+
}
|
|
781
|
+
return null
|
|
782
|
+
}
|
|
549
783
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const createWasiBinding = (
|
|
2
|
+
wasmFileName: string,
|
|
3
|
+
wasiRegisterFunctions: string[],
|
|
4
|
+
) => `/* eslint-disable */
|
|
5
|
+
/* prettier-ignore */
|
|
6
|
+
|
|
7
|
+
/* auto-generated by NAPI-RS */
|
|
8
|
+
|
|
9
|
+
const __nodeFs= require('node:fs')
|
|
10
|
+
const __nodePath = require('node:path')
|
|
11
|
+
const { WASI: __nodeWASI } = require('node:wasi')
|
|
12
|
+
const { Worker } = require('node:worker_threads')
|
|
13
|
+
|
|
14
|
+
const { instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync } = require('@emnapi/core')
|
|
15
|
+
const { getDefaultContext: __emnapiGetDefaultContext } = require('@emnapi/runtime')
|
|
16
|
+
|
|
17
|
+
const __wasi = new __nodeWASI({
|
|
18
|
+
version: 'preview1',
|
|
19
|
+
env: process.env,
|
|
20
|
+
preopens: {
|
|
21
|
+
'/': __dirname,
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const __emnapiContext = __emnapiGetDefaultContext()
|
|
26
|
+
|
|
27
|
+
const __sharedMemory = new WebAssembly.Memory({
|
|
28
|
+
initial: 1024,
|
|
29
|
+
maximum: 10240,
|
|
30
|
+
shared: true,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__nodePath.join(__dirname, '${wasmFileName}.wasm')), {
|
|
34
|
+
context: __emnapiContext,
|
|
35
|
+
asyncWorkPoolSize: 4,
|
|
36
|
+
wasi: __wasi,
|
|
37
|
+
onCreateWorker() {
|
|
38
|
+
return new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
|
|
39
|
+
env: process.env,
|
|
40
|
+
execArgv: ['--experimental-wasi-unstable-preview1'],
|
|
41
|
+
})
|
|
42
|
+
},
|
|
43
|
+
overwriteImports(importObject) {
|
|
44
|
+
importObject.env = {
|
|
45
|
+
...importObject.env,
|
|
46
|
+
...importObject.napi,
|
|
47
|
+
...importObject.emnapi,
|
|
48
|
+
memory: __sharedMemory,
|
|
49
|
+
}
|
|
50
|
+
return importObject
|
|
51
|
+
},
|
|
52
|
+
beforeInit({ instance }) {
|
|
53
|
+
__napi_rs_initialize_modules(instance)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
function __napi_rs_initialize_modules(__napiInstance) {
|
|
58
|
+
${wasiRegisterFunctions
|
|
59
|
+
.map((name) => ` __napiInstance.exports['${name}']()`)
|
|
60
|
+
.join('\n')}
|
|
61
|
+
}
|
|
62
|
+
`
|
package/src/api/new.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
debugFactory,
|
|
11
11
|
DEFAULT_TARGETS,
|
|
12
12
|
mkdirAsync,
|
|
13
|
+
readdirAsync,
|
|
14
|
+
statAsync,
|
|
13
15
|
writeFileAsync,
|
|
14
16
|
} from '../utils/index.js'
|
|
15
17
|
import { napiEngineRequirement } from '../utils/version.js'
|
|
@@ -69,21 +71,45 @@ export async function newProject(userOptions: RawNewOptions) {
|
|
|
69
71
|
|
|
70
72
|
const outputs = generateFiles(options)
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
debug(`Try to create target directory: ${options.path}`)
|
|
74
|
-
if (!options.dryRun) {
|
|
75
|
-
await mkdirAsync(options.path, { recursive: true })
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
throw new Error(`Failed to create target directory: ${options.path}`, {
|
|
79
|
-
cause: e,
|
|
80
|
-
})
|
|
81
|
-
}
|
|
74
|
+
await ensurePath(options.path, options.dryRun)
|
|
82
75
|
|
|
83
76
|
await dumpOutputs(outputs, options.dryRun)
|
|
84
77
|
debug(`Project created at: ${options.path}`)
|
|
85
78
|
}
|
|
86
79
|
|
|
80
|
+
async function ensurePath(path: string, dryRun = false) {
|
|
81
|
+
const stat = await statAsync(path, {}).catch(() => undefined)
|
|
82
|
+
|
|
83
|
+
// file descriptor exists
|
|
84
|
+
if (stat) {
|
|
85
|
+
if (stat.isFile()) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`Path ${path} for creating new napi-rs project already exists and it's not a directory.`,
|
|
88
|
+
)
|
|
89
|
+
} else if (stat.isDirectory()) {
|
|
90
|
+
const files = await readdirAsync(path)
|
|
91
|
+
if (files.length) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Path ${path} for creating new napi-rs project already exists and it's not empty.`,
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!dryRun) {
|
|
100
|
+
try {
|
|
101
|
+
debug(`Try to create target directory: ${path}`)
|
|
102
|
+
if (!dryRun) {
|
|
103
|
+
await mkdirAsync(path, { recursive: true })
|
|
104
|
+
}
|
|
105
|
+
} catch (e) {
|
|
106
|
+
throw new Error(`Failed to create target directory: ${path}`, {
|
|
107
|
+
cause: e,
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
87
113
|
function generateFiles(options: NewOptions): Output[] {
|
|
88
114
|
return [
|
|
89
115
|
generateCargoToml,
|
|
@@ -157,10 +183,7 @@ function generateGithubWorkflow(options: NewOptions): Output | null {
|
|
|
157
183
|
|
|
158
184
|
return {
|
|
159
185
|
target: './.github/workflows/ci.yml',
|
|
160
|
-
content: createGithubActionsCIYml(
|
|
161
|
-
getBinaryName(options.name),
|
|
162
|
-
options.targets,
|
|
163
|
-
),
|
|
186
|
+
content: createGithubActionsCIYml(options.targets),
|
|
164
187
|
}
|
|
165
188
|
}
|
|
166
189
|
|
package/src/api/pre-publish.ts
CHANGED
|
@@ -129,11 +129,14 @@ export async function prePublish(userOptions: PrePublishOptions) {
|
|
|
129
129
|
if (!options.dryRun) {
|
|
130
130
|
await version(userOptions)
|
|
131
131
|
await updatePackageJson(packageJsonPath, {
|
|
132
|
-
optionalDependencies: targets.reduce(
|
|
133
|
-
deps
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
optionalDependencies: targets.reduce(
|
|
133
|
+
(deps, target) => {
|
|
134
|
+
deps[`${packageName}-${target.platformArchABI}`] = packageJson.version
|
|
135
|
+
|
|
136
|
+
return deps
|
|
137
|
+
},
|
|
138
|
+
{} as Record<string, string>,
|
|
139
|
+
),
|
|
137
140
|
})
|
|
138
141
|
}
|
|
139
142
|
|