@napi-rs/cli 2.15.2 → 3.0.0-alpha.0

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.
Files changed (194) hide show
  1. package/README.md +17 -78
  2. package/cli.mjs +12 -0
  3. package/dist/api/artifacts.d.ts +2 -0
  4. package/dist/api/artifacts.js +50 -0
  5. package/dist/api/build.d.ts +14 -0
  6. package/dist/api/build.js +404 -0
  7. package/dist/api/create-npm-dirs.d.ts +2 -0
  8. package/dist/api/create-npm-dirs.js +63 -0
  9. package/dist/api/new.d.ts +4 -0
  10. package/dist/api/new.js +154 -0
  11. package/dist/api/pre-publish.d.ts +2 -0
  12. package/dist/api/pre-publish.js +157 -0
  13. package/dist/api/rename.d.ts +2 -0
  14. package/dist/api/rename.js +28 -0
  15. package/dist/api/templates/.gitignore.d.ts +1 -0
  16. package/dist/api/templates/.gitignore.js +198 -0
  17. package/dist/api/templates/.npmignore.d.ts +1 -0
  18. package/dist/api/templates/.npmignore.js +14 -0
  19. package/dist/api/templates/build.rs.d.ts +1 -0
  20. package/dist/api/templates/build.rs.js +4 -0
  21. package/dist/api/templates/cargo.toml.d.ts +6 -0
  22. package/dist/api/templates/cargo.toml.js +25 -0
  23. package/dist/api/templates/ci-template.d.ts +1 -0
  24. package/dist/api/templates/ci-template.js +566 -0
  25. package/dist/api/templates/ci.yml.d.ts +1 -0
  26. package/dist/api/templates/ci.yml.js +92 -0
  27. package/dist/api/templates/index.d.ts +8 -0
  28. package/dist/api/templates/index.js +8 -0
  29. package/dist/api/templates/js-binding.d.ts +1 -0
  30. package/dist/api/templates/js-binding.js +124 -0
  31. package/dist/api/templates/lib.rs.d.ts +1 -0
  32. package/dist/api/templates/lib.rs.js +10 -0
  33. package/dist/api/templates/package.json.d.ts +8 -0
  34. package/dist/api/templates/package.json.js +30 -0
  35. package/dist/api/universalize.d.ts +2 -0
  36. package/dist/api/universalize.js +38 -0
  37. package/dist/api/version.d.ts +2 -0
  38. package/dist/api/version.js +16 -0
  39. package/dist/cli.d.ts +1 -0
  40. package/dist/cli.js +25 -0
  41. package/dist/commands/artifacts.d.ts +6 -0
  42. package/dist/commands/artifacts.js +19 -0
  43. package/dist/commands/build.d.ts +6 -0
  44. package/dist/commands/build.js +34 -0
  45. package/dist/commands/create-npm-dirs.d.ts +4 -0
  46. package/dist/commands/create-npm-dirs.js +7 -0
  47. package/dist/commands/help.d.ts +10 -0
  48. package/dist/commands/help.js +12 -0
  49. package/dist/commands/new.d.ts +12 -0
  50. package/dist/commands/new.js +112 -0
  51. package/dist/commands/pre-publish.d.ts +4 -0
  52. package/dist/commands/pre-publish.js +8 -0
  53. package/dist/commands/rename.d.ts +4 -0
  54. package/dist/commands/rename.js +7 -0
  55. package/dist/commands/universalize.d.ts +4 -0
  56. package/dist/commands/universalize.js +7 -0
  57. package/dist/commands/version.d.ts +4 -0
  58. package/dist/commands/version.js +7 -0
  59. package/dist/def/artifacts.d.ts +50 -0
  60. package/dist/def/artifacts.js +38 -0
  61. package/dist/def/build.d.ts +150 -0
  62. package/dist/def/build.js +105 -0
  63. package/dist/def/commands/artifacts.d.ts +15 -0
  64. package/dist/def/commands/artifacts.js +29 -0
  65. package/dist/def/commands/build.d.ts +53 -0
  66. package/dist/def/commands/build.js +105 -0
  67. package/dist/def/commands/create-npm-dirs.d.ts +15 -0
  68. package/dist/def/commands/create-npm-dirs.js +29 -0
  69. package/dist/def/commands/new.d.ts +27 -0
  70. package/dist/def/commands/new.js +53 -0
  71. package/dist/def/commands/pre-publish.d.ts +23 -0
  72. package/dist/def/commands/pre-publish.js +45 -0
  73. package/dist/def/commands/rename.d.ts +25 -0
  74. package/dist/def/commands/rename.js +49 -0
  75. package/dist/def/commands/universalize.d.ts +13 -0
  76. package/dist/def/commands/universalize.js +25 -0
  77. package/dist/def/commands/version.d.ts +13 -0
  78. package/dist/def/commands/version.js +25 -0
  79. package/dist/def/create-npm-dirs.d.ts +50 -0
  80. package/dist/def/create-npm-dirs.js +38 -0
  81. package/dist/def/new.d.ts +106 -0
  82. package/dist/def/new.js +66 -0
  83. package/dist/def/options/artifacts.d.ts +35 -0
  84. package/dist/def/options/artifacts.js +11 -0
  85. package/dist/def/options/build.d.ts +97 -0
  86. package/dist/def/options/build.js +3 -0
  87. package/dist/def/options/create-npm-dirs.d.ts +35 -0
  88. package/dist/def/options/create-npm-dirs.js +11 -0
  89. package/dist/def/options/new.d.ts +79 -0
  90. package/dist/def/options/new.js +15 -0
  91. package/dist/def/options/pre-publish.d.ts +65 -0
  92. package/dist/def/options/pre-publish.js +13 -0
  93. package/dist/def/options/rename.d.ts +75 -0
  94. package/dist/def/options/rename.js +11 -0
  95. package/dist/def/options/universalize.d.ts +28 -0
  96. package/dist/def/options/universalize.js +10 -0
  97. package/dist/def/options/version.d.ts +28 -0
  98. package/dist/def/options/version.js +10 -0
  99. package/dist/def/pre-publish.d.ts +88 -0
  100. package/dist/def/pre-publish.js +56 -0
  101. package/dist/def/rename.d.ts +100 -0
  102. package/dist/def/rename.js +58 -0
  103. package/dist/def/universalize.d.ts +41 -0
  104. package/dist/def/universalize.js +33 -0
  105. package/dist/def/version.d.ts +41 -0
  106. package/dist/def/version.js +33 -0
  107. package/dist/index.cjs +20641 -0
  108. package/dist/index.d.ts +30 -0
  109. package/dist/index.js +30 -0
  110. package/dist/utils/__tests__/target.spec.d.ts +1 -0
  111. package/dist/utils/__tests__/target.spec.js +10 -0
  112. package/dist/utils/__tests__/typegen.spec.d.ts +1 -0
  113. package/dist/utils/__tests__/typegen.spec.js +37 -0
  114. package/dist/utils/__tests__/version.spec.d.ts +1 -0
  115. package/dist/utils/__tests__/version.spec.js +5 -0
  116. package/dist/utils/cargo.d.ts +1 -0
  117. package/dist/utils/cargo.js +33 -0
  118. package/dist/utils/ci.d.ts +11 -0
  119. package/dist/utils/ci.js +86 -0
  120. package/dist/utils/config.d.ts +65 -0
  121. package/dist/utils/config.js +42 -0
  122. package/dist/utils/index.d.ts +9 -0
  123. package/dist/utils/index.js +9 -0
  124. package/dist/utils/log.d.ts +10 -0
  125. package/dist/utils/log.js +14 -0
  126. package/dist/utils/metadata.d.ts +24 -0
  127. package/dist/utils/metadata.js +19 -0
  128. package/dist/utils/misc.d.ts +13 -0
  129. package/dist/utils/misc.js +35 -0
  130. package/dist/utils/target.d.ts +30 -0
  131. package/dist/utils/target.js +109 -0
  132. package/dist/utils/typegen.d.ts +3 -0
  133. package/dist/utils/typegen.js +158 -0
  134. package/dist/utils/version.d.ts +11 -0
  135. package/dist/utils/version.js +59 -0
  136. package/package.json +63 -27
  137. package/src/api/artifacts.ts +93 -0
  138. package/src/api/build.ts +549 -0
  139. package/src/api/create-npm-dirs.ts +105 -0
  140. package/src/api/new.ts +206 -0
  141. package/src/api/pre-publish.ts +216 -0
  142. package/src/api/rename.ts +51 -0
  143. package/src/api/templates/.gitignore.ts +198 -0
  144. package/src/api/templates/.npmignore.ts +14 -0
  145. package/src/api/templates/build.rs.ts +4 -0
  146. package/src/api/templates/cargo.toml.ts +35 -0
  147. package/src/api/templates/ci-template.ts +566 -0
  148. package/src/api/templates/ci.yml.ts +116 -0
  149. package/src/api/templates/index.ts +8 -0
  150. package/src/api/templates/js-binding.ts +130 -0
  151. package/src/api/templates/lib.rs.ts +10 -0
  152. package/src/api/templates/package.json.ts +44 -0
  153. package/src/api/universalize.ts +76 -0
  154. package/src/api/version.ts +26 -0
  155. package/src/cli.ts +29 -0
  156. package/src/commands/artifacts.ts +23 -0
  157. package/src/commands/build.ts +42 -0
  158. package/src/commands/create-npm-dirs.ts +8 -0
  159. package/src/commands/help.ts +13 -0
  160. package/src/commands/new.ts +138 -0
  161. package/src/commands/pre-publish.ts +9 -0
  162. package/src/commands/rename.ts +8 -0
  163. package/src/commands/universalize.ts +8 -0
  164. package/src/commands/version.ts +8 -0
  165. package/src/def/artifacts.ts +79 -0
  166. package/src/def/build.ts +242 -0
  167. package/src/def/create-npm-dirs.ts +79 -0
  168. package/src/def/new.ts +144 -0
  169. package/src/def/pre-publish.ts +120 -0
  170. package/src/def/rename.ts +122 -0
  171. package/src/def/universalize.ts +66 -0
  172. package/src/def/version.ts +65 -0
  173. package/src/index.ts +31 -0
  174. package/src/utils/__tests__/__fixtures__/napi_type_def +201 -0
  175. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +110 -0
  176. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  177. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +618 -0
  178. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  179. package/src/utils/__tests__/__snapshots__/version.spec.ts.md +20 -0
  180. package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
  181. package/src/utils/__tests__/target.spec.ts +19 -0
  182. package/src/utils/__tests__/typegen.spec.ts +49 -0
  183. package/src/utils/__tests__/version.spec.ts +13 -0
  184. package/src/utils/cargo.ts +35 -0
  185. package/src/utils/ci.ts +102 -0
  186. package/src/utils/config.ts +123 -0
  187. package/src/utils/index.ts +9 -0
  188. package/src/utils/log.ts +34 -0
  189. package/src/utils/metadata.ts +59 -0
  190. package/src/utils/misc.ts +45 -0
  191. package/src/utils/target.ts +145 -0
  192. package/src/utils/typegen.ts +193 -0
  193. package/src/utils/version.ts +76 -0
  194. package/scripts/index.js +0 -153779
@@ -0,0 +1,13 @@
1
+ import test from 'ava'
2
+
3
+ import { napiEngineRequirement, NapiVersion } from '../version.js'
4
+
5
+ test('should generate correct napi engine requirement', (t) => {
6
+ t.snapshot(
7
+ (
8
+ Object.values(NapiVersion).filter(
9
+ (v) => typeof v === 'number',
10
+ ) as NapiVersion[]
11
+ ).map(napiEngineRequirement),
12
+ )
13
+ })
@@ -0,0 +1,35 @@
1
+ import { execSync } from 'child_process'
2
+
3
+ import { debug } from './log.js'
4
+
5
+ export function tryInstallCargoBinary(name: string, bin: string) {
6
+ if (detectCargoBinary(bin)) {
7
+ debug('Cargo binary already installed: %s', name)
8
+ return
9
+ }
10
+
11
+ try {
12
+ debug('Installing cargo binary: %s', name)
13
+ execSync(`cargo install ${name}`, {
14
+ stdio: 'inherit',
15
+ })
16
+ } catch (e) {
17
+ throw new Error(`Failed to install cargo binary: ${name}`, {
18
+ cause: e,
19
+ })
20
+ }
21
+ }
22
+
23
+ function detectCargoBinary(bin: string) {
24
+ debug('Detecting cargo binary: %s', bin)
25
+ try {
26
+ execSync(`cargo help ${bin}`, {
27
+ stdio: 'ignore',
28
+ })
29
+ debug('Cargo binary detected: %s', bin)
30
+ return true
31
+ } catch (e) {
32
+ debug('Cargo binary not detected: %s', bin)
33
+ return false
34
+ }
35
+ }
@@ -0,0 +1,102 @@
1
+ import { TargetTriple } from './target.js'
2
+
3
+ export const CIConfig: Partial<
4
+ Record<
5
+ TargetTriple,
6
+ {
7
+ host: string
8
+ build_image?: string
9
+ build_setup?: string[]
10
+ test?: boolean
11
+ test_image?: string
12
+ test_setup?: string[]
13
+ yarn_cpu?: string
14
+ yarn_libc?: string
15
+ }
16
+ >
17
+ > = {
18
+ 'x86_64-apple-darwin': {
19
+ host: 'macos-latest',
20
+ },
21
+ 'x86_64-pc-windows-msvc': {
22
+ host: 'windows-latest',
23
+ },
24
+ 'i686-pc-windows-msvc': {
25
+ host: 'windows-latest',
26
+ test: false,
27
+ },
28
+ 'x86_64-unknown-linux-gnu': {
29
+ host: 'ubuntu-latest',
30
+ build_image: 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian',
31
+ },
32
+ 'x86_64-unknown-linux-musl': {
33
+ host: 'ubuntu-latest',
34
+ build_image: 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine',
35
+ test_image: 'node:${{ matrix.node }}-alpine',
36
+ yarn_libc: 'musl',
37
+ },
38
+ 'aarch64-apple-darwin': {
39
+ host: 'macos-latest',
40
+ build_setup: [
41
+ 'sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*',
42
+ 'export CC=$(xcrun -f clang)',
43
+ 'export CXX=$(xcrun -f clang++)',
44
+ 'export SDK_ROOT=$(xcrun --sdk macosx --show-sdk-path)',
45
+ 'export CFLAGS="-isysroot $SDK_ROOT -isystem $SDK_ROOT"',
46
+ ],
47
+ test: false,
48
+ },
49
+ 'aarch64-unknown-linux-gnu': {
50
+ host: 'ubuntu-latest',
51
+ build_image: 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64',
52
+ build_setup: [
53
+ 'sudo apt-get update',
54
+ 'sudo apt-get install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu -y',
55
+ 'export CARGO_BUILD_TARGET=x86_64-unknown-linux-gnu',
56
+ ],
57
+ test_image: 'ghcr.io/napi-rs/napi-rs/nodejs:aarch64-${{ matrix.node }}',
58
+ yarn_cpu: 'arm64',
59
+ },
60
+ 'aarch64-unknown-linux-musl': {
61
+ host: 'ubuntu-latest',
62
+ build_image: 'ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine',
63
+ build_setup: ['rustup target add aarch64-unknown-linux-musl'],
64
+ test_image: 'multiarch/alpine:aarch64-latest-stable',
65
+ test_setup: ['apk add nodejs npm yarn'],
66
+ yarn_cpu: 'arm64',
67
+ yarn_libc: 'musl',
68
+ },
69
+ 'aarch64-pc-windows-msvc': {
70
+ host: 'windows-latest',
71
+ test: false,
72
+ },
73
+ 'armv7-unknown-linux-gnueabihf': {
74
+ host: 'ubuntu-latest',
75
+ build_setup: [
76
+ 'sudo apt-get update',
77
+ 'sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y',
78
+ ],
79
+ yarn_cpu: 'arm',
80
+ test_image: 'ghcr.io/napi-rs/napi-rs/nodejs:armhf-${{ matrix.node }}',
81
+ },
82
+ 'aarch64-linux-android': {
83
+ host: 'ubuntu-latest',
84
+ build_setup: [
85
+ 'export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"',
86
+ 'export CC="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang"',
87
+ 'export CXX="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++"',
88
+ 'export PATH="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}"',
89
+ ],
90
+ test: false,
91
+ },
92
+ 'armv7-linux-androideabi': {
93
+ host: 'ubuntu-latest',
94
+ build_setup: [
95
+ 'export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang"',
96
+ 'export CC="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang"',
97
+ 'export CXX="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++"',
98
+ 'export PATH="${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH}"',
99
+ ],
100
+ test: false,
101
+ },
102
+ }
@@ -0,0 +1,123 @@
1
+ import { merge, omit } from 'lodash-es'
2
+
3
+ import { fileExists, readFileAsync } from './misc.js'
4
+ import { DEFAULT_TARGETS, parseTriple, Target } from './target.js'
5
+
6
+ interface UserNapiConfig {
7
+ /**
8
+ * Name of the binary to be generated, default to `index`
9
+ */
10
+ binaryName?: string
11
+ /**
12
+ * Name of the npm package, default to the name of root package.json name
13
+ *
14
+ * Always given `@scope/pkg` and arch suffix will be appended like `@scope/pkg-linux-gnu-x64`
15
+ */
16
+ packageName?: string
17
+ /**
18
+ * All targets the crate will be compiled for
19
+ */
20
+ targets?: string[]
21
+
22
+ /**
23
+ * The npm client project uses.
24
+ */
25
+ npmClient?: string
26
+
27
+ /**
28
+ * @deprecated binaryName instead
29
+ */
30
+ name?: string
31
+ /**
32
+ * @deprecated use packageName instead
33
+ */
34
+ package?: {
35
+ name?: string
36
+ }
37
+ /**
38
+ * @deprecated use targets instead
39
+ */
40
+ triples?: {
41
+ /**
42
+ * Whether enable default targets
43
+ */
44
+ default: boolean
45
+ /**
46
+ * Additional targets to be compiled for
47
+ */
48
+ additional?: string[]
49
+ }
50
+ }
51
+
52
+ interface CommonPackageJsonFields {
53
+ name: string
54
+ version: string
55
+ description?: string
56
+ keywords?: string[]
57
+ author?: string
58
+ authors?: string[]
59
+ license?: string
60
+ repository?: any
61
+ homepage?: any
62
+ engines?: Record<string, string>
63
+ publishConfig?: any
64
+ bugs?: any
65
+ // eslint-disable-next-line no-use-before-define
66
+ napi?: UserNapiConfig
67
+ }
68
+
69
+ export type NapiConfig = Required<
70
+ Pick<UserNapiConfig, 'binaryName' | 'packageName' | 'npmClient'>
71
+ > & {
72
+ targets: Target[]
73
+ packageJson: CommonPackageJsonFields
74
+ }
75
+
76
+ export async function readNapiConfig(path: string): Promise<NapiConfig> {
77
+ if (!(await fileExists(path))) {
78
+ throw new Error(`napi-rs config not found at ${path}`)
79
+ }
80
+ // May support multiple config sources later on.
81
+ const content = await readFileAsync(path, 'utf8')
82
+ let pkgJson
83
+ try {
84
+ pkgJson = JSON.parse(content) as CommonPackageJsonFields
85
+ } catch (e) {
86
+ throw new Error('Failed to parse napi-rs config', {
87
+ cause: e,
88
+ })
89
+ }
90
+
91
+ const userNapiConfig = pkgJson.napi ?? {}
92
+ const napiConfig: NapiConfig = merge(
93
+ {
94
+ binaryName: 'index',
95
+ packageName: pkgJson.name,
96
+ targets: [],
97
+ packageJson: pkgJson,
98
+ npmClient: 'npm',
99
+ },
100
+ omit(userNapiConfig, 'targets'),
101
+ )
102
+
103
+ let targets: string[] = userNapiConfig.targets ?? []
104
+
105
+ // compatible with old config
106
+ if (userNapiConfig.package?.name) {
107
+ napiConfig.packageName = userNapiConfig.package.name
108
+ }
109
+
110
+ if (!targets.length) {
111
+ if (userNapiConfig.triples?.default) {
112
+ targets = targets.concat(DEFAULT_TARGETS)
113
+ }
114
+
115
+ if (userNapiConfig.triples?.additional?.length) {
116
+ targets = targets.concat(userNapiConfig.triples.additional)
117
+ }
118
+ }
119
+
120
+ napiConfig.targets = targets.map(parseTriple)
121
+
122
+ return napiConfig
123
+ }
@@ -0,0 +1,9 @@
1
+ export * from './ci.js'
2
+ export * from './log.js'
3
+ export * from './misc.js'
4
+ export * from './target.js'
5
+ export * from './version.js'
6
+ export * from './metadata.js'
7
+ export * from './config.js'
8
+ export * from './cargo.js'
9
+ export * from './typegen.js'
@@ -0,0 +1,34 @@
1
+ import * as colors from 'colorette'
2
+ import rawDebug from 'debug'
3
+
4
+ // debug('%i', 'This is an info')
5
+ rawDebug.formatters.i = (v) => {
6
+ return colors.green(v)
7
+ }
8
+
9
+ declare module 'debug' {
10
+ interface Debugger {
11
+ info: typeof console.error
12
+ warn: typeof console.error
13
+ error: typeof console.error
14
+ }
15
+ }
16
+
17
+ export const debugFactory = (namespace: string) => {
18
+ const debug = rawDebug(`napi:${namespace}`)
19
+
20
+ debug.info = (...args: any[]) =>
21
+ console.error(colors.black(colors.bgGreen(' INFO ')), ...args)
22
+ debug.warn = (...args: any[]) =>
23
+ console.error(colors.black(colors.bgYellow(' WARNING ')), ...args)
24
+ debug.error = (...args: any[]) =>
25
+ console.error(
26
+ colors.white(colors.bgRed(' ERROR ')),
27
+ ...args.map((arg) =>
28
+ arg instanceof Error ? arg.stack ?? arg.message : arg,
29
+ ),
30
+ )
31
+
32
+ return debug
33
+ }
34
+ export const debug = debugFactory('utils')
@@ -0,0 +1,59 @@
1
+ import { execSync } from 'child_process'
2
+ import fs from 'fs'
3
+
4
+ export type CrateTargetKind =
5
+ | 'bin'
6
+ | 'example'
7
+ | 'test'
8
+ | 'bench'
9
+ | 'lib'
10
+ | 'rlib'
11
+ | 'cdylib'
12
+ | 'custom-build'
13
+
14
+ export interface CrateTarget {
15
+ name: string
16
+ kind: CrateTargetKind[]
17
+ crate_types: CrateTargetKind[]
18
+ }
19
+
20
+ export interface Crate {
21
+ id: string
22
+ name: string
23
+ src_path: string
24
+ version: string
25
+ edition: string
26
+ targets: CrateTarget[]
27
+ features: Record<string, string[]>
28
+ manifest_path: string
29
+ }
30
+
31
+ export interface CargoWorkspaceMetadata {
32
+ version: number
33
+ packages: Crate[]
34
+ workspace_members: string[]
35
+ target_directory: string
36
+ workspace_root: string
37
+ }
38
+
39
+ export function parseMetadata(manifestPath: string) {
40
+ if (!fs.existsSync(manifestPath)) {
41
+ throw new Error(`No crate found in manifest: ${manifestPath}`)
42
+ }
43
+
44
+ const cmd = `cargo metadata --manifest-path ${manifestPath} --format-version 1 --no-deps`
45
+
46
+ try {
47
+ const output = execSync(cmd, {
48
+ encoding: 'utf-8',
49
+ })
50
+ return JSON.parse(output) as CargoWorkspaceMetadata
51
+ } catch (e) {
52
+ throw new Error(
53
+ `Failed to parse cargo metadata output by command: ${cmd}`,
54
+ {
55
+ cause: e,
56
+ },
57
+ )
58
+ }
59
+ }
@@ -0,0 +1,45 @@
1
+ import { readFile, writeFile, copyFile, mkdir, unlink, stat, readdir } from 'fs'
2
+ import { createRequire } from 'module'
3
+ import { promisify } from 'util'
4
+
5
+ import { debug } from './log.js'
6
+
7
+ const require = createRequire(import.meta.url)
8
+ const pkgJson = require('../../package.json')
9
+
10
+ export const readFileAsync = promisify(readFile)
11
+ export const writeFileAsync = promisify(writeFile)
12
+ export const unlinkAsync = promisify(unlink)
13
+ export const copyFileAsync = promisify(copyFile)
14
+ export const mkdirAsync = promisify(mkdir)
15
+ export const statAsync = promisify(stat)
16
+ export const readdirAsync = promisify(readdir)
17
+
18
+ export async function fileExists(path: string) {
19
+ const exists = await statAsync(path)
20
+ .then(() => true)
21
+ .catch(() => false)
22
+ return exists
23
+ }
24
+
25
+ export function pick<O, K extends keyof O>(o: O, ...keys: K[]): Pick<O, K> {
26
+ return keys.reduce((acc, key) => {
27
+ acc[key] = o[key]
28
+ return acc
29
+ }, {} as O)
30
+ }
31
+
32
+ export async function updatePackageJson(
33
+ path: string,
34
+ partial: Record<string, any>,
35
+ ) {
36
+ const exists = await fileExists(path)
37
+ if (!exists) {
38
+ debug(`File not exists ${path}`)
39
+ return
40
+ }
41
+ const old = require(path)
42
+ await writeFileAsync(path, JSON.stringify({ ...old, ...partial }, null, 2))
43
+ }
44
+
45
+ export const CLI_VERSION = pkgJson.version
@@ -0,0 +1,145 @@
1
+ import { execSync } from 'child_process'
2
+
3
+ export const AVAILABLE_TARGETS = [
4
+ 'aarch64-apple-darwin',
5
+ 'aarch64-linux-android',
6
+ 'aarch64-unknown-linux-gnu',
7
+ 'aarch64-unknown-linux-musl',
8
+ 'aarch64-pc-windows-msvc',
9
+ 'x86_64-apple-darwin',
10
+ 'x86_64-pc-windows-msvc',
11
+ 'x86_64-unknown-linux-gnu',
12
+ 'x86_64-unknown-linux-musl',
13
+ 'x86_64-unknown-freebsd',
14
+ 'i686-pc-windows-msvc',
15
+ 'armv7-unknown-linux-gnueabihf',
16
+ 'armv7-linux-androideabi',
17
+ 'universal-apple-darwin',
18
+ ] as const
19
+
20
+ export type TargetTriple = (typeof AVAILABLE_TARGETS)[number]
21
+
22
+ export const DEFAULT_TARGETS = [
23
+ 'x86_64-apple-darwin',
24
+ 'x86_64-pc-windows-msvc',
25
+ 'x86_64-unknown-linux-gnu',
26
+ ] as const
27
+
28
+ export const TARGET_LINKER: Record<string, string> = {
29
+ 'aarch64-unknown-linux-gnu': 'aarch64-linux-gnu-gcc',
30
+ 'armv7-unknown-linux-gnueabihf': 'arm-linux-gnueabihf-gcc',
31
+ 'aarch64-unknown-linux-musl': 'aarch64-linux-musl-gcc',
32
+ }
33
+
34
+ // https://nodejs.org/api/process.html#process_process_arch
35
+ type NodeJSArch =
36
+ | 'arm'
37
+ | 'arm64'
38
+ | 'ia32'
39
+ | 'mips'
40
+ | 'mipsel'
41
+ | 'ppc'
42
+ | 'ppc64'
43
+ | 's390'
44
+ | 's390x'
45
+ | 'x32'
46
+ | 'x64'
47
+ | 'universal'
48
+
49
+ const CpuToNodeArch: Record<string, NodeJSArch> = {
50
+ x86_64: 'x64',
51
+ aarch64: 'arm64',
52
+ i686: 'ia32',
53
+ armv7: 'arm',
54
+ }
55
+
56
+ export const NodeArchToCpu: Record<string, string> = {
57
+ x64: 'x86_64',
58
+ arm64: 'aarch64',
59
+ ia32: 'i686',
60
+ arm: 'armv7',
61
+ }
62
+
63
+ const SysToNodePlatform: Record<string, NodeJS.Platform> = {
64
+ linux: 'linux',
65
+ freebsd: 'freebsd',
66
+ darwin: 'darwin',
67
+ windows: 'win32',
68
+ }
69
+
70
+ export const UniArchsByPlatform: Partial<
71
+ Record<NodeJS.Platform, NodeJSArch[]>
72
+ > = {
73
+ darwin: ['x64', 'arm64'],
74
+ }
75
+
76
+ export interface Target {
77
+ triple: string
78
+ platformArchABI: string
79
+ platform: NodeJS.Platform
80
+ arch: NodeJSArch
81
+ abi: string | null
82
+ }
83
+
84
+ /**
85
+ * A triple is a specific format for specifying a target architecture.
86
+ * Triples may be referred to as a target triple which is the architecture for the artifact produced, and the host triple which is the architecture that the compiler is running on.
87
+ * The general format of the triple is `<arch><sub>-<vendor>-<sys>-<abi>` where:
88
+ * - `arch` = The base CPU architecture, for example `x86_64`, `i686`, `arm`, `thumb`, `mips`, etc.
89
+ * - `sub` = The CPU sub-architecture, for example `arm` has `v7`, `v7s`, `v5te`, etc.
90
+ * - `vendor` = The vendor, for example `unknown`, `apple`, `pc`, `nvidia`, etc.
91
+ * - `sys` = The system name, for example `linux`, `windows`, `darwin`, etc. none is typically used for bare-metal without an OS.
92
+ * - `abi` = The ABI, for example `gnu`, `android`, `eabi`, etc.
93
+ */
94
+ export function parseTriple(rawTriple: string): Target {
95
+ const triple = rawTriple.endsWith('eabi')
96
+ ? `${rawTriple.slice(0, -4)}-eabi`
97
+ : rawTriple
98
+ const triples = triple.split('-')
99
+ let cpu: string
100
+ let sys: string
101
+ let abi: string | null = null
102
+ if (triples.length === 2) {
103
+ // aarch64-fuchsia
104
+ // ^ cpu ^ sys
105
+ ;[cpu, sys] = triples
106
+ } else {
107
+ // aarch64-unknown-linux-musl
108
+ // ^ cpu ^ sys ^ abi
109
+ // aarch64-apple-darwin
110
+ // ^ cpu ^ sys (abi is None)
111
+ ;[cpu, , sys, abi = null] = triples
112
+ }
113
+
114
+ const platform = SysToNodePlatform[sys] ?? (sys as NodeJS.Platform)
115
+ const arch = CpuToNodeArch[cpu] ?? (cpu as NodeJSArch)
116
+ return {
117
+ triple: rawTriple,
118
+ platformArchABI: abi ? `${platform}-${arch}-${abi}` : `${platform}-${arch}`,
119
+ platform,
120
+ arch,
121
+ abi,
122
+ }
123
+ }
124
+
125
+ export function getSystemDefaultTarget(): Target {
126
+ const host = execSync(`rustc -vV`, {
127
+ env: process.env,
128
+ })
129
+ .toString('utf8')
130
+ .split('\n')
131
+ .find((line) => line.startsWith('host: '))
132
+ const triple = host?.slice('host: '.length)
133
+ if (!triple) {
134
+ throw new TypeError(`Can not parse target triple from host`)
135
+ }
136
+ return parseTriple(triple)
137
+ }
138
+
139
+ export function getTargetLinker(target: string): string | undefined {
140
+ return TARGET_LINKER[target]
141
+ }
142
+
143
+ export function targetToEnvVar(target: string): string {
144
+ return target.replace(/-/g, '_').toUpperCase()
145
+ }