@napi-rs/cli 3.0.0-alpha.10 → 3.0.0-alpha.100
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/__tests__/create-npm-dirs.spec.d.ts +1 -0
- package/dist/api/__tests__/new.spec.d.ts +1 -0
- package/dist/api/build.d.ts +1 -1
- package/dist/api/create-npm-dirs.d.ts +5 -0
- package/dist/api/templates/index.d.ts +0 -7
- package/dist/api/templates/js-binding.d.ts +1 -0
- package/dist/api/templates/load-wasi-template.d.ts +2 -0
- package/dist/api/templates/wasi-worker-template.d.ts +2 -0
- package/dist/cli.js +3961 -15
- package/dist/def/artifacts.d.ts +21 -1
- package/dist/def/build.d.ts +149 -4
- package/dist/def/create-npm-dirs.d.ts +10 -0
- package/dist/def/new.d.ts +25 -7
- package/dist/def/pre-publish.d.ts +21 -2
- package/dist/def/rename.d.ts +16 -6
- package/dist/def/universalize.d.ts +10 -0
- package/dist/def/version.d.ts +10 -0
- package/dist/index.cjs +10052 -15662
- package/dist/index.js +3712 -32
- package/dist/utils/__tests__/config.spec.d.ts +1 -0
- package/dist/utils/config.d.ts +56 -4
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/metadata.d.ts +13 -1
- package/dist/utils/misc.d.ts +3 -3
- package/dist/utils/read-config.d.ts +7 -0
- package/dist/utils/target.d.ts +8 -6
- package/dist/utils/typegen.d.ts +1 -1
- package/dist/utils/version.d.ts +2 -1
- package/package.json +38 -34
- package/src/api/__tests__/create-npm-dirs.spec.ts +210 -0
- package/src/api/__tests__/new.spec.ts +429 -0
- package/src/api/artifacts.ts +81 -9
- package/src/api/build.ts +595 -183
- package/src/api/create-npm-dirs.ts +64 -13
- package/src/api/new.ts +389 -122
- package/src/api/pre-publish.ts +19 -11
- package/src/api/rename.ts +103 -17
- package/src/api/templates/index.ts +0 -7
- package/src/api/templates/js-binding.ts +159 -220
- package/src/api/templates/load-wasi-template.ts +216 -0
- 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 +55 -8
- package/src/def/create-npm-dirs.ts +9 -0
- package/src/def/new.ts +28 -3
- package/src/def/pre-publish.ts +24 -3
- package/src/def/rename.ts +11 -2
- package/src/def/universalize.ts +9 -0
- package/src/def/version.ts +9 -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 +49 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +316 -332
- 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/cargo.ts +2 -2
- package/src/utils/config.ts +127 -9
- package/src/utils/index.ts +1 -1
- package/src/utils/log.ts +1 -1
- package/src/utils/metadata.ts +52 -14
- package/src/utils/misc.ts +21 -12
- package/src/utils/read-config.ts +20 -0
- package/src/utils/target.ts +37 -5
- package/src/utils/typegen.ts +87 -52
- package/src/utils/version.ts +10 -8
- package/dist/api/artifacts.js +0 -53
- package/dist/api/artifacts.js.map +0 -1
- package/dist/api/build.js +0 -498
- package/dist/api/build.js.map +0 -1
- package/dist/api/create-npm-dirs.js +0 -64
- package/dist/api/create-npm-dirs.js.map +0 -1
- package/dist/api/load-wasi-template.d.ts +0 -1
- package/dist/api/load-wasi-template.js +0 -60
- package/dist/api/load-wasi-template.js.map +0 -1
- package/dist/api/new.js +0 -155
- package/dist/api/new.js.map +0 -1
- package/dist/api/pre-publish.js +0 -158
- package/dist/api/pre-publish.js.map +0 -1
- package/dist/api/rename.js +0 -29
- package/dist/api/rename.js.map +0 -1
- package/dist/api/templates/.gitignore.d.ts +0 -1
- package/dist/api/templates/.gitignore.js +0 -200
- package/dist/api/templates/.gitignore.js.map +0 -1
- package/dist/api/templates/.npmignore.d.ts +0 -1
- package/dist/api/templates/.npmignore.js +0 -15
- package/dist/api/templates/.npmignore.js.map +0 -1
- package/dist/api/templates/build.rs.d.ts +0 -1
- package/dist/api/templates/build.rs.js +0 -5
- package/dist/api/templates/build.rs.js.map +0 -1
- package/dist/api/templates/cargo.toml.d.ts +0 -6
- package/dist/api/templates/cargo.toml.js +0 -26
- package/dist/api/templates/cargo.toml.js.map +0 -1
- package/dist/api/templates/ci-template.d.ts +0 -1
- package/dist/api/templates/ci-template.js +0 -578
- package/dist/api/templates/ci-template.js.map +0 -1
- package/dist/api/templates/ci.yml.d.ts +0 -1
- package/dist/api/templates/ci.yml.js +0 -99
- package/dist/api/templates/ci.yml.js.map +0 -1
- package/dist/api/templates/index.js +0 -9
- package/dist/api/templates/index.js.map +0 -1
- package/dist/api/templates/js-binding.js +0 -293
- package/dist/api/templates/js-binding.js.map +0 -1
- package/dist/api/templates/lib.rs.d.ts +0 -1
- package/dist/api/templates/lib.rs.js +0 -8
- package/dist/api/templates/lib.rs.js.map +0 -1
- package/dist/api/templates/package.json.d.ts +0 -8
- package/dist/api/templates/package.json.js +0 -32
- package/dist/api/templates/package.json.js.map +0 -1
- package/dist/api/universalize.js +0 -39
- package/dist/api/universalize.js.map +0 -1
- package/dist/api/version.js +0 -17
- package/dist/api/version.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/cli.js.map +0 -1
- package/dist/commands/artifacts.js +0 -20
- package/dist/commands/artifacts.js.map +0 -1
- package/dist/commands/build.js +0 -35
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/create-npm-dirs.js +0 -8
- package/dist/commands/create-npm-dirs.js.map +0 -1
- package/dist/commands/help.js +0 -13
- package/dist/commands/help.js.map +0 -1
- package/dist/commands/new.js +0 -110
- package/dist/commands/new.js.map +0 -1
- package/dist/commands/pre-publish.js +0 -9
- package/dist/commands/pre-publish.js.map +0 -1
- package/dist/commands/rename.js +0 -8
- package/dist/commands/rename.js.map +0 -1
- package/dist/commands/universalize.js +0 -8
- package/dist/commands/universalize.js.map +0 -1
- package/dist/commands/version.js +0 -8
- package/dist/commands/version.js.map +0 -1
- package/dist/def/artifacts.js +0 -39
- package/dist/def/artifacts.js.map +0 -1
- package/dist/def/build.js +0 -118
- package/dist/def/build.js.map +0 -1
- package/dist/def/create-npm-dirs.js +0 -39
- package/dist/def/create-npm-dirs.js.map +0 -1
- package/dist/def/new.js +0 -67
- package/dist/def/new.js.map +0 -1
- package/dist/def/pre-publish.js +0 -57
- package/dist/def/pre-publish.js.map +0 -1
- package/dist/def/rename.js +0 -59
- package/dist/def/rename.js.map +0 -1
- package/dist/def/universalize.js +0 -34
- package/dist/def/universalize.js.map +0 -1
- package/dist/def/version.js +0 -34
- package/dist/def/version.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/utils/__tests__/target.spec.js +0 -11
- package/dist/utils/__tests__/target.spec.js.map +0 -1
- package/dist/utils/__tests__/typegen.spec.js +0 -42
- package/dist/utils/__tests__/typegen.spec.js.map +0 -1
- package/dist/utils/__tests__/version.spec.js +0 -6
- package/dist/utils/__tests__/version.spec.js.map +0 -1
- package/dist/utils/cargo.js +0 -34
- package/dist/utils/cargo.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/dist/utils/config.js +0 -43
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/index.js +0 -10
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/log.js +0 -15
- package/dist/utils/log.js.map +0 -1
- package/dist/utils/metadata.js +0 -20
- package/dist/utils/metadata.js.map +0 -1
- package/dist/utils/misc.js +0 -41
- package/dist/utils/misc.js.map +0 -1
- package/dist/utils/target.js +0 -121
- package/dist/utils/target.js.map +0 -1
- package/dist/utils/typegen.js +0 -179
- package/dist/utils/typegen.js.map +0 -1
- package/dist/utils/version.js +0 -60
- package/dist/utils/version.js.map +0 -1
- package/src/api/load-wasi-template.ts +0 -62
- package/src/api/templates/.gitignore.ts +0 -199
- package/src/api/templates/.npmignore.ts +0 -14
- package/src/api/templates/build.rs.ts +0 -4
- package/src/api/templates/cargo.toml.ts +0 -35
- package/src/api/templates/ci-template.ts +0 -577
- package/src/api/templates/ci.yml.ts +0 -119
- package/src/api/templates/lib.rs.ts +0 -7
- package/src/api/templates/package.json.ts +0 -48
- 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, rmSync } from 'node:fs'
|
|
3
4
|
import { createRequire } from 'node:module'
|
|
4
|
-
import {
|
|
5
|
+
import { 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 {
|
|
@@ -28,36 +30,45 @@ import {
|
|
|
28
30
|
tryInstallCargoBinary,
|
|
29
31
|
unlinkAsync,
|
|
30
32
|
writeFileAsync,
|
|
33
|
+
dirExistsAsync,
|
|
34
|
+
readdirAsync,
|
|
35
|
+
CargoWorkspaceMetadata,
|
|
31
36
|
} from '../utils/index.js'
|
|
32
37
|
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
|
|
38
|
+
import { createCjsBinding, createEsmBinding } from './templates/index.js'
|
|
39
|
+
import {
|
|
40
|
+
createWasiBinding,
|
|
41
|
+
createWasiBrowserBinding,
|
|
42
|
+
} from './templates/load-wasi-template.js'
|
|
43
|
+
import {
|
|
44
|
+
createWasiBrowserWorkerBinding,
|
|
45
|
+
WASI_WORKER_TEMPLATE,
|
|
46
|
+
} from './templates/wasi-worker-template.js'
|
|
36
47
|
|
|
37
48
|
const debug = debugFactory('build')
|
|
38
49
|
const require = createRequire(import.meta.url)
|
|
39
50
|
|
|
40
51
|
type OutputKind = 'js' | 'dts' | 'node' | 'exe' | 'wasm'
|
|
41
|
-
type Output = {
|
|
42
|
-
kind: OutputKind
|
|
43
|
-
path: string
|
|
44
|
-
}
|
|
52
|
+
type Output = { kind: OutputKind; path: string }
|
|
45
53
|
|
|
46
|
-
type BuildOptions = RawBuildOptions & {
|
|
47
|
-
|
|
48
|
-
}
|
|
54
|
+
type BuildOptions = RawBuildOptions & { cargoOptions?: string[] }
|
|
55
|
+
type ParsedBuildOptions = Omit<BuildOptions, 'cwd'> & { cwd: string }
|
|
49
56
|
|
|
50
|
-
export async function buildProject(
|
|
51
|
-
debug('napi build command receive options: %O',
|
|
57
|
+
export async function buildProject(rawOptions: BuildOptions) {
|
|
58
|
+
debug('napi build command receive options: %O', rawOptions)
|
|
52
59
|
|
|
53
|
-
const
|
|
60
|
+
const options: ParsedBuildOptions = {
|
|
61
|
+
dtsCache: true,
|
|
62
|
+
...rawOptions,
|
|
63
|
+
cwd: rawOptions.cwd ?? process.cwd(),
|
|
64
|
+
}
|
|
54
65
|
|
|
55
|
-
const resolvePath = (...paths: string[]) => resolve(cwd, ...paths)
|
|
66
|
+
const resolvePath = (...paths: string[]) => resolve(options.cwd, ...paths)
|
|
56
67
|
|
|
57
68
|
const manifestPath = resolvePath(options.manifestPath ?? 'Cargo.toml')
|
|
58
|
-
const metadata = parseMetadata(manifestPath)
|
|
69
|
+
const metadata = await parseMetadata(manifestPath)
|
|
59
70
|
|
|
60
|
-
const
|
|
71
|
+
const crate = metadata.packages.find((p) => {
|
|
61
72
|
// package with given name
|
|
62
73
|
if (options.package) {
|
|
63
74
|
return p.name === options.package
|
|
@@ -66,33 +77,20 @@ export async function buildProject(options: BuildOptions) {
|
|
|
66
77
|
}
|
|
67
78
|
})
|
|
68
79
|
|
|
69
|
-
if (!
|
|
80
|
+
if (!crate) {
|
|
70
81
|
throw new Error(
|
|
71
82
|
'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.',
|
|
72
83
|
)
|
|
73
84
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const builder = new Builder(
|
|
78
|
-
options,
|
|
79
|
-
pkg,
|
|
80
|
-
cwd,
|
|
81
|
-
options.target
|
|
82
|
-
? parseTriple(options.target)
|
|
83
|
-
: process.env.CARGO_BUILD_TARGET
|
|
84
|
-
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
|
85
|
-
: getSystemDefaultTarget(),
|
|
86
|
-
crateDir,
|
|
87
|
-
resolvePath(options.outputDir ?? crateDir),
|
|
88
|
-
options.targetDir ??
|
|
89
|
-
process.env.CARGO_BUILD_TARGET_DIR ??
|
|
90
|
-
metadata.target_directory,
|
|
91
|
-
await readNapiConfig(
|
|
92
|
-
resolvePath(options.packageJsonPath ?? 'package.json'),
|
|
85
|
+
const config = await readNapiConfig(
|
|
86
|
+
resolvePath(
|
|
87
|
+
options.configPath ?? options.packageJsonPath ?? 'package.json',
|
|
93
88
|
),
|
|
89
|
+
options.configPath ? resolvePath(options.configPath) : undefined,
|
|
94
90
|
)
|
|
95
91
|
|
|
92
|
+
const builder = new Builder(metadata, crate, config, options)
|
|
93
|
+
|
|
96
94
|
return builder.build()
|
|
97
95
|
}
|
|
98
96
|
|
|
@@ -101,16 +99,57 @@ class Builder {
|
|
|
101
99
|
private readonly envs: Record<string, string> = {}
|
|
102
100
|
private readonly outputs: Output[] = []
|
|
103
101
|
|
|
102
|
+
private readonly target: Target
|
|
103
|
+
private readonly crateDir: string
|
|
104
|
+
private readonly outputDir: string
|
|
105
|
+
private readonly targetDir: string
|
|
106
|
+
private readonly enableTypeDef: boolean = false
|
|
107
|
+
|
|
104
108
|
constructor(
|
|
105
|
-
private readonly
|
|
109
|
+
private readonly metadata: CargoWorkspaceMetadata,
|
|
106
110
|
private readonly crate: Crate,
|
|
107
|
-
private readonly cwd: string,
|
|
108
|
-
private readonly target: Target,
|
|
109
|
-
private readonly crateDir: string,
|
|
110
|
-
private readonly outputDir: string,
|
|
111
|
-
private readonly targetDir: string,
|
|
112
111
|
private readonly config: NapiConfig,
|
|
113
|
-
|
|
112
|
+
private readonly options: ParsedBuildOptions,
|
|
113
|
+
) {
|
|
114
|
+
this.target = options.target
|
|
115
|
+
? parseTriple(options.target)
|
|
116
|
+
: process.env.CARGO_BUILD_TARGET
|
|
117
|
+
? parseTriple(process.env.CARGO_BUILD_TARGET)
|
|
118
|
+
: getSystemDefaultTarget()
|
|
119
|
+
this.crateDir = parse(crate.manifest_path).dir
|
|
120
|
+
this.outputDir = resolve(
|
|
121
|
+
this.options.cwd,
|
|
122
|
+
options.outputDir ?? this.crateDir,
|
|
123
|
+
)
|
|
124
|
+
this.targetDir =
|
|
125
|
+
options.targetDir ??
|
|
126
|
+
process.env.CARGO_BUILD_TARGET_DIR ??
|
|
127
|
+
metadata.target_directory
|
|
128
|
+
this.enableTypeDef = this.crate.dependencies.some(
|
|
129
|
+
(dep) =>
|
|
130
|
+
dep.name === 'napi-derive' &&
|
|
131
|
+
(dep.uses_default_features || dep.features.includes('type-def')),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if (!this.enableTypeDef) {
|
|
135
|
+
const requirementWarning =
|
|
136
|
+
'`napi-derive` crate is not used or `type-def` feature is not enabled for `napi-derive` crate'
|
|
137
|
+
debug.warn(
|
|
138
|
+
`${requirementWarning}. Will skip binding generation for \`.node\`, \`.wasi\` and \`.d.ts\` files.`,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
if (
|
|
142
|
+
this.options.dts ||
|
|
143
|
+
this.options.dtsHeader ||
|
|
144
|
+
this.config.dtsHeader ||
|
|
145
|
+
this.config.dtsHeaderFile
|
|
146
|
+
) {
|
|
147
|
+
debug.warn(
|
|
148
|
+
`${requirementWarning}. \`dts\` related options are enabled but will be ignored.`,
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
114
153
|
|
|
115
154
|
get cdyLibName() {
|
|
116
155
|
return this.crate.targets.find((t) => t.crate_types.includes('cdylib'))
|
|
@@ -143,11 +182,132 @@ class Builder {
|
|
|
143
182
|
.setPackage()
|
|
144
183
|
.setFeatures()
|
|
145
184
|
.setTarget()
|
|
185
|
+
.pickCrossToolchain()
|
|
146
186
|
.setEnvs()
|
|
147
187
|
.setBypassArgs()
|
|
148
188
|
.exec()
|
|
149
189
|
}
|
|
150
190
|
|
|
191
|
+
private pickCrossToolchain() {
|
|
192
|
+
if (!this.options.useNapiCross) {
|
|
193
|
+
return this
|
|
194
|
+
}
|
|
195
|
+
if (this.options.useCross) {
|
|
196
|
+
debug.warn(
|
|
197
|
+
'You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.',
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (this.options.crossCompile) {
|
|
202
|
+
debug.warn(
|
|
203
|
+
'You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.',
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
const { version, download } = require('@napi-rs/cross-toolchain')
|
|
209
|
+
|
|
210
|
+
const alias: Record<string, string> = {
|
|
211
|
+
's390x-unknown-linux-gnu': 's390x-ibm-linux-gnu',
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const toolchainPath = join(
|
|
215
|
+
homedir(),
|
|
216
|
+
'.napi-rs',
|
|
217
|
+
'cross-toolchain',
|
|
218
|
+
version,
|
|
219
|
+
this.target.triple,
|
|
220
|
+
)
|
|
221
|
+
mkdirSync(toolchainPath, { recursive: true })
|
|
222
|
+
if (existsSync(join(toolchainPath, 'package.json'))) {
|
|
223
|
+
debug(`Toolchain ${toolchainPath} exists, skip extracting`)
|
|
224
|
+
} else {
|
|
225
|
+
const tarArchive = download(process.arch, this.target.triple)
|
|
226
|
+
tarArchive.unpack(toolchainPath)
|
|
227
|
+
}
|
|
228
|
+
const upperCaseTarget = targetToEnvVar(this.target.triple)
|
|
229
|
+
const crossTargetName = alias[this.target.triple] ?? this.target.triple
|
|
230
|
+
const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`
|
|
231
|
+
this.envs[linkerEnv] = join(
|
|
232
|
+
toolchainPath,
|
|
233
|
+
'bin',
|
|
234
|
+
`${crossTargetName}-gcc`,
|
|
235
|
+
)
|
|
236
|
+
if (!process.env.TARGET_SYSROOT) {
|
|
237
|
+
this.envs[`TARGET_SYSROOT`] = join(
|
|
238
|
+
toolchainPath,
|
|
239
|
+
crossTargetName,
|
|
240
|
+
'sysroot',
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
if (!process.env.TARGET_AR) {
|
|
244
|
+
this.envs[`TARGET_AR`] = join(
|
|
245
|
+
toolchainPath,
|
|
246
|
+
'bin',
|
|
247
|
+
`${crossTargetName}-ar`,
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
if (!process.env.TARGET_RANLIB) {
|
|
251
|
+
this.envs[`TARGET_RANLIB`] = join(
|
|
252
|
+
toolchainPath,
|
|
253
|
+
'bin',
|
|
254
|
+
`${crossTargetName}-ranlib`,
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
if (!process.env.TARGET_READELF) {
|
|
258
|
+
this.envs[`TARGET_READELF`] = join(
|
|
259
|
+
toolchainPath,
|
|
260
|
+
'bin',
|
|
261
|
+
`${crossTargetName}-readelf`,
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
if (!process.env.TARGET_C_INCLUDE_PATH) {
|
|
265
|
+
this.envs[`TARGET_C_INCLUDE_PATH`] = join(
|
|
266
|
+
toolchainPath,
|
|
267
|
+
crossTargetName,
|
|
268
|
+
'sysroot',
|
|
269
|
+
'usr',
|
|
270
|
+
'include/',
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
if (!process.env.TARGET_CC) {
|
|
274
|
+
this.envs[`TARGET_CC`] = join(
|
|
275
|
+
toolchainPath,
|
|
276
|
+
'bin',
|
|
277
|
+
`${crossTargetName}-gcc`,
|
|
278
|
+
)
|
|
279
|
+
}
|
|
280
|
+
if (!process.env.TARGET_CXX) {
|
|
281
|
+
this.envs[`TARGET_CXX`] = join(
|
|
282
|
+
toolchainPath,
|
|
283
|
+
'bin',
|
|
284
|
+
`${crossTargetName}-g++`,
|
|
285
|
+
)
|
|
286
|
+
}
|
|
287
|
+
if (
|
|
288
|
+
process.env.TARGET_CC?.startsWith('clang') ||
|
|
289
|
+
(process.env.CC?.startsWith('clang') && !process.env.TARGET_CC)
|
|
290
|
+
) {
|
|
291
|
+
const TARGET_CFLAGS = process.env.TARGET_CFLAGS ?? ''
|
|
292
|
+
this.envs.TARGET_CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${TARGET_CFLAGS}`
|
|
293
|
+
}
|
|
294
|
+
if (
|
|
295
|
+
(process.env.CXX?.startsWith('clang++') && !process.env.TARGET_CXX) ||
|
|
296
|
+
process.env.TARGET_CXX?.startsWith('clang++')
|
|
297
|
+
) {
|
|
298
|
+
const TARGET_CXXFLAGS = process.env.TARGET_CXXFLAGS ?? ''
|
|
299
|
+
this.envs.TARGET_CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath} ${TARGET_CXXFLAGS}`
|
|
300
|
+
}
|
|
301
|
+
this.envs.PATH = this.envs.PATH
|
|
302
|
+
? `${toolchainPath}/bin:${this.envs.PATH}:${process.env.PATH}`
|
|
303
|
+
: `${toolchainPath}/bin:${process.env.PATH}`
|
|
304
|
+
} catch (e) {
|
|
305
|
+
debug.warn('Pick cross toolchain failed', e as Error)
|
|
306
|
+
// ignore, do nothing
|
|
307
|
+
}
|
|
308
|
+
return this
|
|
309
|
+
}
|
|
310
|
+
|
|
151
311
|
private exec() {
|
|
152
312
|
debug(`Start building crate: ${this.crate.name}`)
|
|
153
313
|
debug(' %i', `cargo ${this.args.join(' ')}`)
|
|
@@ -156,15 +316,17 @@ class Builder {
|
|
|
156
316
|
|
|
157
317
|
const watch = this.options.watch
|
|
158
318
|
const buildTask = new Promise<void>((resolve, reject) => {
|
|
319
|
+
if (this.options.useCross && this.options.crossCompile) {
|
|
320
|
+
throw new Error(
|
|
321
|
+
'`--use-cross` and `--cross-compile` can not be used together',
|
|
322
|
+
)
|
|
323
|
+
}
|
|
159
324
|
const command =
|
|
160
325
|
process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
|
|
161
326
|
const buildProcess = spawn(command, this.args, {
|
|
162
|
-
env: {
|
|
163
|
-
...process.env,
|
|
164
|
-
...this.envs,
|
|
165
|
-
},
|
|
327
|
+
env: { ...process.env, ...this.envs },
|
|
166
328
|
stdio: watch ? ['inherit', 'inherit', 'pipe'] : 'inherit',
|
|
167
|
-
cwd: this.cwd,
|
|
329
|
+
cwd: this.options.cwd,
|
|
168
330
|
signal: controller.signal,
|
|
169
331
|
})
|
|
170
332
|
|
|
@@ -178,18 +340,14 @@ class Builder {
|
|
|
178
340
|
})
|
|
179
341
|
|
|
180
342
|
buildProcess.once('error', (e) => {
|
|
181
|
-
reject(
|
|
182
|
-
new Error(`Build failed with error: ${e.message}`, {
|
|
183
|
-
cause: e,
|
|
184
|
-
}),
|
|
185
|
-
)
|
|
343
|
+
reject(new Error(`Build failed with error: ${e.message}`, { cause: e }))
|
|
186
344
|
})
|
|
187
345
|
|
|
188
346
|
// watch mode only, they are piped through stderr
|
|
189
347
|
buildProcess.stderr?.on('data', (data) => {
|
|
190
348
|
const output = data.toString()
|
|
191
349
|
console.error(output)
|
|
192
|
-
if (/Finished\s(dev
|
|
350
|
+
if (/Finished\s(`dev`|`release`)/.test(output)) {
|
|
193
351
|
this.postBuild().catch(() => {})
|
|
194
352
|
}
|
|
195
353
|
})
|
|
@@ -313,13 +471,12 @@ class Builder {
|
|
|
313
471
|
}
|
|
314
472
|
|
|
315
473
|
private setEnvs() {
|
|
316
|
-
//
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this.envs.CARGO_CFG_NAPI_RS_CLI_VERSION = CLI_VERSION
|
|
474
|
+
// TYPE DEF
|
|
475
|
+
if (this.enableTypeDef) {
|
|
476
|
+
this.envs.NAPI_TYPE_DEF_TMP_FOLDER =
|
|
477
|
+
this.generateIntermediateTypeDefFolder()
|
|
478
|
+
this.setForceBuildEnvs(this.envs.NAPI_TYPE_DEF_TMP_FOLDER)
|
|
479
|
+
}
|
|
323
480
|
|
|
324
481
|
// RUSTFLAGS
|
|
325
482
|
let rustflags =
|
|
@@ -352,50 +509,20 @@ class Builder {
|
|
|
352
509
|
const linkerEnv = `CARGO_TARGET_${targetToEnvVar(
|
|
353
510
|
this.target.triple,
|
|
354
511
|
)}_LINKER`
|
|
355
|
-
if (linker && !process.env[linkerEnv]) {
|
|
512
|
+
if (linker && !process.env[linkerEnv] && !this.envs[linkerEnv]) {
|
|
356
513
|
this.envs[linkerEnv] = linker
|
|
357
514
|
}
|
|
358
515
|
|
|
359
516
|
if (this.target.platform === 'android') {
|
|
360
|
-
|
|
361
|
-
if (!ANDROID_NDK_LATEST_HOME) {
|
|
362
|
-
debug.warn(
|
|
363
|
-
`${colors.red(
|
|
364
|
-
'ANDROID_NDK_LATEST_HOME',
|
|
365
|
-
)} environment variable is missing`,
|
|
366
|
-
)
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
const targetArch = this.target.arch === 'arm' ? 'armv7a' : 'aarch64'
|
|
370
|
-
const targetPlatform =
|
|
371
|
-
this.target.arch === 'arm' ? 'androideabi24' : 'android24'
|
|
372
|
-
const hostPlatform =
|
|
373
|
-
process.platform === 'darwin'
|
|
374
|
-
? 'darwin'
|
|
375
|
-
: process.platform === 'win32'
|
|
376
|
-
? 'windows'
|
|
377
|
-
: 'linux'
|
|
378
|
-
Object.assign(this.envs, {
|
|
379
|
-
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
380
|
-
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
381
|
-
CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
382
|
-
CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
383
|
-
AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
384
|
-
RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
385
|
-
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
386
|
-
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
|
|
387
|
-
})
|
|
517
|
+
this.setAndroidEnv()
|
|
388
518
|
}
|
|
389
|
-
// END LINKER
|
|
390
519
|
|
|
391
520
|
if (this.target.platform === 'wasi') {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
)
|
|
398
|
-
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
521
|
+
this.setWasiEnv()
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (this.target.platform === 'openharmony') {
|
|
525
|
+
this.setOpenHarmonyEnv()
|
|
399
526
|
}
|
|
400
527
|
|
|
401
528
|
debug('Set envs: ')
|
|
@@ -406,13 +533,168 @@ class Builder {
|
|
|
406
533
|
return this
|
|
407
534
|
}
|
|
408
535
|
|
|
536
|
+
private setForceBuildEnvs(typeDefTmpFolder: string) {
|
|
537
|
+
// dynamically check all napi-rs deps and set `NAPI_FORCE_BUILD_{uppercase(snake_case(name))} = timestamp`
|
|
538
|
+
this.metadata.packages.forEach((crate) => {
|
|
539
|
+
if (
|
|
540
|
+
crate.dependencies.some((d) => d.name === 'napi-derive') &&
|
|
541
|
+
!existsSync(join(typeDefTmpFolder, crate.name))
|
|
542
|
+
) {
|
|
543
|
+
this.envs[
|
|
544
|
+
`NAPI_FORCE_BUILD_${crate.name.replace(/-/g, '_').toUpperCase()}`
|
|
545
|
+
] = Date.now().toString()
|
|
546
|
+
}
|
|
547
|
+
})
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
private setAndroidEnv() {
|
|
551
|
+
const { ANDROID_NDK_LATEST_HOME } = process.env
|
|
552
|
+
if (!ANDROID_NDK_LATEST_HOME) {
|
|
553
|
+
debug.warn(
|
|
554
|
+
`${colors.red(
|
|
555
|
+
'ANDROID_NDK_LATEST_HOME',
|
|
556
|
+
)} environment variable is missing`,
|
|
557
|
+
)
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// skip cross compile setup if host is android
|
|
561
|
+
if (process.platform === 'android') {
|
|
562
|
+
return
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const targetArch = this.target.arch === 'arm' ? 'armv7a' : 'aarch64'
|
|
566
|
+
const targetPlatform =
|
|
567
|
+
this.target.arch === 'arm' ? 'androideabi24' : 'android24'
|
|
568
|
+
const hostPlatform =
|
|
569
|
+
process.platform === 'darwin'
|
|
570
|
+
? 'darwin'
|
|
571
|
+
: process.platform === 'win32'
|
|
572
|
+
? 'windows'
|
|
573
|
+
: 'linux'
|
|
574
|
+
Object.assign(this.envs, {
|
|
575
|
+
CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
|
|
576
|
+
CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
|
|
577
|
+
TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
|
|
578
|
+
TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
|
|
579
|
+
TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
|
|
580
|
+
TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
|
|
581
|
+
ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
|
|
582
|
+
PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin${process.platform === 'win32' ? ';' : ':'}${process.env.PATH}`,
|
|
583
|
+
})
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
private setWasiEnv() {
|
|
587
|
+
const emnapi = join(
|
|
588
|
+
require.resolve('emnapi'),
|
|
589
|
+
'..',
|
|
590
|
+
'lib',
|
|
591
|
+
'wasm32-wasi-threads',
|
|
592
|
+
)
|
|
593
|
+
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
594
|
+
this.envs.SETJMP_LINK_DIR = setjmpLib
|
|
595
|
+
const { WASI_SDK_PATH } = process.env
|
|
596
|
+
|
|
597
|
+
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
598
|
+
this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
|
|
599
|
+
WASI_SDK_PATH,
|
|
600
|
+
'bin',
|
|
601
|
+
'wasm-ld',
|
|
602
|
+
)
|
|
603
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
|
|
604
|
+
WASI_SDK_PATH,
|
|
605
|
+
'bin',
|
|
606
|
+
'wasm-ld',
|
|
607
|
+
)
|
|
608
|
+
this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
|
|
609
|
+
WASI_SDK_PATH,
|
|
610
|
+
'bin',
|
|
611
|
+
'wasm-ld',
|
|
612
|
+
)
|
|
613
|
+
this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
|
|
614
|
+
WASI_SDK_PATH,
|
|
615
|
+
'bin',
|
|
616
|
+
'wasm-ld',
|
|
617
|
+
)
|
|
618
|
+
this.setEnvIfNotExists('TARGET_CC', join(WASI_SDK_PATH, 'bin', 'clang'))
|
|
619
|
+
this.setEnvIfNotExists(
|
|
620
|
+
'TARGET_CXX',
|
|
621
|
+
join(WASI_SDK_PATH, 'bin', 'clang++'),
|
|
622
|
+
)
|
|
623
|
+
this.setEnvIfNotExists('TARGET_AR', join(WASI_SDK_PATH, 'bin', 'ar'))
|
|
624
|
+
this.setEnvIfNotExists(
|
|
625
|
+
'TARGET_RANLIB',
|
|
626
|
+
join(WASI_SDK_PATH, 'bin', 'ranlib'),
|
|
627
|
+
)
|
|
628
|
+
this.setEnvIfNotExists(
|
|
629
|
+
'TARGET_CFLAGS',
|
|
630
|
+
`--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
|
|
631
|
+
)
|
|
632
|
+
this.setEnvIfNotExists(
|
|
633
|
+
'TARGET_CXXFLAGS',
|
|
634
|
+
`--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
|
|
635
|
+
)
|
|
636
|
+
this.setEnvIfNotExists(
|
|
637
|
+
`TARGET_LDFLAGS`,
|
|
638
|
+
`-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
|
|
639
|
+
)
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
private setOpenHarmonyEnv() {
|
|
644
|
+
const { OHOS_SDK_PATH, OHOS_SDK_NATIVE } = process.env
|
|
645
|
+
const ndkPath = OHOS_SDK_PATH
|
|
646
|
+
? `${OHOS_SDK_NATIVE}/native`
|
|
647
|
+
: OHOS_SDK_NATIVE
|
|
648
|
+
// @ts-expect-error
|
|
649
|
+
if (!ndkPath && process.platform !== 'openharmony') {
|
|
650
|
+
debug.warn(
|
|
651
|
+
`${colors.red('OHOS_SDK_PATH')} or ${colors.red('OHOS_SDK_NATIVE')} environment variable is missing`,
|
|
652
|
+
)
|
|
653
|
+
return
|
|
654
|
+
}
|
|
655
|
+
const linkerName = `CARGO_TARGET_${this.target.triple.toUpperCase().replace(/-/g, '_')}_LINKER`
|
|
656
|
+
const ranPath = `${ndkPath}/llvm/bin/llvm-ranlib`
|
|
657
|
+
const arPath = `${ndkPath}/llvm/bin/llvm-ar`
|
|
658
|
+
const ccPath = `${ndkPath}/llvm/bin/${this.target.triple}-clang`
|
|
659
|
+
const cxxPath = `${ndkPath}/llvm/bin/${this.target.triple}-clang++`
|
|
660
|
+
const asPath = `${ndkPath}/llvm/bin/llvm-as`
|
|
661
|
+
const ldPath = `${ndkPath}/llvm/bin/ld.lld`
|
|
662
|
+
const stripPath = `${ndkPath}/llvm/bin/llvm-strip`
|
|
663
|
+
const objDumpPath = `${ndkPath}/llvm/bin/llvm-objdump`
|
|
664
|
+
const objCopyPath = `${ndkPath}/llvm/bin/llvm-objcopy`
|
|
665
|
+
const nmPath = `${ndkPath}/llvm/bin/llvm-nm`
|
|
666
|
+
const binPath = `${ndkPath}/llvm/bin`
|
|
667
|
+
const libPath = `${ndkPath}/llvm/lib`
|
|
668
|
+
|
|
669
|
+
this.setEnvIfNotExists('LIBCLANG_PATH', libPath)
|
|
670
|
+
this.setEnvIfNotExists('DEP_ATOMIC', 'clang_rt.builtins')
|
|
671
|
+
this.setEnvIfNotExists(linkerName, ccPath)
|
|
672
|
+
this.setEnvIfNotExists('TARGET_CC', ccPath)
|
|
673
|
+
this.setEnvIfNotExists('TARGET_CXX', cxxPath)
|
|
674
|
+
this.setEnvIfNotExists('TARGET_AR', arPath)
|
|
675
|
+
this.setEnvIfNotExists('TARGET_RANLIB', ranPath)
|
|
676
|
+
this.setEnvIfNotExists('TARGET_AS', asPath)
|
|
677
|
+
this.setEnvIfNotExists('TARGET_LD', ldPath)
|
|
678
|
+
this.setEnvIfNotExists('TARGET_STRIP', stripPath)
|
|
679
|
+
this.setEnvIfNotExists('TARGET_OBJDUMP', objDumpPath)
|
|
680
|
+
this.setEnvIfNotExists('TARGET_OBJCOPY', objCopyPath)
|
|
681
|
+
this.setEnvIfNotExists('TARGET_NM', nmPath)
|
|
682
|
+
this.envs.PATH = `${binPath}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH}`
|
|
683
|
+
}
|
|
684
|
+
|
|
409
685
|
private setFeatures() {
|
|
410
686
|
const args = []
|
|
687
|
+
if (this.options.allFeatures && this.options.noDefaultFeatures) {
|
|
688
|
+
throw new Error(
|
|
689
|
+
'Cannot specify --all-features and --no-default-features together',
|
|
690
|
+
)
|
|
691
|
+
}
|
|
411
692
|
if (this.options.allFeatures) {
|
|
412
693
|
args.push('--all-features')
|
|
413
694
|
} else if (this.options.noDefaultFeatures) {
|
|
414
695
|
args.push('--no-default-features')
|
|
415
|
-
}
|
|
696
|
+
}
|
|
697
|
+
if (this.options.features) {
|
|
416
698
|
args.push('--features', ...this.options.features)
|
|
417
699
|
}
|
|
418
700
|
|
|
@@ -440,6 +722,10 @@ class Builder {
|
|
|
440
722
|
this.args.push('--profile', this.options.profile)
|
|
441
723
|
}
|
|
442
724
|
|
|
725
|
+
if (this.options.manifestPath) {
|
|
726
|
+
this.args.push('--manifest-path', this.options.manifestPath)
|
|
727
|
+
}
|
|
728
|
+
|
|
443
729
|
if (this.options.cargoOptions?.length) {
|
|
444
730
|
this.args.push(...this.options.cargoOptions)
|
|
445
731
|
}
|
|
@@ -447,26 +733,25 @@ class Builder {
|
|
|
447
733
|
return this
|
|
448
734
|
}
|
|
449
735
|
|
|
450
|
-
private
|
|
451
|
-
|
|
452
|
-
|
|
736
|
+
private generateIntermediateTypeDefFolder() {
|
|
737
|
+
let folder = join(
|
|
738
|
+
this.targetDir,
|
|
739
|
+
'napi-rs',
|
|
453
740
|
`${this.crate.name}-${createHash('sha256')
|
|
454
741
|
.update(this.crate.manifest_path)
|
|
455
742
|
.update(CLI_VERSION)
|
|
456
743
|
.digest('hex')
|
|
457
|
-
.substring(0, 8)}
|
|
744
|
+
.substring(0, 8)}`,
|
|
458
745
|
)
|
|
459
|
-
}
|
|
460
746
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
)
|
|
747
|
+
if (!this.options.dtsCache) {
|
|
748
|
+
rmSync(folder, { recursive: true, force: true })
|
|
749
|
+
folder += `_${Date.now()}`
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
mkdirAsync(folder, { recursive: true })
|
|
753
|
+
|
|
754
|
+
return folder
|
|
470
755
|
}
|
|
471
756
|
|
|
472
757
|
private async postBuild() {
|
|
@@ -481,38 +766,21 @@ class Builder {
|
|
|
481
766
|
})
|
|
482
767
|
}
|
|
483
768
|
|
|
484
|
-
const
|
|
769
|
+
const wasmBinaryName = await this.copyArtifact()
|
|
485
770
|
|
|
486
771
|
// only for cdylib
|
|
487
772
|
if (this.cdyLibName) {
|
|
488
773
|
const idents = await this.generateTypeDef()
|
|
489
|
-
const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH
|
|
490
|
-
const wasiRegisterFunctions =
|
|
491
|
-
this.target.arch === 'wasm32'
|
|
492
|
-
? JSON.parse(
|
|
493
|
-
await readFileAsync(intermediateWasiRegisterFile, 'utf8').catch(
|
|
494
|
-
(err) => {
|
|
495
|
-
console.warn(
|
|
496
|
-
`Read ${colors.yellowBright(
|
|
497
|
-
intermediateWasiRegisterFile,
|
|
498
|
-
)} failed, reason: ${err.message}`,
|
|
499
|
-
)
|
|
500
|
-
return `[]`
|
|
501
|
-
},
|
|
502
|
-
),
|
|
503
|
-
)
|
|
504
|
-
: []
|
|
505
774
|
const jsOutput = await this.writeJsBinding(idents)
|
|
506
|
-
const
|
|
507
|
-
|
|
508
|
-
dest ?? 'index.wasm',
|
|
775
|
+
const wasmBindingsOutput = await this.writeWasiBinding(
|
|
776
|
+
wasmBinaryName,
|
|
509
777
|
idents,
|
|
510
778
|
)
|
|
511
779
|
if (jsOutput) {
|
|
512
780
|
this.outputs.push(jsOutput)
|
|
513
781
|
}
|
|
514
|
-
if (
|
|
515
|
-
this.outputs.push(
|
|
782
|
+
if (wasmBindingsOutput) {
|
|
783
|
+
this.outputs.push(...wasmBindingsOutput)
|
|
516
784
|
}
|
|
517
785
|
}
|
|
518
786
|
|
|
@@ -520,7 +788,7 @@ class Builder {
|
|
|
520
788
|
}
|
|
521
789
|
|
|
522
790
|
private async copyArtifact() {
|
|
523
|
-
const [srcName, destName] = this.getArtifactNames()
|
|
791
|
+
const [srcName, destName, wasmBinaryName] = this.getArtifactNames()
|
|
524
792
|
if (!srcName || !destName) {
|
|
525
793
|
return
|
|
526
794
|
}
|
|
@@ -530,6 +798,7 @@ class Builder {
|
|
|
530
798
|
const src = join(this.targetDir, this.target.triple, profile, srcName)
|
|
531
799
|
debug(`Copy artifact from: [${src}]`)
|
|
532
800
|
const dest = join(this.outputDir, destName)
|
|
801
|
+
const isWasm = dest.endsWith('.wasm')
|
|
533
802
|
|
|
534
803
|
try {
|
|
535
804
|
if (await fileExists(dest)) {
|
|
@@ -538,22 +807,56 @@ class Builder {
|
|
|
538
807
|
}
|
|
539
808
|
debug('Copy artifact to:')
|
|
540
809
|
debug(' %i', dest)
|
|
541
|
-
|
|
810
|
+
if (isWasm) {
|
|
811
|
+
const { ModuleConfig } = await import('@napi-rs/wasm-tools')
|
|
812
|
+
debug('Generate debug wasm module')
|
|
813
|
+
try {
|
|
814
|
+
const debugWasmModule = new ModuleConfig()
|
|
815
|
+
.generateDwarf(true)
|
|
816
|
+
.generateNameSection(true)
|
|
817
|
+
.generateProducersSection(true)
|
|
818
|
+
.preserveCodeTransform(true)
|
|
819
|
+
.strictValidate(false)
|
|
820
|
+
.parse(await readFileAsync(src))
|
|
821
|
+
const debugWasmBinary = debugWasmModule.emitWasm(true)
|
|
822
|
+
await writeFileAsync(
|
|
823
|
+
dest.replace(/\.wasm$/, '.debug.wasm'),
|
|
824
|
+
debugWasmBinary,
|
|
825
|
+
)
|
|
826
|
+
debug('Generate release wasm module')
|
|
827
|
+
const releaseWasmModule = new ModuleConfig()
|
|
828
|
+
.generateDwarf(false)
|
|
829
|
+
.generateNameSection(false)
|
|
830
|
+
.generateProducersSection(false)
|
|
831
|
+
.preserveCodeTransform(false)
|
|
832
|
+
.strictValidate(false)
|
|
833
|
+
.onlyStableFeatures(false)
|
|
834
|
+
.parse(debugWasmBinary)
|
|
835
|
+
const releaseWasmBinary = releaseWasmModule.emitWasm(false)
|
|
836
|
+
await writeFileAsync(dest, releaseWasmBinary)
|
|
837
|
+
} catch (e) {
|
|
838
|
+
debug.warn(
|
|
839
|
+
`Failed to generate debug wasm module: ${(e as any).message ?? e}`,
|
|
840
|
+
)
|
|
841
|
+
await copyFileAsync(src, dest)
|
|
842
|
+
}
|
|
843
|
+
} else {
|
|
844
|
+
await copyFileAsync(src, dest)
|
|
845
|
+
}
|
|
542
846
|
this.outputs.push({
|
|
543
|
-
kind: dest.endsWith('.node') ? 'node' : 'exe',
|
|
847
|
+
kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe',
|
|
544
848
|
path: dest,
|
|
545
849
|
})
|
|
546
|
-
return
|
|
850
|
+
return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null
|
|
547
851
|
} catch (e) {
|
|
548
|
-
throw new Error('Failed to copy artifact', {
|
|
549
|
-
cause: e,
|
|
550
|
-
})
|
|
852
|
+
throw new Error('Failed to copy artifact', { cause: e })
|
|
551
853
|
}
|
|
552
854
|
}
|
|
553
855
|
|
|
554
856
|
private getArtifactNames() {
|
|
555
857
|
if (this.cdyLibName) {
|
|
556
858
|
const cdyLib = this.cdyLibName.replace(/-/g, '_')
|
|
859
|
+
const wasiTarget = this.config.targets.find((t) => t.platform === 'wasi')
|
|
557
860
|
|
|
558
861
|
const srcName =
|
|
559
862
|
this.target.platform === 'darwin'
|
|
@@ -572,12 +875,18 @@ class Builder {
|
|
|
572
875
|
destName += `.${this.target.platformArchABI}`
|
|
573
876
|
}
|
|
574
877
|
if (srcName.endsWith('.wasm')) {
|
|
575
|
-
destName += '.
|
|
878
|
+
destName += '.wasm'
|
|
576
879
|
} else {
|
|
577
880
|
destName += '.node'
|
|
578
881
|
}
|
|
579
882
|
|
|
580
|
-
return [
|
|
883
|
+
return [
|
|
884
|
+
srcName,
|
|
885
|
+
destName,
|
|
886
|
+
wasiTarget
|
|
887
|
+
? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm`
|
|
888
|
+
: null,
|
|
889
|
+
]
|
|
581
890
|
} else if (this.binName) {
|
|
582
891
|
const srcName =
|
|
583
892
|
this.target.platform === 'win32' ? `${this.binName}.exe` : this.binName
|
|
@@ -589,28 +898,84 @@ class Builder {
|
|
|
589
898
|
}
|
|
590
899
|
|
|
591
900
|
private async generateTypeDef() {
|
|
592
|
-
|
|
901
|
+
const typeDefDir = this.envs.NAPI_TYPE_DEF_TMP_FOLDER
|
|
902
|
+
if (!this.enableTypeDef || !(await dirExistsAsync(typeDefDir))) {
|
|
593
903
|
return []
|
|
594
904
|
}
|
|
595
905
|
|
|
596
906
|
const dest = join(this.outputDir, this.options.dts ?? 'index.d.ts')
|
|
597
907
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
908
|
+
let header = ''
|
|
909
|
+
let dts = ''
|
|
910
|
+
let exports: string[] = []
|
|
911
|
+
|
|
912
|
+
if (!this.options.noDtsHeader) {
|
|
913
|
+
const dtsHeader = this.options.dtsHeader ?? this.config.dtsHeader
|
|
914
|
+
// `dtsHeaderFile` in config > `dtsHeader` in cli flag > `dtsHeader` in config
|
|
915
|
+
if (this.config.dtsHeaderFile) {
|
|
916
|
+
try {
|
|
917
|
+
header = await readFileAsync(
|
|
918
|
+
join(this.options.cwd, this.config.dtsHeaderFile),
|
|
919
|
+
'utf-8',
|
|
920
|
+
)
|
|
921
|
+
} catch (e) {
|
|
922
|
+
debug.warn(
|
|
923
|
+
`Failed to read dts header file ${this.config.dtsHeaderFile}`,
|
|
924
|
+
e,
|
|
925
|
+
)
|
|
926
|
+
}
|
|
927
|
+
} else if (dtsHeader) {
|
|
928
|
+
header = dtsHeader
|
|
929
|
+
} else {
|
|
930
|
+
header = DEFAULT_TYPE_DEF_HEADER
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const files = await readdirAsync(typeDefDir, { withFileTypes: true })
|
|
935
|
+
|
|
936
|
+
if (!files.length) {
|
|
937
|
+
debug('No type def files found. Skip generating dts file.')
|
|
938
|
+
return []
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
for (const file of files) {
|
|
942
|
+
if (!file.isFile()) {
|
|
943
|
+
continue
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
const { dts: fileDts, exports: fileExports } = await processTypeDef(
|
|
947
|
+
join(typeDefDir, file.name),
|
|
948
|
+
this.options.constEnum ?? this.config.constEnum ?? true,
|
|
949
|
+
)
|
|
950
|
+
|
|
951
|
+
dts += fileDts
|
|
952
|
+
exports.push(...fileExports)
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
if (dts.indexOf('ExternalObject<') > -1) {
|
|
956
|
+
header += `
|
|
957
|
+
export declare class ExternalObject<T> {
|
|
958
|
+
readonly '': {
|
|
959
|
+
readonly '': unique symbol
|
|
960
|
+
[K: symbol]: T
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
`
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
if (dts.indexOf('TypedArray') > -1) {
|
|
967
|
+
header += `
|
|
968
|
+
export type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array
|
|
969
|
+
`
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
dts = header + dts
|
|
605
973
|
|
|
606
974
|
try {
|
|
607
975
|
debug('Writing type def to:')
|
|
608
976
|
debug(' %i', dest)
|
|
609
977
|
await writeFileAsync(dest, dts, 'utf-8')
|
|
610
|
-
this.outputs.push({
|
|
611
|
-
kind: 'dts',
|
|
612
|
-
path: dest,
|
|
613
|
-
})
|
|
978
|
+
this.outputs.push({ kind: 'dts', path: dest })
|
|
614
979
|
} catch (e) {
|
|
615
980
|
debug.error('Failed to write type def file')
|
|
616
981
|
debug.error(e as Error)
|
|
@@ -629,57 +994,104 @@ class Builder {
|
|
|
629
994
|
return
|
|
630
995
|
}
|
|
631
996
|
|
|
632
|
-
const name =
|
|
997
|
+
const name = this.options.jsBinding ?? 'index.js'
|
|
633
998
|
|
|
634
|
-
const
|
|
999
|
+
const createBinding = this.options.esm ? createEsmBinding : createCjsBinding
|
|
1000
|
+
const binding = createBinding(
|
|
635
1001
|
this.config.binaryName,
|
|
636
1002
|
this.config.packageName,
|
|
637
1003
|
idents,
|
|
638
1004
|
)
|
|
639
1005
|
|
|
640
1006
|
try {
|
|
641
|
-
const dest = join(this.outputDir,
|
|
1007
|
+
const dest = join(this.outputDir, name)
|
|
642
1008
|
debug('Writing js binding to:')
|
|
643
1009
|
debug(' %i', dest)
|
|
644
|
-
await writeFileAsync(dest,
|
|
645
|
-
return {
|
|
646
|
-
kind: 'js',
|
|
647
|
-
path: dest,
|
|
648
|
-
} satisfies Output
|
|
1010
|
+
await writeFileAsync(dest, binding, 'utf-8')
|
|
1011
|
+
return { kind: 'js', path: dest } satisfies Output
|
|
649
1012
|
} catch (e) {
|
|
650
1013
|
throw new Error('Failed to write js binding file', { cause: e })
|
|
651
1014
|
}
|
|
652
1015
|
}
|
|
653
1016
|
|
|
654
1017
|
private async writeWasiBinding(
|
|
655
|
-
|
|
656
|
-
distFileName: string | undefined,
|
|
1018
|
+
distFileName: string | undefined | null,
|
|
657
1019
|
idents: string[],
|
|
658
1020
|
) {
|
|
659
|
-
if (distFileName
|
|
1021
|
+
if (distFileName) {
|
|
660
1022
|
const { name, dir } = parse(distFileName)
|
|
661
|
-
const
|
|
1023
|
+
const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`)
|
|
1024
|
+
const browserBindingPath = join(
|
|
1025
|
+
dir,
|
|
1026
|
+
`${this.config.binaryName}.wasi-browser.js`,
|
|
1027
|
+
)
|
|
662
1028
|
const workerPath = join(dir, 'wasi-worker.mjs')
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
1029
|
+
const browserWorkerPath = join(dir, 'wasi-worker-browser.mjs')
|
|
1030
|
+
const browserEntryPath = join(dir, 'browser.js')
|
|
1031
|
+
const exportsCode =
|
|
1032
|
+
`module.exports = __napiModule.exports\n` +
|
|
1033
|
+
idents
|
|
1034
|
+
.map(
|
|
1035
|
+
(ident) =>
|
|
1036
|
+
`module.exports.${ident} = __napiModule.exports.${ident}`,
|
|
1037
|
+
)
|
|
1038
|
+
.join('\n')
|
|
669
1039
|
await writeFileAsync(
|
|
670
|
-
|
|
671
|
-
createWasiBinding(
|
|
672
|
-
|
|
1040
|
+
bindingPath,
|
|
1041
|
+
createWasiBinding(
|
|
1042
|
+
name,
|
|
1043
|
+
this.config.packageName,
|
|
1044
|
+
this.config.wasm?.initialMemory,
|
|
1045
|
+
this.config.wasm?.maximumMemory,
|
|
1046
|
+
) +
|
|
673
1047
|
exportsCode +
|
|
674
1048
|
'\n',
|
|
675
1049
|
'utf8',
|
|
676
1050
|
)
|
|
1051
|
+
await writeFileAsync(
|
|
1052
|
+
browserBindingPath,
|
|
1053
|
+
createWasiBrowserBinding(
|
|
1054
|
+
name,
|
|
1055
|
+
this.config.wasm?.initialMemory,
|
|
1056
|
+
this.config.wasm?.maximumMemory,
|
|
1057
|
+
this.config.wasm?.browser?.fs,
|
|
1058
|
+
this.config.wasm?.browser?.asyncInit,
|
|
1059
|
+
this.config.wasm?.browser?.buffer,
|
|
1060
|
+
) +
|
|
1061
|
+
`export default __napiModule.exports\n` +
|
|
1062
|
+
idents
|
|
1063
|
+
.map(
|
|
1064
|
+
(ident) =>
|
|
1065
|
+
`export const ${ident} = __napiModule.exports.${ident}`,
|
|
1066
|
+
)
|
|
1067
|
+
.join('\n') +
|
|
1068
|
+
'\n',
|
|
1069
|
+
'utf8',
|
|
1070
|
+
)
|
|
677
1071
|
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
1072
|
+
await writeFileAsync(
|
|
1073
|
+
browserWorkerPath,
|
|
1074
|
+
createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false),
|
|
1075
|
+
'utf8',
|
|
1076
|
+
)
|
|
1077
|
+
await writeFileAsync(
|
|
1078
|
+
browserEntryPath,
|
|
1079
|
+
`export * from '${this.config.packageName}-wasm32-wasi'\n`,
|
|
1080
|
+
)
|
|
1081
|
+
return [
|
|
1082
|
+
{ kind: 'js', path: bindingPath },
|
|
1083
|
+
{ kind: 'js', path: browserBindingPath },
|
|
1084
|
+
{ kind: 'js', path: workerPath },
|
|
1085
|
+
{ kind: 'js', path: browserWorkerPath },
|
|
1086
|
+
{ kind: 'js', path: browserEntryPath },
|
|
1087
|
+
] satisfies Output[]
|
|
1088
|
+
}
|
|
1089
|
+
return []
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
private setEnvIfNotExists(env: string, value: string) {
|
|
1093
|
+
if (!process.env[env]) {
|
|
1094
|
+
this.envs[env] = value
|
|
682
1095
|
}
|
|
683
|
-
return null
|
|
684
1096
|
}
|
|
685
1097
|
}
|