@napi-rs/cli 3.0.0-alpha.10 → 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/src/api/build.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { spawn } from 'node:child_process'
2
2
  import { createHash } from 'node:crypto'
3
+ import { existsSync, mkdirSync } from 'node:fs'
3
4
  import { createRequire } from 'node:module'
4
- import { tmpdir } from 'node:os'
5
+ import { tmpdir, homedir } from 'node:os'
5
6
  import { parse, join, resolve } from 'node:path'
6
7
 
7
8
  import * as colors from 'colorette'
@@ -143,11 +144,103 @@ class Builder {
143
144
  .setPackage()
144
145
  .setFeatures()
145
146
  .setTarget()
147
+ .pickCrossToolchain()
146
148
  .setEnvs()
147
149
  .setBypassArgs()
148
150
  .exec()
149
151
  }
150
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
+
151
244
  private exec() {
152
245
  debug(`Start building crate: ${this.crate.name}`)
153
246
  debug(' %i', `cargo ${this.args.join(' ')}`)
@@ -156,6 +249,11 @@ class Builder {
156
249
 
157
250
  const watch = this.options.watch
158
251
  const buildTask = new Promise<void>((resolve, reject) => {
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
+ }
159
257
  const command =
160
258
  process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
161
259
  const buildProcess = spawn(command, this.args, {
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
- try {
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,
@@ -245,7 +245,6 @@ jobs:
245
245
  target: 'x86_64-apple-darwin'
246
246
  - host: windows-latest
247
247
  target: 'x86_64-pc-windows-msvc'
248
- node: ['16', '18']
249
248
  node: ['18', '20']
250
249
  runs-on: \${{ matrix.settings.host }}
251
250
 
@@ -281,7 +280,6 @@ jobs:
281
280
  strategy:
282
281
  fail-fast: false
283
282
  matrix:
284
- node: ['16', '18']
285
283
  node: ['18', '20']
286
284
  runs-on: ubuntu-latest
287
285
 
@@ -317,7 +315,6 @@ jobs:
317
315
  strategy:
318
316
  fail-fast: false
319
317
  matrix:
320
- node: ['16', '18']
321
318
  node: ['18', '20']
322
319
  runs-on: ubuntu-latest
323
320
 
@@ -355,7 +352,6 @@ jobs:
355
352
  strategy:
356
353
  fail-fast: false
357
354
  matrix:
358
- node: ['16', '18']
359
355
  node: ['18', '20']
360
356
  runs-on: ubuntu-latest
361
357
 
@@ -401,7 +397,7 @@ jobs:
401
397
  strategy:
402
398
  fail-fast: false
403
399
  matrix:
404
- node: ['16', '18']
400
+ node: ['18', '20']
405
401
 
406
402
  runs-on: ubuntu-latest
407
403
 
@@ -446,7 +442,6 @@ jobs:
446
442
  strategy:
447
443
  fail-fast: false
448
444
  matrix:
449
- node: ['16', '18']
450
445
  node: ['18', '20']
451
446
  runs-on: ubuntu-latest
452
447
 
package/src/def/build.ts CHANGED
@@ -110,6 +110,11 @@ export abstract class BaseBuildCommand extends Command {
110
110
  '[experimental] use [cross](https://github.com/cross-rs/cross) instead of `cargo`',
111
111
  })
112
112
 
113
+ useNapiCross?: boolean = Option.Boolean('--use-napi-cross', {
114
+ description:
115
+ '[experimental] use @napi-rs/cross-toolchain to cross-compile Linux arm/arm64/x64 gnu targets',
116
+ })
117
+
113
118
  watch?: boolean = Option.Boolean('--watch,-w', {
114
119
  description:
115
120
  'watch the crate changes and build continiously with `cargo-watch` crates',
@@ -151,6 +156,7 @@ export abstract class BaseBuildCommand extends Command {
151
156
  profile: this.profile,
152
157
  crossCompile: this.crossCompile,
153
158
  useCross: this.useCross,
159
+ useNapiCross: this.useNapiCross,
154
160
  watch: this.watch,
155
161
  features: this.features,
156
162
  allFeatures: this.allFeatures,
@@ -251,6 +257,10 @@ export interface BuildOptions {
251
257
  * [experimental] use [cross](https://github.com/cross-rs/cross) instead of `cargo`
252
258
  */
253
259
  useCross?: boolean
260
+ /**
261
+ * [experimental] use @napi-rs/cross-toolchain to cross-compile Linux arm/arm64/x64 gnu targets
262
+ */
263
+ useNapiCross?: boolean
254
264
  /**
255
265
  * watch the crate changes and build continiously with `cargo-watch` crates
256
266
  */
@@ -120,7 +120,7 @@ export async function readNapiConfig(path: string): Promise<NapiConfig> {
120
120
 
121
121
  // compatible with old config
122
122
  if (userNapiConfig?.name) {
123
- napiConfig.packageName = userNapiConfig.name
123
+ napiConfig.binaryName = userNapiConfig.name
124
124
  }
125
125
 
126
126
  if (!targets.length) {
@@ -1,4 +1,4 @@
1
- import { execSync } from 'child_process'
1
+ import { execSync } from 'node:child_process'
2
2
 
3
3
  export type Platform = NodeJS.Platform | 'wasm' | 'wasi'
4
4