@flun/nodejs-mobile-gyp 1.0.2 → 1.1.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.
package/README.md CHANGED
@@ -1,256 +1,362 @@
1
- # @flun/nodejs-mobile-gyp
2
-
3
- 移动端 Node.js 原生模块(Native Addon)的交叉编译工具。
4
-
5
- 用于为 [nodejs-mobile](https://github.com/nodejs-mobile/nodejs-mobile) 环境编译 C/C++ 原生模块,支持 Android 与 iOS 的交叉编译。
6
-
7
- [`@flun/nodejs-mobile-react-native`](https://www.npmjs.com/package/@flun/nodejs-mobile-react-native) 在构建时会自动调用本包,无需手动安装。
8
-
9
- 本包是 [`nodejs-mobile-gyp`](https://github.com/nodejs-mobile/nodejs-mobile-gyp) 的 flun fork,后者又基于上游 [`node-gyp`](https://github.com/nodejs/node-gyp)。
10
-
11
- - GitHub:https://github.com/OpenFlun/nodejs-mobile-gyp
12
- - gitee: https://gitee.com/OpenFlun/nodejs-mobile-gyp
13
- - npm:https://www.npmjs.com/package/@flun/nodejs-mobile-gyp
14
-
15
- ## 项目结构
16
-
17
- ```txt
18
- @flun/nodejs-mobile-gyp/
19
- │
20
- ├── bin/
21
- │ └── node-gyp.js # CLI 入口(#!/usr/bin/env node),创建 Gyp 实例并依次执行命令队列
22
- │
23
- ├── lib/ # 核心实现,全部为 ESM
24
- │ ├── node-gyp.js # Gyp 主类:参数解析、命令分发、usage 生成
25
- │ ├── build.js # build 命令:调用 make / msbuild 编译原生模块
26
- │ ├── clean.js # clean 命令:删除 build 目录
27
- │ ├── configure.js # configure 命令:下载 headers、生成 config.gypi 与工程文件
28
- │ ├── rebuild.js # rebuild 命令:依次执行 clean + configure + build
29
- │ ├── install.js # install 命令:下载并解压指定版本的 Node 开发文件
30
- │ ├── remove.js # remove 命令:删除指定版本的 Node 开发文件
31
- │ ├── list.js # list 命令:列出已安装的 Node 开发文件版本
32
- │ ├── create-config-gypi.js # 生成 config.gypi;Windows 上强制 MSVC 工具集、关闭 LTO
33
- │ ├── process-release.js # 解析下载 URL、本地目录名、headers 与 node.lib 地址
34
- │ ├── download.js # 基于 make-fetch-happen 的 HTTP 下载与 CA 读取
35
- │ ├── find-node-directory.js # 推断 Node 安装根目录(用于 AIX / zOS)
36
- │ ├── find-python.js # PythonFinder 类:按顺序定位可用的 Python 3.6+
37
- │ ├── find-visualstudio.js # VisualStudioFinder 类:定位可用的 VS 安装(含 VS2026)
38
- │ ├── Find-VisualStudio.cs # PowerShell 调用的 C# 脚本,枚举 VS 安装信息
39
- │ ├── log.js # Logger 类 + proc-log 包装,分级着色日志
40
- │ └── util.js # 通用工具:execFile 包装、注册表读取、候选文件查找
41
- │
42
- ├── gyp/ # 内置的 gyp 工具(Python)
43
- │ ├── gyp # Python 启动脚本(Unix)
44
- │ ├── gyp.bat # Python 启动脚本(Windows)
45
- │ ├── gyp_main.py # gyp 主入口
46
- │ ├── LICENSE # gyp 自身的许可证
47
- │ ├── pylib/gyp/ # gyp 核心 Python 模块
48
- │ │ ├── input.py # 解析 .gyp / .gypi 文件
49
- │ │ ├── common.py # 通用工具
50
- │ │ ├── MSVS*.py # MSBuild / VS 工程生成
51
- │ │ ├── msvs_emulation.py # VS 配置模拟
52
- │ │ ├── xcode*.py # Xcode 工程生成
53
- │ │ ├── mac_tool.py # macOS 工具链
54
- │ │ ├── win_tool.py # Windows 工具链
55
- │ │ └── generator/ # 各类生成器后端(make / msvs / ninja / xcode / cmake ...)
56
- │ ├── pylib/packaging/ # gyp 依赖的 Python packaging 库(vendored)
57
- │ └── data/win/
58
- │ └── large-pdb-shim.cc # Windows 大 PDB 兼容编译单元
59
- │
60
- ├── src/
61
- │ └── win_delay_load_hook.cc # Windows 加载延迟钩子(编译进每个原生模块)
62
- │
63
- ├── addon.gypi # 所有原生模块共用的 gyp 配置
64
- ├── package.json # type: module,bin 命令名为 nodejs-mobile-gyp
65
- ├── LICENSE # 本包许可证(ISC)
66
- ├── README.md # 本文件
67
- ├── CHANGELOG.md # 版本变更记录
68
- ├── .gitignore # Git 忽略规则
69
- ├── .npmignore # npm 发布排除规则
70
- ├── .gitattributes # Git 换行符 / 二进制标记
71
- └── macOS_Catalina_acid_test.sh # macOS Catalina 兼容性验证脚本(仅本地开发,不随包发布)
72
- ```
73
-
74
- ## 本 fork 的改动
75
-
76
- 本 fork 在功能上与原版 `nodejs-mobile-gyp` 一致,做了以下改造。
77
-
78
- ### 代码风格
79
-
80
- | 项 | 原版 | 本 fork |
81
- | -------- | ----------------------- | --------------------------------------------- |
82
- | 模块系统 | CommonJS | **ESM**(`package.json` 的 `type: "module"`) |
83
- | 导出方式 | 文件内 `module.exports` | **末尾统一 `export { ... }`** |
84
- | 函数声明 | `async function xxx` | `const xxx = async () =>`(`class` 保留) |
85
- | 注释 | 英文 | 中文 |
86
-
87
- ### 依赖升级
88
-
89
- | 包 | 原版 | 本 fork | 原因 |
90
- | ------------------- | ---------- | --------- | -------------------------------------------- |
91
- | `tar` | `^6.1.2` | `^7.5.22` | 上游 v6 停更,有安全公告 |
92
- | `glob` | `^10.3.10` | `^13.0.6` | 上游 v10 停更 |
93
- | `make-fetch-happen` | `^13.0.0` | `^16.0.1` | 连带升级 `cacache`,去掉 `tar@6` / `glob@10` |
94
-
95
- 升级后依赖树干净,`npm audit` 0 vulnerabilities。
96
-
97
- ### Windows 构建适配
98
-
99
- 原版在 Windows 上默认走 ClangCL 工具集,且继承 Node 官方二进制的 LTO 配置。Node.js 24+ 官方二进制由 ClangCL + ThinLTO 编译,其 `common.gypi` 会在 `clang==1` 时把 MSBuild 工具集设为 `ClangCL`,并在 `enable_lto==true` / `enable_thin_lto==true` 时向链接器传入 `-flto=thin`、`/opt:lldltojobs` 等 Clang 专用参数。若用户本机没装 ClangCL,或用的是传统 MSVC 工具链,会报以下错误:
100
-
101
- - `MSB8020: 无法找到 ClangCL 的生成工具`
102
- - `LNK1117: 选项"opt:lldltojobs=2"中的语法错误`
103
-
104
- 本 fork 强制走 MSVC 工具集并关闭 LTO,避免上述报错。
105
-
106
- ### 具体改动清单
107
-
108
- | 文件 | 改动 |
109
- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
110
- | `lib/create-config-gypi.js` | 生成 `config.gypi` 时,把 `clang` 置 0,`enable_lto` / `enable_thin_lto` 置 `'false'`,`lto_jobs` 置空。避免 `common.gypi` 把工具集改成 ClangCL、向 MSVC 传 LTO 参数 |
111
- | `lib/configure.js` | 调用 gyp 时追加 `-Gmsvs_toolset=v145`,显式指定 VS2026 工具集 |
112
- | `lib/find-visualstudio.js` | 支持 VS2026(版本号 18,`versionYear=2026`,toolset `v145`) |
113
-
114
- ### 兼容性与健壮性修复
115
-
116
- - **`proc-log` 新版本兼容**:新版 `proc-log` 的日志级别函数与 `pause` / `resume` 挂在默认导出的 `log` 对象下,而非包顶层。本 fork 已按此调整 `lib/log.js`,否则在 `configure` 阶段会直接抛出 `TypeError`。
117
- - **弃用 API 清理**:`lib/process-release.js` 不再使用 `url.resolve()` / `url.parse()`,改用 WHATWG `URL`,消除新版 Node 的 `DEP0169` 弃用警告。
118
- - **外部头文件警告抑制**:Windows 下,Node 官方 V8 头文件会触发 `warning C4018` 等噪音。本 fork 通过 `ExternalWarningLevel` 属性 + `/external:anglebrackets`,只对 `#include <...>` 引入的 Node / V8 头文件静音,**不影响下游自己代码的警告**;同时避免与 MSBuild 默认设置冲突而产生的命令行警告。
119
- - **依赖脚本放行**:针对新版 npm 默认禁止依赖执行安装脚本的行为,`package.json` 显式声明 `allowScripts`,保证安装脚本正常执行。
120
-
121
- ### 迁移踩过的坑
122
-
123
- 1. **`graceful-fs` 是 CJS,命名导入会失败**
124
- 写成 `import gracefulFs from 'graceful-fs'`,再从 default 解构 `const { openSync, closeSync } = gracefulFs`。
125
-
126
- 2. **`tar@7` 没有 default export**
127
- 写成 `import * as tar from 'tar'`。
128
-
129
- 3. **`proc-log` 的解构**
130
- `import procLog from 'proc-log'`,再把需要的函数从 default 里解构后统一导出。
131
-
132
- 4. **PowerShell 写文件会加 BOM**
133
- `Set-Content -Encoding UTF8` 会写入 `\uFEFF`,导致 gyp 的 `eval()` 报 `SyntaxError: invalid non-printable character U+FEFF`。写 `binding.gyp` 等交给 Python eval 的文件时,用 `[System.IO.File]::WriteAllText` + `New-Object System.Text.UTF8Encoding $false`。
134
-
135
- 5. **ESM 不支持动态 `require('./' + command)`**
136
- `lib/node-gyp.js` 原本用 `require('./' + command)` 动态加载命令模块,ESM 下改为在顶部静态 import 所有命令,再用静态映射表组装 `this.commands`。
137
-
138
- 6. **`__dirname` / `__filename` 在 ESM 中不存在**
139
- 用 `fileURLToPath(import.meta.url)` 重建。
140
-
141
- 7. **非 Windows 平台不引入 `find-visualstudio.js`**
142
- 该模块依赖 Windows 专属的 `path.win32` 和注册表操作,保持原版的"仅在 Windows 上条件加载"逻辑。
143
-
144
- ## 安装
145
-
146
- ```bash
147
- npm install @flun/nodejs-mobile-gyp
148
- ```
149
-
150
- 通常你不需要手动安装本包——它由 [`@flun/nodejs-mobile-react-native`](https://www.npmjs.com/package/@flun/nodejs-mobile-react-native) 在编译原生模块时自动调用。
151
-
152
- > **Node 版本要求**:本 fork 的依赖链(`make-fetch-happen`、`nopt`、`proc-log`、`which` 等)已升级到较新版本,要求比原版 `nodejs-mobile-gyp` 更高的 Node。具体最低版本见 `package.json` 的 `engines.node` 字段。若你的项目仍在使用较旧的 Node,请改用原版 `nodejs-mobile-gyp`。
153
-
154
- ## 使用
155
-
156
- ### 命令行
157
-
158
- ```bash
159
- npx @flun/nodejs-mobile-gyp <command> [options]
160
- ```
161
-
162
- 或在 `package.json` 的 `scripts` 中调用:
163
-
164
- ```json
165
- {
166
- "scripts": {
167
- "build-addon": "nodejs-mobile-gyp rebuild"
168
- }
169
- }
170
- ```
171
-
172
- ### 从 Node.js 代码调用
173
-
174
- 本包主要作为 CLI 工具使用,推荐通过 spawn / execFile 调用其命令行入口。包本身也导出了 Gyp 类,但属于内部实现,接口可能随版本变化,不建议直接在代码中依赖。
175
-
176
- ## 命令
177
-
178
- | 命令 | 说明 |
179
- | ----------- | ---------------------------------------- |
180
- | `help` | 显示帮助 |
181
- | `build` | 调用 `make` / `msbuild.exe` 编译原生模块 |
182
- | `clean` | 删除 `build` 目录(若存在) |
183
- | `configure` | 为当前平台生成工程构建文件 |
184
- | `rebuild` | 依次执行 `clean` → `configure` → `build` |
185
- | `install` | 为指定版本安装 Node.js 头文件 |
186
- | `list` | 列出已安装的 Node.js 头文件版本 |
187
- | `remove` | 删除指定版本的 Node.js 头文件 |
188
-
189
- ## 命令选项
190
-
191
- | 选项 | 说明 |
192
- | --------------------------------- | -------------------------------------------------- |
193
- | `-v`, `--version` | 打印本包版本号 |
194
- | `-j n`, `--jobs n` | 并行运行 `make`;`max` 表示使用所有 CPU 核心 |
195
- | `--target=v6.2.1` | 目标 Node.js 版本(默认 `process.version`) |
196
- | `--silly`, `--loglevel=silly` | 输出全部进度日志 |
197
- | `--verbose`, `--loglevel=verbose` | 输出大部分进度日志 |
198
- | `--silent`, `--loglevel=silent` | 不输出任何日志 |
199
- | `debug`, `--debug` | 生成 Debug 构建(默认 Release) |
200
- | `--release`, `--no-debug` | 生成 Release 构建 |
201
- | `-C $dir`, `--directory=$dir` | 在指定目录运行命令 |
202
- | `--make=$make` | 覆盖 `make` 命令(如 `gmake`) |
203
- | `--thin=yes` | 启用 thin 静态库 |
204
- | `--arch=$arch` | 目标架构(如 `ia32`) |
205
- | `--tarball=$path` | 从本地 tarball 获取头文件 |
206
- | `--devdir=$path` | SDK 下载目录(默认为系统缓存目录) |
207
- | `--ensure` | 已存在的头文件不重装 |
208
- | `--dist-url=$url` | 从自定义 URL 下载头文件 tarball |
209
- | `--proxy=$url` | 下载时使用 HTTP(S) 代理 |
210
- | `--noproxy=$urls` | 下载时忽略代理的 URL 列表 |
211
- | `--cafile=$cafile` | 覆盖默认 CA 链(用于下载 tarball) |
212
- | `--nodedir=$path` | 指定 Node 源码路径 |
213
- | `--python=$path` | 指定 Python 二进制路径 |
214
- | `--msvs_version=$version` | 指定 Visual Studio 版本(仅 Windows) |
215
- | `--solution=$solution` | 指定 Visual Studio Solution 版本(仅 Windows) |
216
- | `--force-process-config` | 强制用运行时的 `process.config` 生成 `config.gypi` |
217
-
218
- ## 配置
219
-
220
- ### 环境变量
221
-
222
- 上表中的所有命令选项,都可以用 `npm_config_OPTION_NAME` 形式的**环境变量**来设置(选项名中的 `-` 替换为 `_`)。
223
-
224
- 例如,把 `devdir` 设为 `/tmp/.gyp`:
225
-
226
- Unix:
227
- ```bash
228
- export npm_config_devdir=/tmp/.gyp
229
- ```
230
-
231
- Windows:
232
- ```console
233
- set npm_config_devdir=c:\temp\.gyp
234
- ```
235
-
236
- ### npm 配置(npm v9 之前)
237
-
238
- 用 `OPTION_NAME` 形式:
239
-
240
- ```bash
241
- npm config set [--global] devdir /tmp/.gyp
242
- ```
243
-
244
- **注意**:通过 `npm config` 设置的配置,只在本包 **由 npm 调用时**生效,直接运行 `nodejs-mobile-gyp` 不生效。
245
-
246
- ## 上游参考
247
-
248
- 本包是 `node-gyp` 的 fork。上游完整文档(含更多高级用法、`binding.gyp` 语法、跨平台细节)请见:
249
-
250
- - [nodejs/node-gyp README](https://github.com/nodejs/node-gyp#readme)
251
- - [gyp 用户文档](https://gyp.gsrc.io/docs/UserDocumentation.md)
252
- - [gyp 输入格式参考](https://gyp.gsrc.io/docs/InputFormatReference.md)
253
-
254
- ## 许可
255
-
256
- ISC
1
+ # @flun/nodejs-mobile-gyp
2
+
3
+ 移动端 Node.js 原生模块(Native Addon)的交叉编译工具。
4
+
5
+ 用于为 [nodejs-mobile](https://github.com/nodejs-mobile/nodejs-mobile) 环境编译 C/C++ 原生模块,支持 Android 与 iOS 的交叉编译。
6
+
7
+ 宿主平台支持 **Windows** / **macOS** / **Linux**,各平台所需的环境与工具见「[支持的系统与配置要求](#支持的系统与配置要求)」。
8
+
9
+ [`@flun/nodejs-mobile-react-native`](https://www.npmjs.com/package/@flun/nodejs-mobile-react-native) 在构建时会自动调用本包,无需手动安装。
10
+
11
+ 本包是 [`nodejs-mobile-gyp`](https://github.com/nodejs-mobile/nodejs-mobile-gyp) 的 flun fork,后者又基于上游 [`node-gyp`](https://github.com/nodejs/node-gyp)。
12
+
13
+ - GitHub:https://github.com/OpenFlun/nodejs-mobile-gyp
14
+ - gitee: https://gitee.com/OpenFlun/nodejs-mobile-gyp
15
+ - npm:https://www.npmjs.com/package/@flun/nodejs-mobile-gyp
16
+
17
+ ## 项目结构
18
+
19
+ ```txt
20
+ @flun/nodejs-mobile-gyp/
21
+ │
22
+ ├── bin/
23
+ │ └── node-gyp.js # CLI 入口(#!/usr/bin/env node),创建 Gyp 实例并依次执行命令队列
24
+ │
25
+ ├── lib/ # 核心实现,全部为 ESM
26
+ │ ├── node-gyp.js # Gyp 主类:参数解析、命令分发、usage 生成
27
+ │ ├── build.js # build 命令:调用 make / msbuild 编译原生模块
28
+ │ ├── clean.js # clean 命令:删除 build 目录
29
+ │ ├── configure.js # configure 命令:下载 headers、生成 config.gypi 与工程文件
30
+ │ ├── rebuild.js # rebuild 命令:依次执行 clean + configure + build
31
+ │ ├── install.js # install 命令:下载并解压指定版本的 Node 开发文件
32
+ │ ├── remove.js # remove 命令:删除指定版本的 Node 开发文件
33
+ │ ├── list.js # list 命令:列出已安装的 Node 开发文件版本
34
+ │ ├── create-config-gypi.js # 生成 config.gypi;Windows 上强制 MSVC 工具集、关闭 LTO
35
+ │ ├── process-release.js # 解析下载 URL、本地目录名、headers 与 node.lib 地址
36
+ │ ├── download.js # 基于 make-fetch-happen 的 HTTP 下载与 CA 读取
37
+ │ ├── find-node-directory.js # 推断 Node 安装根目录(用于 AIX / zOS)
38
+ │ ├── find-python.js # PythonFinder 类:动态定位 Python 3.6+(py 启动器 / 目录扫描)
39
+ │ ├── find-visualstudio.js # VisualStudioFinder 类:定位可用的 VS 安装(VS2013+,含 VS2026)
40
+ │ ├── Find-VisualStudio.cs # PowerShell 调用的 C# 脚本,枚举 VS 安装信息
41
+ │ ├── log.js # Logger 类 + proc-log 包装,分级着色日志
42
+ │ └── util.js # 通用工具:execFile 包装、注册表读取、候选文件查找
43
+ │
44
+ ├── gyp/ # 内置的 gyp 工具(Python)
45
+ │ ├── gyp # Python 启动脚本(Unix)
46
+ │ ├── gyp.bat # Python 启动脚本(Windows)
47
+ │ ├── gyp_main.py # gyp 主入口
48
+ │ ├── LICENSE # gyp 自身的许可证
49
+ │ ├── pylib/gyp/ # gyp 核心 Python 模块
50
+ │ │ ├── input.py # 解析 .gyp / .gypi 文件
51
+ │ │ ├── common.py # 通用工具
52
+ │ │ ├── MSVS*.py # MSBuild / VS 工程生成
53
+ │ │ ├── msvs_emulation.py # VS 配置模拟
54
+ │ │ ├── xcode*.py # Xcode 工程生成
55
+ │ │ ├── mac_tool.py # macOS 工具链
56
+ │ │ ├── win_tool.py # Windows 工具链
57
+ │ │ └── generator/ # 各类生成器后端(make / msvs / ninja / xcode / cmake ...)
58
+ │ ├── pylib/packaging/ # gyp 依赖的 Python packaging 库(vendored)
59
+ │ └── data/win/
60
+ │ └── large-pdb-shim.cc # Windows 大 PDB 兼容编译单元
61
+ │
62
+ ├── src/
63
+ │ └── win_delay_load_hook.cc # Windows 加载延迟钩子(编译进每个原生模块)
64
+ │
65
+ ├── addon.gypi # 所有原生模块共用的 gyp 配置
66
+ ├── package.json # type: module,bin 命令名为 nodejs-mobile-gyp
67
+ ├── LICENSE # 本包许可证(ISC)
68
+ ├── README.md # 本文件
69
+ ├── CHANGELOG.md # 版本变更记录
70
+ ├── .gitignore # Git 忽略规则
71
+ ├── .npmignore # npm 发布排除规则
72
+ ├── .gitattributes # Git 换行符 / 二进制标记
73
+ └── macOS_Catalina_acid_test.sh # macOS Catalina 兼容性验证脚本(仅本地开发,不随包发布)
74
+ ```
75
+
76
+ ## 本 fork 的改动
77
+
78
+ 本 fork 在功能上与原版 `nodejs-mobile-gyp` 一致,做了以下改造。
79
+
80
+ ### 代码风格
81
+
82
+ | 项 | 原版 | 本 fork |
83
+ | -------- | ----------------------- | --------------------------------------------- |
84
+ | 模块系统 | CommonJS | **ESM**(`package.json` 的 `type: "module"`) |
85
+ | 导出方式 | 文件内 `module.exports` | **末尾统一 `export { ... }`** |
86
+ | 函数声明 | `async function xxx` | `const xxx = async () =>`(`class` 保留) |
87
+ | 注释 | 英文 | 中文 |
88
+
89
+ ### 依赖升级
90
+
91
+ | 包 | 原版 | 本 fork | 原因 |
92
+ | ------------------- | ---------- | --------- | -------------------------------------------- |
93
+ | `tar` | `^6.1.2` | `^7.5.22` | 上游 v6 停更,有安全公告 |
94
+ | `glob` | `^10.3.10` | `^13.0.6` | 上游 v10 停更 |
95
+ | `make-fetch-happen` | `^13.0.0` | `^16.0.1` | 连带升级 `cacache`,去掉 `tar@6` / `glob@10` |
96
+
97
+ 升级后依赖树干净,`npm audit` 0 vulnerabilities。
98
+
99
+ ### Windows 构建适配
100
+
101
+ 原版 `nodejs-mobile-gyp` 在 Windows 上有若干问题,本 fork 逐一解决,涉及三方面。
102
+
103
+ #### 1. 工具集与 LTO
104
+
105
+ 原版默认走 ClangCL 工具集,且继承 Node 官方二进制的 LTO 配置。Node.js 24+ 官方二进制由 ClangCL + ThinLTO 编译,其 `common.gypi` 会在 `clang==1` 时把 MSBuild 工具集设为 `ClangCL`,并在 `enable_lto==true` / `enable_thin_lto==true` 时向链接器传入 `-flto=thin`、`/opt:lldltojobs` 等 Clang 专用参数。若用户本机没装 ClangCL,或用的是传统 MSVC 工具链,会报:
106
+
107
+ - `MSB8020: 无法找到 ClangCL 的生成工具`
108
+ - `LNK1117: 选项"opt:lldltojobs=2"中的语法错误`
109
+
110
+ 本 fork 强制走 MSVC 工具集并关闭 LTO,避免上述报错。工具集版本从 `find-visualstudio` 的探测结果**动态获取**(`v140` / `v141` / `v142` / `v143` / `v145`...),不写死。
111
+
112
+ #### 2. GNU make 的 POSIX 环境
113
+
114
+ Android 原生模块通过 GNU make 构建,其 Makefile 会调用 `printf`、`xargs`、`sed` 等 Unix 命令。GNU make 需要一个 POSIX shell(`sh.exe`)来执行它们;Windows 上若无,会直接报 `CreateProcess(NULL, printf ...) failed`。本 fork 自动定位 Git for Windows 的 `usr/bin` 并前置到 PATH,详见「[支持的系统与配置要求](#支持的系统与配置要求) → 自动探测」。
115
+
116
+ #### 3. 路径分隔符
117
+
118
+ gyp 生成的 Makefile 中,路径原本会带上 Windows 的反斜杠(如 `src\bufferutil.o`),导致 `sh` / `sed` / `make` 解析失败。本 fork 在 gyp 的路径生成环节统一转成正斜杠;该改动在非 Windows 平台上是 no-op。
119
+
120
+ ### 具体改动清单
121
+
122
+ #### 构建工具链
123
+
124
+ | 文件 | 改动 |
125
+ | --- | --- |
126
+ | `lib/create-config-gypi.js` | 生成 `config.gypi` 时把 `clang` 置 0、`enable_lto` / `enable_thin_lto` 置 `'false'`、`lto_jobs` 置空,避免 `common.gypi` 切到 ClangCL 并向 MSVC 传 LTO 参数 |
127
+ | `lib/configure.js` | 调用 gyp 时追加 `-Gmsvs_toolset=<探测到的 toolset>`,不再写死 `v145` |
128
+ | `lib/find-visualstudio.js` | 支持 VS2013+,含最新 VS2026(版本号 18,`versionYear=2026`,toolset `v145`) |
129
+ | `gyp/pylib/gyp/MSVSSettings.py` | 注册 `ExternalWarningLevel`(MSBuild 属性),供 `addon.gypi` 使用 |
130
+ | `addon.gypi` | Windows 下追加 `/external:anglebrackets` + `ExternalWarningLevel: TurnOffAllWarnings`,只静音外部头(Node / V8)的警告 |
131
+
132
+ #### 跨平台路径
133
+
134
+ | 文件 | 改动 |
135
+ | --- | --- |
136
+ | `gyp/pylib/gyp/common.py` | `RelativePath` 返回值统一转正斜杠 |
137
+ | `gyp/pylib/gyp/generator/make.py` | `Absolutify` 返回正斜杠;新增 `slashpath` 供 `mkdir` 使用;Windows 下跳过 `node_modules` 中的超长 gypi 依赖 |
138
+
139
+ #### Windows 运行时探测
140
+
141
+ | 文件 | 改动 |
142
+ | --- | --- |
143
+ | `lib/find-python.js` | 重写:移除硬编码版本列表,改为 `py.exe` 候选 + `py -0p` 枚举 + 目录扫描;`run()` 显式检查 `execFile` 的 err |
144
+ | `lib/build.js` | 区分「宿主 Windows」与「Android 交叉编译」;自动探测 `sh.exe` 并前置到 PATH;为 Python 创建 `python3.cmd` shim |
145
+
146
+ #### 兼容性与健壮性
147
+
148
+ - **`proc-log` 新版本兼容**:新版把日志级别函数与 `pause` / `resume` 挂在默认导出的 `log` 对象下。本 fork 已按此调整 `lib/log.js`,否则 `configure` 阶段会抛 `TypeError`。
149
+ - **弃用 API 清理**:`lib/process-release.js` 不再用 `url.resolve()` / `url.parse()`,改用 WHATWG `URL`,消除 `DEP0169` 警告。
150
+ - **依赖脚本放行**:`package.json` 显式声明 `allowScripts`,适配新版 npm 默认禁止依赖执行安装脚本的行为。
151
+
152
+
153
+ ### 迁移踩过的坑
154
+
155
+ 1. **`graceful-fs` 是 CJS,命名导入会失败**
156
+ 写成 `import gracefulFs from 'graceful-fs'`,再从 default 解构 `const { openSync, closeSync } = gracefulFs`。
157
+
158
+ 2. **`tar@7` 没有 default export**
159
+ 写成 `import * as tar from 'tar'`。
160
+
161
+ 3. **`proc-log` 的解构**
162
+ `import procLog from 'proc-log'`,再把需要的函数从 default 里解构后统一导出。
163
+
164
+ 4. **PowerShell 写文件会加 BOM**
165
+ `Set-Content -Encoding UTF8` 会写入 `\uFEFF`,导致 gyp 的 `eval()` 报 `SyntaxError: invalid non-printable character U+FEFF`。写 `binding.gyp` 等交给 Python eval 的文件时,用 `[System.IO.File]::WriteAllText` + `New-Object System.Text.UTF8Encoding $false`。
166
+
167
+ 5. **ESM 不支持动态 `require('./' + command)`**
168
+ `lib/node-gyp.js` 原本用 `require('./' + command)` 动态加载命令模块,ESM 下改为在顶部静态 import 所有命令,再用静态映射表组装 `this.commands`。
169
+
170
+ 6. **`__dirname` / `__filename` 在 ESM 中不存在**
171
+ 用 `fileURLToPath(import.meta.url)` 重建。
172
+
173
+ 7. **非 Windows 平台不引入 `find-visualstudio.js`**
174
+ 该模块依赖 Windows 专属的 `path.win32` 和注册表操作,保持原版的"仅在 Windows 上条件加载"逻辑。
175
+
176
+ ## 支持的系统与配置要求
177
+
178
+ 本包面向 **Android / iOS 交叉编译**,宿主平台支持情况:
179
+
180
+ | 宿主平台 | 目标:Android | 目标:iOS |
181
+ | -------- | ------------- | ---------- |
182
+ | Windows | ✅ 完整支持 | ❌ 需 macOS |
183
+ | macOS | ✅ 完整支持 | ✅ 完整支持 |
184
+ | Linux | ✅ 完整支持 | ❌ 需 macOS |
185
+
186
+ 各平台所需的构建环境如下。
187
+
188
+ ### 通用要求
189
+
190
+ - **Node.js**:最低版本见 `package.json` 的 `engines.node` 字段
191
+ - **Python 3.6+**:gyp 本身是 Python 程序,构建时必需
192
+ - **目标平台 SDK**:
193
+ - Android:Android NDK(已在 NDK **27.x** 上验证)
194
+ - iOS:Xcode Command Line Tools(仅 macOS)
195
+
196
+ ### Windows
197
+
198
+ | 组件 | 要求 | 说明 |
199
+ | --------------- | --------------------------------------- | ----------------------------------------------------------- |
200
+ | Node.js | 见 `engines.node` | |
201
+ | Python | 3.6+ | 支持任意安装位置,见下方「自动探测」 |
202
+ | Visual Studio | **VS2026**(版本号 18,toolset `v145`) | 需勾选「使用 C++ 的桌面开发」工作负载,含 Windows SDK |
203
+ | Android NDK | 27.x(已验证) | 由 `@flun/nodejs-mobile-react-native` 自动定位 |
204
+ | Git for Windows | 任意近期版本 | 提供 make 所需的 `sh.exe` / `printf` / `xargs` 等 Unix 工具 |
205
+
206
+ > **为什么需要 Git for Windows?** Android 原生模块通过 GNU make 构建,Makefile 中会调用 `printf`、`xargs`、`sed` 等 Unix 命令。GNU make 需要一个 POSIX shell(`sh.exe`)来执行它们,而 Git for Windows 自带完整的这套工具链,无需额外安装 MSYS2 或 Cygwin。
207
+
208
+ ### macOS
209
+
210
+ | 组件 | 要求 |
211
+ | ----------- | -------------------------------- |
212
+ | Node.js | 见 `engines.node` |
213
+ | Python | 3.6+ |
214
+ | Xcode | 完整 Xcode 或 Command Line Tools |
215
+ | Android NDK | 仅构建 Android 目标时需 27.x |
216
+
217
+ ### Linux
218
+
219
+ | 组件 | 要求 |
220
+ | ----------- | ------------------------------------------------------ |
221
+ | Node.js | 见 `engines.node` |
222
+ | Python | 3.6+ |
223
+ | 构建工具 | `make`、`g++`(`apt install build-essential python3`) |
224
+ | Android NDK | 仅构建 Android 目标时需 27.x |
225
+
226
+ ### 自动探测(Windows)
227
+
228
+ Windows 上以下路径 / 版本由本包动态探测,**无需手动配置**:
229
+
230
+ - **Python**,依次尝试:
231
+ 1. `NODE_GYP_FORCE_PYTHON` 环境变量
232
+ 2. 命令行 `--python=`
233
+ 3. `PYTHON` 环境变量
234
+ 4. `py.exe` 启动器(PATH 中、`%SystemRoot%\py.exe`、`%SystemRoot%\System32\py.exe`)
235
+ 5. `py -0p` 枚举所有已注册 Python
236
+ 6. `python3` / `python` 命令
237
+ 7. 扫描 `%LOCALAPPDATA%\Programs\Python\Python*` 与 `%ProgramFiles%\Python*`
238
+
239
+ - **POSIX shell(`sh.exe`)**,依次尝试:
240
+ 1. 注册表 `HKLM\SOFTWARE\GitForWindows` 的 `InstallPath`
241
+ 2. `which git` 反推 `../usr/bin`
242
+ 3. `PATH` 中的 `git.exe` 反推 `../usr/bin`
243
+ 4. 常见安装位置兜底
244
+
245
+ - **Android NDK**:由 `@flun/nodejs-mobile-react-native` 通过 `android.ndkDirectory` 定位,并注入 `make.exe`、`clang` 等工具路径。
246
+
247
+ > 本包不依赖任何随包分发的硬编码配置文件。上述探测均为运行时动态完成;仅 Visual Studio 的「版本号 → 版本年份 → toolset」对照表以常量形式内联在 `lib/find-visualstudio.js` 中——这类信息由微软固定发布,无枚举接口,且随 VS 版本发布而更新,不适合做成外部资源。
248
+
249
+
250
+ ## 安装
251
+
252
+ ```bash
253
+ npm install @flun/nodejs-mobile-gyp
254
+ ```
255
+
256
+ 通常你不需要手动安装本包——它由 [`@flun/nodejs-mobile-react-native`](https://www.npmjs.com/package/@flun/nodejs-mobile-react-native) 在编译原生模块时自动调用。
257
+
258
+ > **Node 版本要求**:本 fork 的依赖链(`make-fetch-happen`、`nopt`、`proc-log`、`which` 等)已升级到较新版本,要求比原版 `nodejs-mobile-gyp` 更高的 Node。具体最低版本见 `package.json` 的 `engines.node` 字段。若你的项目仍在使用较旧的 Node,请改用原版 `nodejs-mobile-gyp`。
259
+
260
+ ## 使用
261
+
262
+ ### 命令行
263
+
264
+ ```bash
265
+ npx @flun/nodejs-mobile-gyp <command> [options]
266
+ ```
267
+
268
+ 或在 `package.json` 的 `scripts` 中调用:
269
+
270
+ ```json
271
+ {
272
+ "scripts": {
273
+ "build-addon": "nodejs-mobile-gyp rebuild"
274
+ }
275
+ }
276
+ ```
277
+
278
+ ### 从 Node.js 代码调用
279
+
280
+ 本包主要作为 CLI 工具使用,推荐通过 spawn / execFile 调用其命令行入口。包本身也导出了 Gyp 类,但属于内部实现,接口可能随版本变化,不建议直接在代码中依赖。
281
+
282
+ ## 命令
283
+
284
+ | 命令 | 说明 |
285
+ | ----------- | ---------------------------------------- |
286
+ | `help` | 显示帮助 |
287
+ | `build` | 调用 `make` / `msbuild.exe` 编译原生模块 |
288
+ | `clean` | 删除 `build` 目录(若存在) |
289
+ | `configure` | 为当前平台生成工程构建文件 |
290
+ | `rebuild` | 依次执行 `clean` → `configure` → `build` |
291
+ | `install` | 为指定版本安装 Node.js 头文件 |
292
+ | `list` | 列出已安装的 Node.js 头文件版本 |
293
+ | `remove` | 删除指定版本的 Node.js 头文件 |
294
+
295
+ ## 命令选项
296
+
297
+ | 选项 | 说明 |
298
+ | --------------------------------- | -------------------------------------------------- |
299
+ | `-v`, `--version` | 打印本包版本号 |
300
+ | `-j n`, `--jobs n` | 并行运行 `make`;`max` 表示使用所有 CPU 核心 |
301
+ | `--target=v6.2.1` | 目标 Node.js 版本(默认 `process.version`) |
302
+ | `--silly`, `--loglevel=silly` | 输出全部进度日志 |
303
+ | `--verbose`, `--loglevel=verbose` | 输出大部分进度日志 |
304
+ | `--silent`, `--loglevel=silent` | 不输出任何日志 |
305
+ | `debug`, `--debug` | 生成 Debug 构建(默认 Release) |
306
+ | `--release`, `--no-debug` | 生成 Release 构建 |
307
+ | `-C $dir`, `--directory=$dir` | 在指定目录运行命令 |
308
+ | `--make=$make` | 覆盖 `make` 命令(如 `gmake`) |
309
+ | `--thin=yes` | 启用 thin 静态库 |
310
+ | `--arch=$arch` | 目标架构(如 `ia32`) |
311
+ | `--tarball=$path` | 从本地 tarball 获取头文件 |
312
+ | `--devdir=$path` | SDK 下载目录(默认为系统缓存目录) |
313
+ | `--ensure` | 已存在的头文件不重装 |
314
+ | `--dist-url=$url` | 从自定义 URL 下载头文件 tarball |
315
+ | `--proxy=$url` | 下载时使用 HTTP(S) 代理 |
316
+ | `--noproxy=$urls` | 下载时忽略代理的 URL 列表 |
317
+ | `--cafile=$cafile` | 覆盖默认 CA 链(用于下载 tarball) |
318
+ | `--nodedir=$path` | 指定 Node 源码路径 |
319
+ | `--python=$path` | 指定 Python 二进制路径 |
320
+ | `--msvs_version=$version` | 指定 Visual Studio 版本或安装路径(仅 Windows;可填 `2022` / `2026` 或 `C:\...\BuildTools`) |
321
+ | `--solution=$solution` | 指定 Visual Studio Solution 版本(仅 Windows) |
322
+ | `--force-process-config` | 强制用运行时的 `process.config` 生成 `config.gypi` |
323
+
324
+ ## 配置
325
+
326
+ ### 环境变量
327
+
328
+ 上表中的所有命令选项,都可以用 `npm_config_OPTION_NAME` 形式的**环境变量**来设置(选项名中的 `-` 替换为 `_`)。
329
+
330
+ 例如,把 `devdir` 设为 `/tmp/.gyp`:
331
+
332
+ Unix:
333
+ ```bash
334
+ export npm_config_devdir=/tmp/.gyp
335
+ ```
336
+
337
+ Windows:
338
+ ```console
339
+ set npm_config_devdir=c:\temp\.gyp
340
+ ```
341
+
342
+ ### npm 配置(npm v9 之前)
343
+
344
+ 用 `OPTION_NAME` 形式:
345
+
346
+ ```bash
347
+ npm config set [--global] devdir /tmp/.gyp
348
+ ```
349
+
350
+ **注意**:通过 `npm config` 设置的配置,只在本包 **由 npm 调用时**生效,直接运行 `nodejs-mobile-gyp` 不生效。
351
+
352
+ ## 上游参考
353
+
354
+ 本包是 `node-gyp` 的 fork。上游完整文档(含更多高级用法、`binding.gyp` 语法、跨平台细节)请见:
355
+
356
+ - [nodejs/node-gyp README](https://github.com/nodejs/node-gyp#readme)
357
+ - [gyp 用户文档](https://gyp.gsrc.io/docs/UserDocumentation.md)
358
+ - [gyp 输入格式参考](https://gyp.gsrc.io/docs/InputFormatReference.md)
359
+
360
+ ## 许可
361
+
362
+ ISC