@flun/nodejs-mobile-gyp 1.1.2 → 1.1.4

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 (79) hide show
  1. package/CHANGELOG.md +10 -75
  2. package/LICENSE +9 -4
  3. package/README.md +198 -132
  4. package/addon.gypi +1 -1
  5. package/bin/node-gyp.js +6 -5
  6. package/gyp/README.md +5 -3
  7. package/gyp/data/win/large-pdb-shim.cc +1 -1
  8. package/gyp/gyp +1 -1
  9. package/gyp/gyp.bat +1 -1
  10. package/gyp/gyp_main.py +1 -1
  11. package/gyp/pylib/gyp/MSVSNew.py +1 -1
  12. package/gyp/pylib/gyp/MSVSProject.py +1 -1
  13. package/gyp/pylib/gyp/MSVSSettings.py +1 -1
  14. package/gyp/pylib/gyp/MSVSToolFile.py +1 -1
  15. package/gyp/pylib/gyp/MSVSUserFile.py +1 -1
  16. package/gyp/pylib/gyp/MSVSUtil.py +1 -1
  17. package/gyp/pylib/gyp/MSVSVersion.py +1 -1
  18. package/gyp/pylib/gyp/__init__.py +1 -1
  19. package/gyp/pylib/gyp/common.py +1 -1
  20. package/gyp/pylib/gyp/easy_xml.py +1 -1
  21. package/gyp/pylib/gyp/flock_tool.py +1 -1
  22. package/gyp/pylib/gyp/generator/analyzer.py +1 -1
  23. package/gyp/pylib/gyp/generator/android.py +1 -1
  24. package/gyp/pylib/gyp/generator/cmake.py +1 -1
  25. package/gyp/pylib/gyp/generator/compile_commands_json.py +1 -1
  26. package/gyp/pylib/gyp/generator/dump_dependency_json.py +1 -1
  27. package/gyp/pylib/gyp/generator/eclipse.py +1 -1
  28. package/gyp/pylib/gyp/generator/gypd.py +1 -1
  29. package/gyp/pylib/gyp/generator/gypsh.py +1 -1
  30. package/gyp/pylib/gyp/generator/make.py +23 -12
  31. package/gyp/pylib/gyp/generator/msvs.py +3 -3
  32. package/gyp/pylib/gyp/generator/ninja.py +1 -1
  33. package/gyp/pylib/gyp/generator/xcode.py +1 -1
  34. package/gyp/pylib/gyp/input.py +1 -1
  35. package/gyp/pylib/gyp/mac_tool.py +1 -1
  36. package/gyp/pylib/gyp/msvs_emulation.py +1 -1
  37. package/gyp/pylib/gyp/ninja_syntax.py +1 -1
  38. package/gyp/pylib/gyp/simple_copy.py +1 -1
  39. package/gyp/pylib/gyp/win_tool.py +1 -1
  40. package/gyp/pylib/gyp/xcode_emulation.py +5 -5
  41. package/gyp/pylib/gyp/xcode_ninja.py +1 -1
  42. package/gyp/pylib/gyp/xcodeproj_file.py +1 -1
  43. package/gyp/pylib/gyp/xml_fix.py +1 -1
  44. package/gyp/pylib/packaging/LICENSE +1 -1
  45. package/gyp/pylib/packaging/LICENSE.APACHE +1 -1
  46. package/gyp/pylib/packaging/LICENSE.BSD +1 -1
  47. package/gyp/pylib/packaging/__init__.py +1 -1
  48. package/gyp/pylib/packaging/_elffile.py +1 -1
  49. package/gyp/pylib/packaging/_manylinux.py +1 -1
  50. package/gyp/pylib/packaging/_musllinux.py +1 -1
  51. package/gyp/pylib/packaging/_parser.py +1 -1
  52. package/gyp/pylib/packaging/_structures.py +1 -1
  53. package/gyp/pylib/packaging/_tokenizer.py +1 -1
  54. package/gyp/pylib/packaging/markers.py +1 -1
  55. package/gyp/pylib/packaging/metadata.py +1 -1
  56. package/gyp/pylib/packaging/requirements.py +1 -1
  57. package/gyp/pylib/packaging/specifiers.py +1 -1
  58. package/gyp/pylib/packaging/tags.py +1 -1
  59. package/gyp/pylib/packaging/utils.py +1 -1
  60. package/gyp/pylib/packaging/version.py +1 -1
  61. package/lib/Find-VisualStudio.cs +1 -1
  62. package/lib/build.js +16 -16
  63. package/lib/clean.js +2 -2
  64. package/lib/configure.js +20 -17
  65. package/lib/create-config-gypi.js +8 -8
  66. package/lib/download.js +3 -3
  67. package/lib/find-node-directory.js +9 -9
  68. package/lib/find-python.js +14 -14
  69. package/lib/find-visualstudio.js +19 -19
  70. package/lib/install.js +22 -21
  71. package/lib/list.js +1 -1
  72. package/lib/log.js +2 -2
  73. package/lib/node-gyp.js +7 -7
  74. package/lib/process-release.js +14 -14
  75. package/lib/rebuild.js +1 -1
  76. package/lib/remove.js +2 -2
  77. package/lib/util.js +5 -4
  78. package/package.json +3 -3
  79. package/src/win_delay_load_hook.cc +1 -1
package/lib/clean.js CHANGED
@@ -3,7 +3,7 @@ import * as log from './log.js';
3
3
 
4
4
  const fs = gracefulFs.promises,
5
5
  /**
6
- * 清理:删除 build 目录
6
+ * 清理:删除 build 目录
7
7
  */
8
8
  clean = async (gyp, argv) => {
9
9
  const buildDir = 'build';
@@ -13,4 +13,4 @@ const fs = gracefulFs.promises,
13
13
  }
14
14
 
15
15
  clean.usage = 'Removes any generated build files and the "out" dir';
16
- export { clean };
16
+ export { clean };
package/lib/configure.js CHANGED
@@ -10,9 +10,10 @@ import { findAccessibleSync } from './util.js';
10
10
  import { PythonFinder } from './find-python.js';
11
11
  import { fileURLToPath } from 'url';
12
12
 
13
- const fs = gracefulFs.promises, win = process.platform === 'win32', __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ const fs = gracefulFs.promises, win = process.platform === 'win32',
14
+ __dirname = path.dirname(fileURLToPath(import.meta.url));
14
15
 
15
- // 条件加载:仅在 Windows 上需要
16
+ // 条件加载:仅在 Windows 上需要
16
17
  let findVisualStudio = null, nodeDir, vsInfo = null;
17
18
  if (win) {
18
19
  const { VisualStudioFinder } = await import('./find-visualstudio.js');
@@ -20,7 +21,7 @@ if (win) {
20
21
  }
21
22
 
22
23
  /**
23
- * 生成构建文件(Makefile / MSVC 工程)
24
+ * 生成构建文件(Makefile / MSVC 工程)
24
25
  */
25
26
  const configure = async (gyp, argv) => {
26
27
  const buildDir = path.resolve('build'), configNames = ['config.gypi', 'common.gypi'], configs = [],
@@ -40,7 +41,7 @@ const configure = async (gyp, argv) => {
40
41
  }
41
42
 
42
43
  configs.forEach(config => argv.push('-I', config)); // 引入所有找到的 .gypi 文件
43
- // AIX 和 z/OS 需要设置导出文件路径,其中包含链接所需符号
44
+ // AIX 和 z/OS 需要设置导出文件路径,其中包含链接所需符号
44
45
  let nodeExpFile, nodeRootDir, candidates, logprefix = 'find exports file';
45
46
  if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
46
47
  const ext = process.platform === 'os390' ? 'x' : 'exp';
@@ -62,7 +63,7 @@ const configure = async (gyp, argv) => {
62
63
  }
63
64
  }
64
65
 
65
- // z/OS 需要设置 zoslib 头文件目录,其中包含 v8config.h 引用的头文件
66
+ // z/OS 需要设置 zoslib 头文件目录,其中包含 v8config.h 引用的头文件
66
67
  let zoslibIncDir;
67
68
  if (process.platform === 'os390') {
68
69
  logprefix = "find zoslib's zos-base.h:";
@@ -110,7 +111,8 @@ const configure = async (gyp, argv) => {
110
111
  if (win) outputDir = buildDir; // Windows 需要绝对路径
111
112
  const nodeGypDir = path.resolve(__dirname, '..');
112
113
 
113
- let nodeLibFile = path.join(nodeDir, !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', release.name + '.lib');
114
+ let nodeLibFile = path.join(nodeDir,
115
+ !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', release.name + '.lib');
114
116
 
115
117
  argv.push('-I', addonGypi), argv.push('-I', commonGypi), argv.push('-Dlibrary=shared_library');
116
118
  argv.push('-Dvisibility=default'), argv.push('-Dnode_root_dir=' + nodeDir);
@@ -120,18 +122,18 @@ const configure = async (gyp, argv) => {
120
122
  }
121
123
  argv.push('-Dnode_gyp_dir=' + nodeGypDir);
122
124
 
123
- // 这样做是为了让 Cygwin 环境正常工作,否则未转义的 '\' 会被吃掉,
124
- // 导致路径错误,如 c:parentFolderfolderanotherFolder 而非 c:\parentFolder\folder\anotherFolder
125
+ // 这样做是为了让 Cygwin 环境正常工作,否则未转义的 '\' 会被吃掉,
126
+ // 导致路径错误,如 c:parentFolderfolderanotherFolder 而非 c:\parentFolder\folder\anotherFolder
125
127
  if (win) nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\');
126
128
  argv.push('-Dnode_lib_file=' + nodeLibFile), argv.push('-Dmodule_root_dir=' + process.cwd());
127
129
  argv.push('-Dnode_engine=' + (gyp.opts.node_engine || process.jsEngine || 'v8'));
128
130
  argv.push('--depth=.'), argv.push('--no-parallel');
129
131
  argv.push('--generator-output', outputDir); // 告诉 gyp 把 Makefile/Solution 文件写到 output_dir
130
- // 使用 find-visualstudio 探测到的实际 toolset(v140/v141/v142/v143/v145...),
131
- // 不再硬编码,以兼容 VS2013+ 各版本
132
+ // 使用 find-visualstudio 探测到的实际 toolset(v140/v141/v142/v143/v145...),
133
+ // 不再硬编码,以兼容 VS2013+ 各版本
132
134
  if (win) {
133
135
  if (vsInfo?.toolset) argv.push('-Gmsvs_toolset=' + vsInfo.toolset);
134
- else log.warn('gyp', '未能探测到 VS toolset,将使用 gyp 默认值');
136
+ else log.warn('gyp', '未能探测到 VS toolset,将使用 gyp 默认值');
135
137
  }
136
138
 
137
139
  argv.push('-Goutput_dir=.'); // 告诉 make 把输出写到同一目录
@@ -187,21 +189,22 @@ const configure = async (gyp, argv) => {
187
189
  process.env.PYTHON = python;
188
190
 
189
191
  if (gyp.opts.nodedir) {
190
- // 指定了 --nodedir,用它作为开发文件目录
192
+ // 指定了 --nodedir,用它作为开发文件目录
191
193
  nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir());
192
194
  log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir);
193
195
  } else {
194
- // 未指定 --nodedir,先确保 Node 依赖已安装
196
+ // 未指定 --nodedir,先确保 Node 依赖已安装
195
197
  if ('v' + release.version !== process.version) {
196
- // 指定了 --target,确定目标版本
198
+ // 指定了 --target,确定目标版本
197
199
  log.verbose('get node dir', 'compiling against --target node version: %s', release.version);
198
200
  } else {
199
- // 未指定 --target,使用当前主机 Node 版本
200
- log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version);
201
+ // 未指定 --target,使用当前主机 Node 版本
202
+ log.verbose('get node dir',
203
+ 'no --target version specified, falling back to host node version: %s', release.version);
201
204
  }
202
205
 
203
206
  if (!release.semver) throw new Error('版本号无效: ' + release.version); // 无法用 semver 解析版本字符串
204
- // 如果指定了 tarball 选项,总是删除并重装 headers 到 devdir,
207
+ // 如果指定了 tarball 选项,总是删除并重装 headers 到 devdir,
205
208
  // 否则只在不存在时安装
206
209
  gyp.opts.ensure = !gyp.opts.tarball, await gyp.commands.install([release.version]);
207
210
  log.verbose('get node dir', 'target node version installed:', release.versionDir);
@@ -16,7 +16,7 @@ const fs = gracefulFs.promises,
16
16
  * 读取基础 config.gypi
17
17
  */
18
18
  getBaseConfigGypi = async ({ gyp, nodeDir }) => {
19
- // 在以下情况优先读取 $nodeDir/include/node/config.gypi:
19
+ // 在以下情况优先读取 $nodeDir/include/node/config.gypi:
20
20
  // 1. 指定了 --dist-url 或 --nodedir
21
21
  // 2. 且没有指定 --force-process-config
22
22
  const useCustomHeaders = gyp.opts.nodedir || gyp.opts.disturl || gyp.opts['dist-url'],
@@ -40,8 +40,8 @@ const fs = gracefulFs.promises,
40
40
  if (!config.variables) config.variables = {};
41
41
 
42
42
  const defaults = config.target_defaults, variables = config.variables;
43
- // 不要继承 base config.gypi 的 defaults,
44
- // 否则当 node 可执行文件在另一台机器编译(lib/include 路径不同)时会出问题
43
+ // 不要继承 base config.gypi 的 defaults,
44
+ // 否则当 node 可执行文件在另一台机器编译(lib/include 路径不同)时会出问题
45
45
  defaults.cflags = [], defaults.defines = [], defaults.include_dirs = [], defaults.libraries = [];
46
46
 
47
47
  // 设置 default_configuration
@@ -66,14 +66,14 @@ const fs = gracefulFs.promises,
66
66
  else log.warn('仅 Visual Studio 2017 15.9 及以上版本支持编译 ARM64 汇编');
67
67
  }
68
68
  variables.msbuild_path = vsInfo.msBuild;
69
- // Windows 原生构建走 MSVC 工具集:必须关闭 clang 与 LTO,
70
- // 否则 common.gypi 会把 toolset 设为 ClangCL,并向 MSVC 链接器传入 Clang 专用参数
71
- // (-flto=thin、/opt:lldltojobs),导致 MSB8020 或 LNK1117
69
+ // Windows 原生构建走 MSVC 工具集:必须关闭 clang 与 LTO,
70
+ // 否则 common.gypi 会把 toolset 设为 ClangCL,并向 MSVC 链接器传入 Clang 专用参数
71
+ // (-flto=thin、/opt:lldltojobs),导致 MSB8020 或 LNK1117
72
72
  if (!gyp.opts.format || gyp.opts.format === 'msvs')
73
73
  variables.clang = 0, variables.enable_lto = 'false', variables.enable_thin_lto = 'false', variables.lto_jobs = '';
74
74
  }
75
75
 
76
- // 把其余未知选项当作变量写入,支持模块自定义 configure 参数,例如:
76
+ // 把其余未知选项当作变量写入,支持模块自定义 configure 参数,例如:
77
77
  // $ node-gyp configure --shared-libxml2
78
78
  for (const [k, v] of Object.entries(gyp.opts)) {
79
79
  if (k === 'argv' || k in gyp.configDefs) continue;
@@ -106,4 +106,4 @@ const fs = gracefulFs.promises,
106
106
  return configPath;
107
107
  };
108
108
 
109
- export { createConfigGypi, parseConfigGypi, getCurrentConfigGypi }
109
+ export { createConfigGypi, parseConfigGypi, getCurrentConfigGypi }
package/lib/download.js CHANGED
@@ -4,10 +4,10 @@ import * as log from './log.js';
4
4
 
5
5
  const { promises: fs } = gracefulFs,
6
6
  /**
7
- * 读取 CA 证书文件,按证书边界切分为多个证书
7
+ * 读取 CA 证书文件,按证书边界切分为多个证书
8
8
  */
9
9
  readCAFile = async filename => {
10
- // CA 文件可能包含多份证书,按证书边界切分; [\S\s]*? 用于匹配包括换行在内的所有内容;
10
+ // CA 文件可能包含多份证书,按证书边界切分; [\S\s]*? 用于匹配包括换行在内的所有内容;
11
11
  const ca = await fs.readFile(filename, 'utf8'), re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g;
12
12
  return ca.match(re);
13
13
  },
@@ -28,4 +28,4 @@ const { promises: fs } = gracefulFs,
28
28
  return res;
29
29
  }
30
30
 
31
- export { readCAFile, download }
31
+ export { readCAFile, download }
@@ -7,33 +7,33 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)),
7
7
  * 从脚本位置或进程对象推断 Node 根目录
8
8
  */
9
9
  findNodeDirectory = (scriptLocation, processObj) => {
10
- // 未传入时使用默认值,便于回归测试
10
+ // 未传入时使用默认值,便于回归测试
11
11
  if (scriptLocation === undefined) scriptLocation = __dirname;
12
12
  if (processObj === undefined) processObj = process;
13
13
 
14
- // 看看上层目录结构,判断当前所处位置
14
+ // 看看上层目录结构,判断当前所处位置
15
15
  const npmParentDirectory = path.join(scriptLocation, '../../../..');
16
16
  log.verbose('node-gyp root', 'npm_parent_directory is ' + path.basename(npmParentDirectory));
17
17
  log.verbose('node-gyp root', 'Finding node root directory');
18
18
  let nodeRootDir = '';
19
19
  if (path.basename(npmParentDirectory) === 'deps') {
20
- // 处于构建目录中,脚本位于 deps/npm/node_modules/node-gyp/lib
20
+ // 处于构建目录中,脚本位于 deps/npm/node_modules/node-gyp/lib
21
21
  nodeRootDir = path.join(npmParentDirectory, '..');
22
22
  log.verbose('node-gyp root', 'in build directory, root = ' + nodeRootDir);
23
23
  } else if (path.basename(npmParentDirectory) === 'node_modules') {
24
- // 处于 Node 安装目录中,脚本位于
24
+ // 处于 Node 安装目录中,脚本位于
25
25
  // lib/node_modules/npm/node_modules/node-gyp/lib 或
26
- // node_modules/npm/node_modules/node-gyp/lib(视平台而定)
26
+ // node_modules/npm/node_modules/node-gyp/lib(视平台而定)
27
27
  if (processObj.platform === 'win32') nodeRootDir = path.join(npmParentDirectory, '..');
28
28
  else nodeRootDir = path.join(npmParentDirectory, '../..');
29
29
  log.verbose('node-gyp root', 'in install directory, root = ' + nodeRootDir);
30
30
  } else {
31
- // 无法判断,尝试从 node 可执行文件的位置推断
31
+ // 无法判断,尝试从 node 可执行文件的位置推断
32
32
  const nodeDir = path.dirname(processObj.execPath), directoryUp = path.basename(nodeDir);
33
33
  if (directoryUp === 'bin') nodeRootDir = path.join(nodeDir, '..');
34
34
  else if (directoryUp === 'Release' || directoryUp === 'Debug') {
35
- // 如果是刚构建的 node,且目录结构为仓库结构:
36
- // Windows 只需上一层,其余平台两层
35
+ // 如果是刚构建的 node,且目录结构为仓库结构:
36
+ // Windows 只需上一层,其余平台两层
37
37
  if (processObj.platform === 'win32') nodeRootDir = path.join(nodeDir, '..');
38
38
  else nodeRootDir = path.join(nodeDir, '../..');
39
39
  }
@@ -42,4 +42,4 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)),
42
42
  return nodeRootDir;
43
43
  }
44
44
 
45
- export { findNodeDirectory }
45
+ export { findNodeDirectory }
@@ -6,7 +6,7 @@ import fs from 'fs';
6
6
 
7
7
  const win = process.platform === 'win32',
8
8
  /**
9
- * 获取当前操作系统用户名(失败时返回 undefined)
9
+ * 获取当前操作系统用户名(失败时返回 undefined)
10
10
  */
11
11
  getOsUserInfo = () => {
12
12
  try { return os.userInfo().username } catch { }
@@ -19,8 +19,8 @@ const win = process.platform === 'win32',
19
19
  programFilesX86 = process.env['ProgramFiles(x86)'] || `${programFiles} (x86)`,
20
20
  systemRoot = process.env.SystemRoot || `${systemDrive}\\Windows`,
21
21
  /**
22
- * 动态扫描 Windows 上所有已安装的 Python,不硬编码版本号。
23
- * 官方安装器目录命名:3.14 -> Python314,3.9 -> Python39,32 位加 -32 后缀。
22
+ * 动态扫描 Windows 上所有已安装的 Python,不硬编码版本号;
23
+ * 官方安装器目录命名:3.14 -> Python314,3.9 -> Python39,32 位加 -32 后缀;
24
24
  */
25
25
  scanWindowsPythonLocations = () => {
26
26
  const results = [], bases = [foundLocalAppData ? `${localAppData}\\Programs\\Python` : null, `${programFiles}\\Python`,
@@ -40,13 +40,13 @@ const win = process.platform === 'win32',
40
40
  return results;
41
41
  },
42
42
  /**
43
- * py.exe 启动器候选:先试 PATH 中的,再试常见绝对路径,
44
- * 避免 Gradle / CI 环境下 PATH 不含 C:\Windows 的情况。
43
+ * py.exe 启动器候选:先试 PATH 中的,再试常见绝对路径,
44
+ * 避免 Gradle / CI 环境下 PATH 不含 C:\Windows 的情况;
45
45
  */
46
46
  pyLauncherCandidates = win ? ['py.exe', `${systemRoot}\\py.exe`, `${systemRoot}\\System32\\py.exe`] : [];
47
47
 
48
48
  /**
49
- * Python 查找器:按顺序尝试多种途径定位可用的 Python 3.6+
49
+ * Python 查找器:按顺序尝试多种途径定位可用的 Python 3.6+
50
50
  */
51
51
  class PythonFinder {
52
52
  static findPython = (...args) => new PythonFinder(...args).findPython();
@@ -66,12 +66,12 @@ class PythonFinder {
66
66
  this.configPython = configPython, this.errorLog = [];
67
67
  }
68
68
 
69
- // 以 verbose 级别记录日志,同时保存下来,出错时以 error 级别展示,便于诊断
69
+ // 以 verbose 级别记录日志,同时保存下来,出错时以 error 级别展示,便于诊断
70
70
  addLog(message) {
71
71
  this.log.verbose(message), this.errorLog.push(message);
72
72
  }
73
73
 
74
- // 依次尝试多种 Python 定位方式。忽略错误,直到找到可用版本
74
+ // 依次尝试多种 Python 定位方式;忽略错误,直到找到可用版本
75
75
  async findPython() {
76
76
  const SKIP = 0, FAIL = 1,
77
77
  toCheck = (() => {
@@ -158,7 +158,7 @@ class PythonFinder {
158
158
  return this.fail();
159
159
  }
160
160
 
161
- // 检查命令是否为可用的 Python。
161
+ // 检查命令是否为可用的 Python;
162
162
  async checkCommand(command) {
163
163
  this.log.verbose(`- executing "${command}" to get executable path`);
164
164
  try {
@@ -171,7 +171,7 @@ class PythonFinder {
171
171
  }
172
172
  }
173
173
 
174
- // 检查指定 py 启动器是否能找到 Python 3。
174
+ // 检查指定 py 启动器是否能找到 Python 3;
175
175
  async checkPyLauncher(launcher = this.pyLauncher) {
176
176
  this.log.verbose(`- executing "${launcher}" to get Python 3 executable path`);
177
177
  try {
@@ -184,7 +184,7 @@ class PythonFinder {
184
184
  }
185
185
  }
186
186
 
187
- // 通过 "py -0p" 枚举所有已注册的 Python,覆盖非标准安装位置。
187
+ // 通过 "py -0p" 枚举所有已注册的 Python,覆盖非标准安装位置;
188
188
  async checkPyList() {
189
189
  this.log.verbose('- executing "py -0p" to list registered Pythons');
190
190
  let lastErr;
@@ -213,7 +213,7 @@ class PythonFinder {
213
213
  throw lastErr || new Error('py -0p returned no usable Python');
214
214
  }
215
215
 
216
- // 检查某个 Python 可执行文件版本是否可用。
216
+ // 检查某个 Python 可执行文件版本是否可用;
217
217
  async checkExecPath(execPath) {
218
218
  this.log.verbose(`- executing "${execPath}" to get version`);
219
219
  try {
@@ -242,8 +242,8 @@ class PythonFinder {
242
242
  }
243
243
  }
244
244
 
245
- // 执行外部命令。execFile 包装不 reject,通过 [err, stdout, stderr] 返回结果,
246
- // 必须显式检查 err,否则失败会被当成"成功但空输出",掩盖真实原因。
245
+ // 执行外部命令;execFile 包装不 reject,通过 [err, stdout, stderr] 返回结果,
246
+ // 必须显式检查 err,否则失败会被当成"成功但空输出",掩盖真实原因;
247
247
  async run(exec, args, shell) {
248
248
  const env = Object.assign({}, this.env), opts = { env, shell };
249
249
  env.TERM = 'dumb';
@@ -6,7 +6,7 @@ import { regSearchKeys, execFile } from './util.js';
6
6
 
7
7
  const path = nodePath.win32, __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
8
8
  /**
9
- * Visual Studio 查找器:定位可用的 VS 安装
9
+ * Visual Studio 查找器:定位可用的 VS 安装
10
10
  */
11
11
  class VisualStudioFinder {
12
12
  static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio();
@@ -17,7 +17,7 @@ class VisualStudioFinder {
17
17
  this.nodeSemver = nodeSemver, this.configMsvsVersion = configMsvsVersion, this.errorLog = [], this.validVersions = [];
18
18
  }
19
19
 
20
- // 以 verbose 级别记录日志,同时保存下来,出错时以 error 级别展示,便于诊断
20
+ // 以 verbose 级别记录日志,同时保存下来,出错时以 error 级别展示,便于诊断
21
21
  addLog(message) {
22
22
  this.log.verbose(message), this.errorLog.push(message);
23
23
  }
@@ -66,7 +66,7 @@ class VisualStudioFinder {
66
66
  this.errorLog.push(
67
67
  'msvs_version does not match this VS Command Prompt or the', 'installation cannot be used.');
68
68
  else if (this.configMsvsVersion) {
69
- // 指定了 msvs_version 但没找到 VS,输出可接受的版本
69
+ // 指定了 msvs_version 但没找到 VS,输出可接受的版本
70
70
  this.errorLog.push('');
71
71
  if (this.validVersions) {
72
72
  this.errorLog.push('valid versions for msvs_version:');
@@ -76,7 +76,7 @@ class VisualStudioFinder {
76
76
  }
77
77
 
78
78
  const errorLog = this.errorLog.join('\n'),
79
- // Windows 80 列控制台,用到 X 标记列之前(含日志前缀共 79 字符,可用 62 字符):
79
+ // Windows 80 列控制台,用到 X 标记列之前(含日志前缀共 79 字符,可用 62 字符):
80
80
  infoLog = [
81
81
  '**************************************************************',
82
82
  'You need to install the latest version of Visual Studio',
@@ -90,7 +90,7 @@ class VisualStudioFinder {
90
90
  throw new Error('未找到可用的 Visual Studio 安装');
91
91
  }
92
92
 
93
- // 调用 PowerShell 脚本,获取 Visual Studio 2017 或更新版本的信息
93
+ // 调用 PowerShell 脚本,获取 Visual Studio 2017 或更新版本的信息
94
94
  async findVisualStudio2017OrNewer() {
95
95
  const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'),
96
96
  csFile = path.join(__dirname, 'Find-VisualStudio.cs'),
@@ -102,7 +102,7 @@ class VisualStudioFinder {
102
102
  return this.parseData(err, stdout, stderr);
103
103
  }
104
104
 
105
- // 解析 PowerShell 脚本输出,寻找可用的 Visual Studio 2017 或更新版本
105
+ // 解析 PowerShell 脚本输出,寻找可用的 Visual Studio 2017 或更新版本
106
106
  parseData(err, stdout, stderr) {
107
107
  this.log.silly('PS stderr = %j', stderr)
108
108
 
@@ -149,7 +149,7 @@ class VisualStudioFinder {
149
149
  return false;
150
150
  })
151
151
 
152
- // 排序:新版本在前
152
+ // 排序:新版本在前
153
153
  vsInfo.sort((a, b) => b.versionYear - a.versionYear)
154
154
 
155
155
  for (let i = 0; i < vsInfo.length; ++i) {
@@ -182,7 +182,7 @@ class VisualStudioFinder {
182
182
  return null;
183
183
  }
184
184
 
185
- // 辅助:解析版本信息
185
+ // 辅助:解析版本信息
186
186
  getVersionInfo(info) {
187
187
  const match = /^(\d+)\.(\d+)\./.exec(info.version);
188
188
  if (!match) {
@@ -206,7 +206,7 @@ class VisualStudioFinder {
206
206
  return existsSync(path);
207
207
  }
208
208
 
209
- // 辅助:解析 MSBuild 信息
209
+ // 辅助:解析 MSBuild 信息
210
210
  getMSBuild(info, versionYear) {
211
211
  const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base',
212
212
  msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe'),
@@ -217,16 +217,16 @@ class VisualStudioFinder {
217
217
  if (versionYear === 2019) return msbuildPath;
218
218
  }
219
219
  /**
220
- * Visual Studio 2022 没有 MSBuild 包。
221
- * ARM64 上编译的支持从 MSVC 14.32.31326 起加入,
222
- * 因此用户设备是 ARM64 时优先使用它。
220
+ * Visual Studio 2022 没有 MSBuild 包;
221
+ * ARM64 上编译的支持从 MSVC 14.32.31326 起加入,
222
+ * 因此用户设备是 ARM64 时优先使用它;
223
223
  */
224
224
  if (process.arch === 'arm64' && this.msBuildPathExists(msbuildPathArm64)) return msbuildPathArm64;
225
225
  else if (this.msBuildPathExists(msbuildPath)) return msbuildPath;
226
226
  return null;
227
227
  }
228
228
 
229
- // 辅助:解析 toolset 信息
229
+ // 辅助:解析 toolset 信息
230
230
  getToolset(info, versionYear) {
231
231
  const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', express = 'Microsoft.VisualStudio.WDExpress';
232
232
  if (info.packages.indexOf(pkg) !== -1) this.log.silly('- found VC.Tools.x86.x64');
@@ -241,7 +241,7 @@ class VisualStudioFinder {
241
241
  return null;
242
242
  }
243
243
 
244
- // 辅助:解析 Windows SDK 信息
244
+ // 辅助:解析 Windows SDK 信息
245
245
  getSDK(info) {
246
246
  const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK',
247
247
  win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.',
@@ -291,7 +291,7 @@ class VisualStudioFinder {
291
291
  return this.findOldVS({ version: '12.0', versionMajor: 12, versionMinor: 0, versionYear: 2013, toolset: 'v120' });
292
292
  }
293
293
 
294
- // 辅助:VS2013 和 VS2015 的公共代码
294
+ // 辅助:VS2013 和 VS2015 的公共代码
295
295
  async findOldVS(info) {
296
296
  const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7',
297
297
  'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7'],
@@ -322,10 +322,10 @@ class VisualStudioFinder {
322
322
  }
323
323
  }
324
324
 
325
- // 找到可用的 Visual Studio 后:
326
- // - 把它加入 validVersions,用于在指定版本未找到时输出;
327
- // - 检查是否是请求的版本;
328
- // - 检查是否匹配 Visual Studio 命令提示符。
325
+ // 找到可用的 Visual Studio 后:
326
+ // - 把它加入 validVersions,用于在指定版本未找到时输出;
327
+ // - 检查是否是请求的版本;
328
+ // - 检查是否匹配 Visual Studio 命令提示符;
329
329
  checkConfigVersion(versionYear, vsPath) {
330
330
  this.validVersions.push(versionYear), this.validVersions.push(vsPath);
331
331
 
package/lib/install.js CHANGED
@@ -17,15 +17,15 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
17
17
  install = async (gyp, argv) => {
18
18
  log.stdout();
19
19
  const release = processRelease(argv, gyp, process.version, process.release),
20
- // 按 create-config-gypi.js 的逻辑推断 target_arch,仅 Windows 用
20
+ // 按 create-config-gypi.js 的逻辑推断 target_arch,仅 Windows 用
21
21
  arch = win ? (gyp.opts.target_arch || gyp.opts.arch || process.arch || 'ia32') : '';
22
- let shouldDownloadTarball = true; // 仅 Windows 下只需新 node.lib 时,避免下载 tarball
22
+ let shouldDownloadTarball = true; // 仅 Windows 下只需新 node.lib 时,避免下载 tarball
23
23
 
24
24
  // 确定要安装哪个版本的 Node 开发文件
25
25
  log.verbose('install', 'input version string %j', release.version);
26
26
  if (!release.semver) throw new Error('版本号无效: ' + release.version); // 无法用 semver 解析版本字符串
27
- if (semver.lt(release.version, '0.8.0')) throw new Error('目标版本最低为 `0.8.0`,当前: ' + release.version);
28
- // 0.x.y-pre 版本尚未发布,无法安装,直接退出
27
+ if (semver.lt(release.version, '0.8.0')) throw new Error('目标版本最低为 `0.8.0`,当前: ' + release.version);
28
+ // 0.x.y-pre 版本尚未发布,无法安装,直接退出
29
29
  if (release.semver.prerelease[0] === 'pre') {
30
30
  log.verbose('detected "pre" node version', release.version);
31
31
  if (!gyp.opts.nodedir) throw new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead');
@@ -51,13 +51,13 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
51
51
  for (const entry of entries) {
52
52
  if (entry.isDirectory()) await copyDirectory(path.join(src, entry.name), path.join(dest, entry.name));
53
53
  else if (entry.isFile()) {
54
- // 并行安装时,Windows 上复制文件可能报文件错误,
54
+ // 并行安装时,Windows 上复制文件可能报文件错误,
55
55
  // 因此用指数退避解决冲突
56
56
  await backOff(async () => {
57
57
  try {
58
58
  await fs.copyFile(path.join(src, entry.name), path.join(dest, entry.name));
59
59
  } catch (err) {
60
- // 若设置了 ensure,检查文件是否已存在,存在就足够了
60
+ // 若设置了 ensure,检查文件是否已存在,存在就足够了
61
61
  if (gyp.opts.ensure && err.code === 'EBUSY') {
62
62
  try {
63
63
  await fs.stat(path.join(dest, entry.name));
@@ -72,16 +72,16 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
72
72
  }
73
73
  },
74
74
  rollback = async err => {
75
- log.warn('install', '发生错误,正在回滚安装')
75
+ log.warn('install', '发生错误,正在回滚安装')
76
76
  await gyp.commands.remove([release.versionDir]);
77
77
  throw err;
78
78
  },
79
79
  /**
80
- * EACCES 回退方案,用于处理 npm 的 `sudo` 行为:
81
- * npm 在调用任何子进程(如 node-gyp)前会先降权,
82
- * 于是 "nobody" 用户没有权限创建 dev dir。
83
- * 作为回退,把 tmpdir() 作为本次安装的 dev dir。
84
- * 这不理想,但至少编译能成功……
80
+ * EACCES 回退方案,用于处理 npm 的 `sudo` 行为:
81
+ * npm 在调用任何子进程(如 node-gyp)前会先降权,
82
+ * 于是 "nobody" 用户没有权限创建 dev dir;
83
+ * 作为回退,把 tmpdir() 作为本次安装的 dev dir;
84
+ * 这不理想,但至少编译能成功......
85
85
  */
86
86
  eaccesFallback = async err => {
87
87
  const noretry = '--node_gyp_internal_noretry';
@@ -90,7 +90,7 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
90
90
  gyp.devDir = path.resolve(tmpdir, '.node-gyp');
91
91
  let userString = '';
92
92
  try {
93
- userString = ` ("${os.userInfo().username}")`; // os.userInfo 在某些系统上会失败,这里不关键
93
+ userString = ` ("${os.userInfo().username}")`; // os.userInfo 在某些系统上会失败,这里不关键
94
94
  } catch (e) { }
95
95
  log.warn('EACCES', '当前用户%s 没有权限访问 dev dir "%s"', userString, devDir);
96
96
  log.warn('EACCES', '尝试用临时 dev dir 重新安装 "%s"', gyp.devDir);
@@ -115,7 +115,7 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
115
115
  // 下载 Node tarball
116
116
  let extractErrors = false, extractCount = 0;
117
117
  const tarPath = gyp.opts.tarball, contentShasums = {}, expectShasums = {},
118
- // 检查从 tarball 解出的文件是否有效。
118
+ // 检查从 tarball 解出的文件是否有效;
119
119
  // 只有 .h 头文件和 gyp 文件会被解出
120
120
  isValid = path => {
121
121
  const isValid = valid(path);
@@ -127,10 +127,10 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
127
127
  onwarn = (code, message) => {
128
128
  extractErrors = true, log.error('error while extracting tarball', code, message);
129
129
  },
130
- // 下载并解压 tarball!
130
+ // 下载并解压 tarball!
131
131
  // 仅 Windows 上只需新 node.lib 时跳过
132
- // Windows 上并行安装时(多个原生模块,很常见)tar 会报文件错误,
133
- // 所以先把 tarball 解到临时目录,再复制过去
132
+ // Windows 上并行安装时(多个原生模块,很常见)tar 会报文件错误,
133
+ // 所以先把 tarball 解到临时目录,再复制过去
134
134
  tarExtractDir = win ? await fs.mkdtemp(path.join(os.tmpdir(), 'node-gyp-tmp-')) : devDir,
135
135
  downloadShasums = async () => {
136
136
  log.verbose('check download content checksum, need to download `SHASUMS256.txt`...');
@@ -159,7 +159,7 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
159
159
  await fs.mkdir(dir, { recursive: true }), log.verbose('streaming', name, 'to:', targetLibPath);
160
160
 
161
161
  const res = await download(gyp, libUrl);
162
- // 只下载所需的 node.lib,若未拿到则抛错
162
+ // 只下载所需的 node.lib,若未拿到则抛错
163
163
  if (res.status !== 200) throw new Error(`${res.status} status code downloading ${name}`);
164
164
 
165
165
  return pipeline(
@@ -188,9 +188,10 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
188
188
  tar.extract({ strip: 1, cwd: tarExtractDir, filter: isValid, onwarn })
189
189
  )
190
190
  } catch (err) {
191
- // tarball 下载出问题?
191
+ // tarball 下载出问题?
192
192
  if (err.code === 'ENOTFOUND')
193
- throw new Error('这通常不是 node-gyp 或包本身的问题,而是网络问题;\n' + '通常是因为你在代理后,或网络设置异常;');
193
+ throw new Error('这通常不是 node-gyp 或包本身的问题,而是网络问题;\n' +
194
+ '通常是因为你在代理后,或网络设置异常;');
194
195
  throw err;
195
196
  }
196
197
  }
@@ -232,7 +233,7 @@ const { createWriteStream, promises: fs } = gracefulFs, { pipeline } = streamPro
232
233
  }
233
234
  };
234
235
 
235
- // 如果传了 --ensure,则不总是安装,只在需要时安装
236
+ // 如果传了 --ensure,则不总是安装,只在需要时安装
236
237
  if (gyp.opts.ensure) {
237
238
  log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed');
238
239
  try {
package/lib/list.js CHANGED
@@ -21,4 +21,4 @@ const fs = gracefulFs.promises,
21
21
  }
22
22
 
23
23
  list.usage = 'Prints a listing of the currently installed node development files';
24
- export { list }
24
+ export { list }
package/lib/log.js CHANGED
@@ -18,7 +18,7 @@ const logLevels = Object.keys(procLog.log).filter((k) => typeof procLog.log[k] =
18
18
  bg: { black: 40, red: 41, green: 42, yellow: 43, blue: 44, magenta: 45, cyan: 46, white: 47 }
19
19
  };
20
20
 
21
- // 日志器:负责缓冲、暂停/恢复、着色输出
21
+ // 日志器:负责缓冲、暂停/恢复、着色输出
22
22
  class Logger {
23
23
  #buffer = [];
24
24
  #paused = null;
@@ -105,6 +105,6 @@ class Logger {
105
105
  // 用于测试时抑制日志
106
106
  const NULL_LOGGER = !!process.env.NODE_GYP_NULL_LOGGER, logger = new Logger(NULL_LOGGER ? null : process.stderr),
107
107
  stdout = NULL_LOGGER ? () => { } : (...args) => console.log(...args),
108
- { notice, error, warn, info, verbose, http, silly, pause, resume } = procLog.log; // 解构 proc-log 的函数,供末尾统一导出
108
+ { notice, error, warn, info, verbose, http, silly, pause, resume } = procLog.log; // 解构 proc-log 的函数,供末尾统一导出
109
109
 
110
110
  export { logger, stdout, withPrefix, notice, error, warn, info, verbose, http, silly, pause, resume }