@napi-rs/cli 3.0.0-alpha.8 → 3.0.0-alpha.81
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 +310 -65
- 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 +140 -125
- 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 +141 -222
- 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 +168 -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 +7596 -13754
- 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 +52 -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.d.ts +13 -1
- package/dist/utils/metadata.js +31 -11
- 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 +55 -20
- 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 +468 -88
- 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 +150 -125
- package/src/api/templates/ci.yml.ts +27 -6
- package/src/api/templates/js-binding.ts +147 -220
- package/src/api/templates/lib.rs.ts +1 -4
- package/src/api/templates/load-wasi-template.ts +182 -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 +116 -10
- package/src/utils/index.ts +0 -1
- package/src/utils/metadata.ts +52 -14
- package/src/utils/misc.ts +11 -3
- package/src/utils/target.ts +22 -4
- package/src/utils/typegen.ts +98 -49
- 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 -64
- 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 -66
- package/src/api/wasi-worker-template.ts +0 -52
- package/src/utils/ci.ts +0 -111
package/dist/api/build.js
CHANGED
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
+
import { existsSync, mkdirSync, unlinkSync, readFileSync, writeFileSync, } 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
|
import * as colors from 'colorette';
|
|
8
|
+
import { groupBy, split } from 'lodash-es';
|
|
9
|
+
import { include as setjmpInclude, lib as setjmpLib } from 'wasm-sjlj';
|
|
7
10
|
import { CLI_VERSION, copyFileAsync, debugFactory, DEFAULT_TYPE_DEF_HEADER, fileExists, getSystemDefaultTarget, getTargetLinker, mkdirAsync, parseMetadata, parseTriple, processTypeDef, readFileAsync, readNapiConfig, targetToEnvVar, tryInstallCargoBinary, unlinkAsync, writeFileAsync, } from '../utils/index.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.js';
|
|
11
|
+
import { createCjsBinding, createEsmBinding } from './templates/index.js';
|
|
12
|
+
import { createWasiBinding, createWasiBrowserBinding, } from './templates/load-wasi-template.js';
|
|
13
|
+
import { createWasiBrowserWorkerBinding, WASI_WORKER_TEMPLATE, } from './templates/wasi-worker-template.js';
|
|
11
14
|
const debug = debugFactory('build');
|
|
12
15
|
const require = createRequire(import.meta.url);
|
|
13
16
|
export async function buildProject(options) {
|
|
14
17
|
debug('napi build command receive options: %O', options);
|
|
18
|
+
options = {
|
|
19
|
+
dtsCache: true,
|
|
20
|
+
...options,
|
|
21
|
+
};
|
|
15
22
|
const cwd = options.cwd ?? process.cwd();
|
|
16
23
|
const resolvePath = (...paths) => resolve(cwd, ...paths);
|
|
17
24
|
const manifestPath = resolvePath(options.manifestPath ?? 'Cargo.toml');
|
|
18
|
-
const metadata = parseMetadata(manifestPath);
|
|
25
|
+
const metadata = await parseMetadata(manifestPath);
|
|
19
26
|
const pkg = metadata.packages.find((p) => {
|
|
20
27
|
// package with given name
|
|
21
28
|
if (options.package) {
|
|
@@ -28,6 +35,9 @@ export async function buildProject(options) {
|
|
|
28
35
|
if (!pkg) {
|
|
29
36
|
throw new Error('Unable to find crate to build. It seems you are trying to build a crate in a workspace, try using `--package` option to specify the package to build.');
|
|
30
37
|
}
|
|
38
|
+
const depsNapiPackages = pkg.dependencies
|
|
39
|
+
.map((p) => metadata.packages.find((c) => c.name === p.name))
|
|
40
|
+
.filter((c) => c != null && c.dependencies.some((d) => d.name == 'napi-derive'));
|
|
31
41
|
const crateDir = parse(pkg.manifest_path).dir;
|
|
32
42
|
const builder = new Builder(options, pkg, cwd, options.target
|
|
33
43
|
? parseTriple(options.target)
|
|
@@ -35,7 +45,7 @@ export async function buildProject(options) {
|
|
|
35
45
|
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
|
36
46
|
: getSystemDefaultTarget(), crateDir, resolvePath(options.outputDir ?? crateDir), options.targetDir ??
|
|
37
47
|
process.env.CARGO_BUILD_TARGET_DIR ??
|
|
38
|
-
metadata.target_directory, await readNapiConfig(resolvePath(options.packageJsonPath ?? 'package.json')));
|
|
48
|
+
metadata.target_directory, await readNapiConfig(resolvePath(options.configPath ?? options.packageJsonPath ?? 'package.json'), options.configPath ? resolvePath(options.configPath) : undefined), depsNapiPackages);
|
|
39
49
|
return builder.build();
|
|
40
50
|
}
|
|
41
51
|
class Builder {
|
|
@@ -47,10 +57,11 @@ class Builder {
|
|
|
47
57
|
outputDir;
|
|
48
58
|
targetDir;
|
|
49
59
|
config;
|
|
60
|
+
depsNapiPackages;
|
|
50
61
|
args = [];
|
|
51
62
|
envs = {};
|
|
52
63
|
outputs = [];
|
|
53
|
-
constructor(options, crate, cwd, target, crateDir, outputDir, targetDir, config) {
|
|
64
|
+
constructor(options, crate, cwd, target, crateDir, outputDir, targetDir, config, depsNapiPackages) {
|
|
54
65
|
this.options = options;
|
|
55
66
|
this.crate = crate;
|
|
56
67
|
this.cwd = cwd;
|
|
@@ -59,6 +70,7 @@ class Builder {
|
|
|
59
70
|
this.outputDir = outputDir;
|
|
60
71
|
this.targetDir = targetDir;
|
|
61
72
|
this.config = config;
|
|
73
|
+
this.depsNapiPackages = depsNapiPackages;
|
|
62
74
|
}
|
|
63
75
|
get cdyLibName() {
|
|
64
76
|
return this.crate.targets.find((t) => t.crate_types.includes('cdylib'))
|
|
@@ -85,16 +97,95 @@ class Builder {
|
|
|
85
97
|
.setPackage()
|
|
86
98
|
.setFeatures()
|
|
87
99
|
.setTarget()
|
|
100
|
+
.pickCrossToolchain()
|
|
88
101
|
.setEnvs()
|
|
89
102
|
.setBypassArgs()
|
|
90
103
|
.exec();
|
|
91
104
|
}
|
|
105
|
+
pickCrossToolchain() {
|
|
106
|
+
if (!this.options.useNapiCross) {
|
|
107
|
+
return this;
|
|
108
|
+
}
|
|
109
|
+
if (this.options.useCross) {
|
|
110
|
+
debug.warn('You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.');
|
|
111
|
+
}
|
|
112
|
+
if (this.options.crossCompile) {
|
|
113
|
+
debug.warn('You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.');
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const { version, download } = require('@napi-rs/cross-toolchain');
|
|
117
|
+
const alias = {
|
|
118
|
+
's390x-unknown-linux-gnu': 's390x-ibm-linux-gnu',
|
|
119
|
+
};
|
|
120
|
+
const toolchainPath = join(homedir(), '.napi-rs', 'cross-toolchain', version, this.target.triple);
|
|
121
|
+
mkdirSync(toolchainPath, { recursive: true });
|
|
122
|
+
if (existsSync(join(toolchainPath, 'package.json'))) {
|
|
123
|
+
debug(`Toolchain ${toolchainPath} exists, skip extracting`);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const tarArchive = download(process.arch, this.target.triple);
|
|
127
|
+
tarArchive.unpack(toolchainPath);
|
|
128
|
+
}
|
|
129
|
+
const upperCaseTarget = targetToEnvVar(this.target.triple);
|
|
130
|
+
const crossTargetName = alias[this.target.triple] ?? this.target.triple;
|
|
131
|
+
const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`;
|
|
132
|
+
this.envs[linkerEnv] = join(toolchainPath, 'bin', `${crossTargetName}-gcc`);
|
|
133
|
+
if (!process.env.TARGET_SYSROOT) {
|
|
134
|
+
this.envs[`TARGET_SYSROOT`] = join(toolchainPath, crossTargetName, 'sysroot');
|
|
135
|
+
}
|
|
136
|
+
if (!process.env.TARGET_AR) {
|
|
137
|
+
this.envs[`TARGET_AR`] = join(toolchainPath, 'bin', `${crossTargetName}-ar`);
|
|
138
|
+
}
|
|
139
|
+
if (!process.env.TARGET_RANLIB) {
|
|
140
|
+
this.envs[`TARGET_RANLIB`] = join(toolchainPath, 'bin', `${crossTargetName}-ranlib`);
|
|
141
|
+
}
|
|
142
|
+
if (!process.env.TARGET_READELF) {
|
|
143
|
+
this.envs[`TARGET_READELF`] = join(toolchainPath, 'bin', `${crossTargetName}-readelf`);
|
|
144
|
+
}
|
|
145
|
+
if (!process.env.TARGET_C_INCLUDE_PATH) {
|
|
146
|
+
this.envs[`TARGET_C_INCLUDE_PATH`] = join(toolchainPath, crossTargetName, 'sysroot', 'usr', 'include/');
|
|
147
|
+
}
|
|
148
|
+
if (!process.env.CC && !process.env.TARGET_CC) {
|
|
149
|
+
this.envs[`CC`] = join(toolchainPath, 'bin', `${crossTargetName}-gcc`);
|
|
150
|
+
this.envs[`TARGET_CC`] = join(toolchainPath, 'bin', `${crossTargetName}-gcc`);
|
|
151
|
+
}
|
|
152
|
+
if (!process.env.CXX && !process.env.TARGET_CXX) {
|
|
153
|
+
this.envs[`CXX`] = join(toolchainPath, 'bin', `${crossTargetName}-g++`);
|
|
154
|
+
this.envs[`TARGET_CXX`] = join(toolchainPath, 'bin', `${crossTargetName}-g++`);
|
|
155
|
+
}
|
|
156
|
+
if ((process.env.CC?.startsWith('clang') &&
|
|
157
|
+
(process.env.TARGET_CC?.startsWith('clang') ||
|
|
158
|
+
!process.env.TARGET_CC)) ||
|
|
159
|
+
process.env.TARGET_CC?.startsWith('clang')) {
|
|
160
|
+
const CFLAGS = process.env.CFLAGS ?? '';
|
|
161
|
+
this.envs.CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${CFLAGS}`;
|
|
162
|
+
}
|
|
163
|
+
if ((process.env.CXX?.startsWith('clang++') &&
|
|
164
|
+
(process.env.TARGET_CXX?.startsWith('clang++') ||
|
|
165
|
+
!process.env.TARGET_CXX)) ||
|
|
166
|
+
process.env.TARGET_CXX?.startsWith('clang++')) {
|
|
167
|
+
const CXXFLAGS = process.env.CXXFLAGS ?? '';
|
|
168
|
+
this.envs.CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${CXXFLAGS} ${CXXFLAGS}`;
|
|
169
|
+
}
|
|
170
|
+
this.envs.PATH = this.envs.PATH
|
|
171
|
+
? `${toolchainPath}/bin:${this.envs.PATH}:${process.env.PATH}`
|
|
172
|
+
: `${toolchainPath}/bin:${process.env.PATH}`;
|
|
173
|
+
}
|
|
174
|
+
catch (e) {
|
|
175
|
+
debug.warn('Pick cross toolchain failed', e);
|
|
176
|
+
// ignore, do nothing
|
|
177
|
+
}
|
|
178
|
+
return this;
|
|
179
|
+
}
|
|
92
180
|
exec() {
|
|
93
181
|
debug(`Start building crate: ${this.crate.name}`);
|
|
94
182
|
debug(' %i', `cargo ${this.args.join(' ')}`);
|
|
95
183
|
const controller = new AbortController();
|
|
96
184
|
const watch = this.options.watch;
|
|
97
185
|
const buildTask = new Promise((resolve, reject) => {
|
|
186
|
+
if (this.options.useCross && this.options.crossCompile) {
|
|
187
|
+
throw new Error('`--use-cross` and `--cross-compile` can not be used together');
|
|
188
|
+
}
|
|
98
189
|
const command = process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo');
|
|
99
190
|
const buildProcess = spawn(command, this.args, {
|
|
100
191
|
env: {
|
|
@@ -123,7 +214,7 @@ class Builder {
|
|
|
123
214
|
buildProcess.stderr?.on('data', (data) => {
|
|
124
215
|
const output = data.toString();
|
|
125
216
|
console.error(output);
|
|
126
|
-
if (/Finished\s(dev
|
|
217
|
+
if (/Finished\s(`dev`|`release`)/.test(output)) {
|
|
127
218
|
this.postBuild().catch(() => { });
|
|
128
219
|
}
|
|
129
220
|
});
|
|
@@ -221,11 +312,68 @@ class Builder {
|
|
|
221
312
|
setEnvs() {
|
|
222
313
|
// type definition intermediate file
|
|
223
314
|
this.envs.TYPE_DEF_TMP_PATH = this.getIntermediateTypeFile();
|
|
224
|
-
//
|
|
225
|
-
this.envs.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
315
|
+
// Validate the packages and dependencies
|
|
316
|
+
if (existsSync(this.envs.TYPE_DEF_TMP_PATH)) {
|
|
317
|
+
const { depsNapiPackages, crate } = this;
|
|
318
|
+
let shouldInvalidateSelf = false;
|
|
319
|
+
const content = readFileSync(this.envs.TYPE_DEF_TMP_PATH, 'utf-8');
|
|
320
|
+
const typedefRaw = content
|
|
321
|
+
.split('\n')
|
|
322
|
+
.filter((line) => line.trim().length)
|
|
323
|
+
.map((line) => {
|
|
324
|
+
const [pkgName, ...jsonContents] = split(line, ':');
|
|
325
|
+
return {
|
|
326
|
+
pkgName,
|
|
327
|
+
jsonContent: jsonContents.join(':'),
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
const groupedTypedefRaw = groupBy(typedefRaw, ({ pkgName }) => pkgName);
|
|
331
|
+
const invalidPackages = new Set();
|
|
332
|
+
for (const [pkgName, value] of Object.entries(groupedTypedefRaw)) {
|
|
333
|
+
const packageInvalidKey = `NAPI_PACKAGE_${pkgName.toUpperCase().replaceAll('-', '_')}_INVALID`;
|
|
334
|
+
let done = false;
|
|
335
|
+
for (const { jsonContent } of value) {
|
|
336
|
+
try {
|
|
337
|
+
// package_name: { "done": true } was written by napi-build in project build.rs
|
|
338
|
+
// if it exists, the package was successfully built and typedef was written
|
|
339
|
+
const json = JSON.parse(jsonContent);
|
|
340
|
+
if (json.done === true) {
|
|
341
|
+
done = true;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
done = false;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (!done) {
|
|
351
|
+
process.env[packageInvalidKey] = `${Date.now()}`;
|
|
352
|
+
shouldInvalidateSelf = true;
|
|
353
|
+
invalidPackages.add(pkgName);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const typedefPackages = new Set(Object.keys(groupedTypedefRaw));
|
|
357
|
+
for (const crate of depsNapiPackages) {
|
|
358
|
+
if (!typedefPackages.has(crate.name)) {
|
|
359
|
+
debug('Set invalid package typedef: %i', crate.name);
|
|
360
|
+
shouldInvalidateSelf = true;
|
|
361
|
+
process.env[`NAPI_PACKAGE_${crate.name.toUpperCase().replaceAll('-', '_')}_INVALID`] = `${Date.now()}`;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (shouldInvalidateSelf) {
|
|
365
|
+
debug('Set invalid package typedef: %i', crate.name);
|
|
366
|
+
process.env[`NAPI_PACKAGE_${crate.name.toUpperCase().replaceAll('-', '_')}_INVALID`] = `${Date.now()}`;
|
|
367
|
+
}
|
|
368
|
+
// clean invalid packages typedef
|
|
369
|
+
if (invalidPackages.size) {
|
|
370
|
+
debug('Clean invalid packages typedef: %O', invalidPackages);
|
|
371
|
+
writeFileSync(this.envs.TYPE_DEF_TMP_PATH, typedefRaw
|
|
372
|
+
.filter(({ pkgName }) => !invalidPackages.has(pkgName))
|
|
373
|
+
.map(({ pkgName, jsonContent }) => `${pkgName}:${jsonContent}`)
|
|
374
|
+
.join('\n'));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
229
377
|
// RUSTFLAGS
|
|
230
378
|
let rustflags = process.env.RUSTFLAGS ?? process.env.CARGO_BUILD_RUSTFLAGS ?? '';
|
|
231
379
|
if (this.target.abi?.includes('musl') &&
|
|
@@ -248,7 +396,7 @@ class Builder {
|
|
|
248
396
|
// will detect by cargo config when it becomes stable
|
|
249
397
|
// see: https://github.com/rust-lang/cargo/issues/9301
|
|
250
398
|
const linkerEnv = `CARGO_TARGET_${targetToEnvVar(this.target.triple)}_LINKER`;
|
|
251
|
-
if (linker && !process.env[linkerEnv]) {
|
|
399
|
+
if (linker && !process.env[linkerEnv] && !this.envs[linkerEnv]) {
|
|
252
400
|
this.envs[linkerEnv] = linker;
|
|
253
401
|
}
|
|
254
402
|
if (this.target.platform === 'android') {
|
|
@@ -266,10 +414,10 @@ class Builder {
|
|
|
266
414
|
Object.assign(this.envs, {
|
|
267
415
|
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
268
416
|
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
417
|
+
TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
418
|
+
TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
419
|
+
TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
420
|
+
TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
273
421
|
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
274
422
|
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
|
|
275
423
|
});
|
|
@@ -278,6 +426,21 @@ class Builder {
|
|
|
278
426
|
if (this.target.platform === 'wasi') {
|
|
279
427
|
const emnapi = join(require.resolve('emnapi'), '..', 'lib', 'wasm32-wasi-threads');
|
|
280
428
|
this.envs.EMNAPI_LINK_DIR = emnapi;
|
|
429
|
+
this.envs.SETJMP_LINK_DIR = setjmpLib;
|
|
430
|
+
const { WASI_SDK_PATH } = process.env;
|
|
431
|
+
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
432
|
+
this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(WASI_SDK_PATH, 'bin', 'wasm-ld');
|
|
433
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(WASI_SDK_PATH, 'bin', 'wasm-ld');
|
|
434
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(WASI_SDK_PATH, 'bin', 'wasm-ld');
|
|
435
|
+
this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(WASI_SDK_PATH, 'bin', 'wasm-ld');
|
|
436
|
+
this.setEnvIfNotExists('CC', join(WASI_SDK_PATH, 'bin', 'clang'));
|
|
437
|
+
this.setEnvIfNotExists('CXX', join(WASI_SDK_PATH, 'bin', 'clang++'));
|
|
438
|
+
this.setEnvIfNotExists('AR', join(WASI_SDK_PATH, 'bin', 'ar'));
|
|
439
|
+
this.setEnvIfNotExists('RANLIB', join(WASI_SDK_PATH, 'bin', 'ranlib'));
|
|
440
|
+
this.setEnvIfNotExists('CFLAGS', `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`);
|
|
441
|
+
this.setEnvIfNotExists('CXXFLAGS', `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`);
|
|
442
|
+
this.setEnvIfNotExists(`LDFLAGS`, `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`);
|
|
443
|
+
}
|
|
281
444
|
}
|
|
282
445
|
debug('Set envs: ');
|
|
283
446
|
Object.entries(this.envs).forEach(([k, v]) => {
|
|
@@ -287,13 +450,16 @@ class Builder {
|
|
|
287
450
|
}
|
|
288
451
|
setFeatures() {
|
|
289
452
|
const args = [];
|
|
453
|
+
if (this.options.allFeatures && this.options.noDefaultFeatures) {
|
|
454
|
+
throw new Error('Cannot specify --all-features and --no-default-features together');
|
|
455
|
+
}
|
|
290
456
|
if (this.options.allFeatures) {
|
|
291
457
|
args.push('--all-features');
|
|
292
458
|
}
|
|
293
459
|
else if (this.options.noDefaultFeatures) {
|
|
294
460
|
args.push('--no-default-features');
|
|
295
461
|
}
|
|
296
|
-
|
|
462
|
+
if (this.options.features) {
|
|
297
463
|
args.push('--features', ...this.options.features);
|
|
298
464
|
}
|
|
299
465
|
debug('Set features flags: ');
|
|
@@ -314,24 +480,28 @@ class Builder {
|
|
|
314
480
|
if (this.options.profile) {
|
|
315
481
|
this.args.push('--profile', this.options.profile);
|
|
316
482
|
}
|
|
483
|
+
if (this.options.manifestPath) {
|
|
484
|
+
this.args.push('--manifest-path', this.options.manifestPath);
|
|
485
|
+
}
|
|
317
486
|
if (this.options.cargoOptions?.length) {
|
|
318
487
|
this.args.push(...this.options.cargoOptions);
|
|
319
488
|
}
|
|
320
489
|
return this;
|
|
321
490
|
}
|
|
322
491
|
getIntermediateTypeFile() {
|
|
323
|
-
|
|
492
|
+
const dtsPath = join(tmpdir(), `${this.crate.name}-${createHash('sha256')
|
|
324
493
|
.update(this.crate.manifest_path)
|
|
325
494
|
.update(CLI_VERSION)
|
|
326
495
|
.digest('hex')
|
|
327
|
-
.substring(0, 8)}.napi_type_def
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
.
|
|
334
|
-
|
|
496
|
+
.substring(0, 8)}.napi_type_def`);
|
|
497
|
+
if (!this.options.dtsCache) {
|
|
498
|
+
try {
|
|
499
|
+
unlinkSync(dtsPath);
|
|
500
|
+
}
|
|
501
|
+
catch { }
|
|
502
|
+
return `${dtsPath}_${Date.now()}.tmp`;
|
|
503
|
+
}
|
|
504
|
+
return `${dtsPath}.tmp`;
|
|
335
505
|
}
|
|
336
506
|
async postBuild() {
|
|
337
507
|
try {
|
|
@@ -345,30 +515,23 @@ class Builder {
|
|
|
345
515
|
cause: e,
|
|
346
516
|
});
|
|
347
517
|
}
|
|
348
|
-
const
|
|
518
|
+
const wasmBinaryName = await this.copyArtifact();
|
|
349
519
|
// only for cdylib
|
|
350
520
|
if (this.cdyLibName) {
|
|
351
521
|
const idents = await this.generateTypeDef();
|
|
352
|
-
const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH;
|
|
353
|
-
const wasiRegisterFunctions = this.target.arch === 'wasm32'
|
|
354
|
-
? JSON.parse(await readFileAsync(intermediateWasiRegisterFile, 'utf8').catch((err) => {
|
|
355
|
-
console.warn(`Read ${colors.yellowBright(intermediateWasiRegisterFile)} failed, reason: ${err.message}`);
|
|
356
|
-
return `[]`;
|
|
357
|
-
}))
|
|
358
|
-
: [];
|
|
359
522
|
const jsOutput = await this.writeJsBinding(idents);
|
|
360
|
-
const
|
|
523
|
+
const wasmBindingsOutput = await this.writeWasiBinding(wasmBinaryName, idents);
|
|
361
524
|
if (jsOutput) {
|
|
362
525
|
this.outputs.push(jsOutput);
|
|
363
526
|
}
|
|
364
|
-
if (
|
|
365
|
-
this.outputs.push(
|
|
527
|
+
if (wasmBindingsOutput) {
|
|
528
|
+
this.outputs.push(...wasmBindingsOutput);
|
|
366
529
|
}
|
|
367
530
|
}
|
|
368
531
|
return this.outputs;
|
|
369
532
|
}
|
|
370
533
|
async copyArtifact() {
|
|
371
|
-
const [srcName, destName] = this.getArtifactNames();
|
|
534
|
+
const [srcName, destName, wasmBinaryName] = this.getArtifactNames();
|
|
372
535
|
if (!srcName || !destName) {
|
|
373
536
|
return;
|
|
374
537
|
}
|
|
@@ -376,6 +539,7 @@ class Builder {
|
|
|
376
539
|
const src = join(this.targetDir, this.target.triple, profile, srcName);
|
|
377
540
|
debug(`Copy artifact from: [${src}]`);
|
|
378
541
|
const dest = join(this.outputDir, destName);
|
|
542
|
+
const isWasm = dest.endsWith('.wasm');
|
|
379
543
|
try {
|
|
380
544
|
if (await fileExists(dest)) {
|
|
381
545
|
debug('Old artifact found, remove it first');
|
|
@@ -383,12 +547,44 @@ class Builder {
|
|
|
383
547
|
}
|
|
384
548
|
debug('Copy artifact to:');
|
|
385
549
|
debug(' %i', dest);
|
|
386
|
-
|
|
550
|
+
if (isWasm) {
|
|
551
|
+
const { ModuleConfig } = await import('@napi-rs/wasm-tools');
|
|
552
|
+
debug('Generate debug wasm module');
|
|
553
|
+
try {
|
|
554
|
+
const debugWasmModule = new ModuleConfig()
|
|
555
|
+
.generateDwarf(true)
|
|
556
|
+
.generateNameSection(true)
|
|
557
|
+
.generateProducersSection(true)
|
|
558
|
+
.preserveCodeTransform(true)
|
|
559
|
+
.strictValidate(false)
|
|
560
|
+
.parse(await readFileAsync(src));
|
|
561
|
+
const debugWasmBinary = debugWasmModule.emitWasm(true);
|
|
562
|
+
await writeFileAsync(dest.replace(/\.wasm$/, '.debug.wasm'), debugWasmBinary);
|
|
563
|
+
debug('Generate release wasm module');
|
|
564
|
+
const releaseWasmModule = new ModuleConfig()
|
|
565
|
+
.generateDwarf(false)
|
|
566
|
+
.generateNameSection(false)
|
|
567
|
+
.generateProducersSection(false)
|
|
568
|
+
.preserveCodeTransform(false)
|
|
569
|
+
.strictValidate(false)
|
|
570
|
+
.onlyStableFeatures(false)
|
|
571
|
+
.parse(debugWasmBinary);
|
|
572
|
+
const releaseWasmBinary = releaseWasmModule.emitWasm(false);
|
|
573
|
+
await writeFileAsync(dest, releaseWasmBinary);
|
|
574
|
+
}
|
|
575
|
+
catch (e) {
|
|
576
|
+
debug.warn(`Failed to generate debug wasm module: ${e.message ?? e}`);
|
|
577
|
+
await copyFileAsync(src, dest);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
await copyFileAsync(src, dest);
|
|
582
|
+
}
|
|
387
583
|
this.outputs.push({
|
|
388
|
-
kind: dest.endsWith('.node') ? 'node' : 'exe',
|
|
584
|
+
kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe',
|
|
389
585
|
path: dest,
|
|
390
586
|
});
|
|
391
|
-
return
|
|
587
|
+
return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null;
|
|
392
588
|
}
|
|
393
589
|
catch (e) {
|
|
394
590
|
throw new Error('Failed to copy artifact', {
|
|
@@ -399,6 +595,7 @@ class Builder {
|
|
|
399
595
|
getArtifactNames() {
|
|
400
596
|
if (this.cdyLibName) {
|
|
401
597
|
const cdyLib = this.cdyLibName.replace(/-/g, '_');
|
|
598
|
+
const wasiTarget = this.config.targets.find((t) => t.platform === 'wasi');
|
|
402
599
|
const srcName = this.target.platform === 'darwin'
|
|
403
600
|
? `lib${cdyLib}.dylib`
|
|
404
601
|
: this.target.platform === 'win32'
|
|
@@ -414,12 +611,18 @@ class Builder {
|
|
|
414
611
|
destName += `.${this.target.platformArchABI}`;
|
|
415
612
|
}
|
|
416
613
|
if (srcName.endsWith('.wasm')) {
|
|
417
|
-
destName += '.
|
|
614
|
+
destName += '.wasm';
|
|
418
615
|
}
|
|
419
616
|
else {
|
|
420
617
|
destName += '.node';
|
|
421
618
|
}
|
|
422
|
-
return [
|
|
619
|
+
return [
|
|
620
|
+
srcName,
|
|
621
|
+
destName,
|
|
622
|
+
wasiTarget
|
|
623
|
+
? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm`
|
|
624
|
+
: null,
|
|
625
|
+
];
|
|
423
626
|
}
|
|
424
627
|
else if (this.binName) {
|
|
425
628
|
const srcName = this.target.platform === 'win32' ? `${this.binName}.exe` : this.binName;
|
|
@@ -432,8 +635,16 @@ class Builder {
|
|
|
432
635
|
return [];
|
|
433
636
|
}
|
|
434
637
|
const dest = join(this.outputDir, this.options.dts ?? 'index.d.ts');
|
|
435
|
-
const { dts, exports } = await processTypeDef(this.envs.TYPE_DEF_TMP_PATH, !this.options.noDtsHeader
|
|
436
|
-
? this.options.dtsHeader ??
|
|
638
|
+
const { dts, exports } = await processTypeDef(this.envs.TYPE_DEF_TMP_PATH, this.options.constEnum ?? this.config.constEnum ?? true, !this.options.noDtsHeader
|
|
639
|
+
? (this.options.dtsHeader ??
|
|
640
|
+
(this.config.dtsHeaderFile
|
|
641
|
+
? await readFileAsync(join(this.cwd, this.config.dtsHeaderFile), 'utf-8').catch(() => {
|
|
642
|
+
debug.warn(`Failed to read dts header file ${this.config.dtsHeaderFile}`);
|
|
643
|
+
return null;
|
|
644
|
+
})
|
|
645
|
+
: null) ??
|
|
646
|
+
this.config.dtsHeader ??
|
|
647
|
+
DEFAULT_TYPE_DEF_HEADER)
|
|
437
648
|
: '');
|
|
438
649
|
try {
|
|
439
650
|
debug('Writing type def to:');
|
|
@@ -457,13 +668,14 @@ class Builder {
|
|
|
457
668
|
idents.length === 0) {
|
|
458
669
|
return;
|
|
459
670
|
}
|
|
460
|
-
const name =
|
|
461
|
-
const
|
|
671
|
+
const name = this.options.jsBinding ?? 'index.js';
|
|
672
|
+
const createBinding = this.options.esm ? createEsmBinding : createCjsBinding;
|
|
673
|
+
const binding = createBinding(this.config.binaryName, this.config.packageName, idents);
|
|
462
674
|
try {
|
|
463
|
-
const dest = join(this.outputDir,
|
|
675
|
+
const dest = join(this.outputDir, name);
|
|
464
676
|
debug('Writing js binding to:');
|
|
465
677
|
debug(' %i', dest);
|
|
466
|
-
await writeFileAsync(dest,
|
|
678
|
+
await writeFileAsync(dest, binding, 'utf-8');
|
|
467
679
|
return {
|
|
468
680
|
kind: 'js',
|
|
469
681
|
path: dest,
|
|
@@ -473,26 +685,59 @@ class Builder {
|
|
|
473
685
|
throw new Error('Failed to write js binding file', { cause: e });
|
|
474
686
|
}
|
|
475
687
|
}
|
|
476
|
-
async writeWasiBinding(
|
|
477
|
-
if (distFileName
|
|
688
|
+
async writeWasiBinding(distFileName, idents) {
|
|
689
|
+
if (distFileName) {
|
|
478
690
|
const { name, dir } = parse(distFileName);
|
|
479
|
-
const
|
|
691
|
+
const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`);
|
|
692
|
+
const browserBindingPath = join(dir, `${this.config.binaryName}.wasi-browser.js`);
|
|
480
693
|
const workerPath = join(dir, 'wasi-worker.mjs');
|
|
481
|
-
const
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
694
|
+
const browserWorkerPath = join(dir, 'wasi-worker-browser.mjs');
|
|
695
|
+
const browserEntryPath = join(dir, 'browser.js');
|
|
696
|
+
const exportsCode = `module.exports = __napiModule.exports\n` +
|
|
697
|
+
idents
|
|
698
|
+
.map((ident) => `module.exports.${ident} = __napiModule.exports.${ident}`)
|
|
699
|
+
.join('\n');
|
|
700
|
+
await writeFileAsync(bindingPath, createWasiBinding(name, this.config.packageName, this.config.wasm?.initialMemory, this.config.wasm?.maximumMemory) +
|
|
487
701
|
exportsCode +
|
|
488
702
|
'\n', 'utf8');
|
|
703
|
+
await writeFileAsync(browserBindingPath, createWasiBrowserBinding(name, this.config.wasm?.initialMemory, this.config.wasm?.maximumMemory, this.config.wasm?.browser?.fs, this.config.wasm?.browser?.asyncInit) +
|
|
704
|
+
`export default __napiModule.exports\n` +
|
|
705
|
+
idents
|
|
706
|
+
.map((ident) => `export const ${ident} = __napiModule.exports.${ident}`)
|
|
707
|
+
.join('\n') +
|
|
708
|
+
'\n', 'utf8');
|
|
489
709
|
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8');
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
710
|
+
await writeFileAsync(browserWorkerPath, createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false), 'utf8');
|
|
711
|
+
await writeFileAsync(browserEntryPath, `export * from '${this.config.packageName}-wasm32-wasi'\n`);
|
|
712
|
+
return [
|
|
713
|
+
{
|
|
714
|
+
kind: 'js',
|
|
715
|
+
path: bindingPath,
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
kind: 'js',
|
|
719
|
+
path: browserBindingPath,
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
kind: 'js',
|
|
723
|
+
path: workerPath,
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
kind: 'js',
|
|
727
|
+
path: browserWorkerPath,
|
|
728
|
+
},
|
|
729
|
+
{
|
|
730
|
+
kind: 'js',
|
|
731
|
+
path: browserEntryPath,
|
|
732
|
+
},
|
|
733
|
+
];
|
|
734
|
+
}
|
|
735
|
+
return [];
|
|
736
|
+
}
|
|
737
|
+
setEnvIfNotExists(env, value) {
|
|
738
|
+
if (!process.env[env]) {
|
|
739
|
+
this.envs[env] = value;
|
|
494
740
|
}
|
|
495
|
-
return null;
|
|
496
741
|
}
|
|
497
742
|
}
|
|
498
743
|
//# sourceMappingURL=build.js.map
|