@flun/nodejs-mobile-gyp 1.0.1 → 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/CHANGELOG.md +53 -2
- package/README.md +131 -21
- package/addon.gypi +13 -1
- package/bin/node-gyp.js +66 -109
- package/gyp/pylib/gyp/MSVSSettings.py +13 -0
- package/gyp/pylib/gyp/common.py +5 -2
- package/gyp/pylib/gyp/generator/make.py +18 -3
- package/lib/build.js +202 -198
- package/lib/clean.js +13 -16
- package/lib/configure.js +184 -262
- package/lib/create-config-gypi.js +102 -156
- package/lib/download.js +29 -42
- package/lib/find-node-directory.js +38 -55
- package/lib/find-python.js +227 -241
- package/lib/find-visualstudio.js +196 -295
- package/lib/install.js +269 -378
- package/lib/list.js +19 -25
- package/lib/log.js +69 -133
- package/lib/node-gyp.js +62 -107
- package/lib/process-release.js +100 -139
- package/lib/rebuild.js +3 -8
- package/lib/remove.js +34 -44
- package/lib/util.js +62 -73
- package/package.json +5 -3
- package/gyp/LICENSE +0 -28
package/lib/configure.js
CHANGED
|
@@ -1,295 +1,217 @@
|
|
|
1
|
-
import gracefulFs from 'graceful-fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import * as log from './log.js'
|
|
4
|
-
import os from 'os'
|
|
5
|
-
import { processRelease } from './process-release.js'
|
|
6
|
-
import { findNodeDirectory } from './find-node-directory.js'
|
|
7
|
-
import { createConfigGypi } from './create-config-gypi.js'
|
|
8
|
-
import { format as msgFormat } from 'util'
|
|
9
|
-
import { findAccessibleSync } from './util.js'
|
|
10
|
-
import { PythonFinder } from './find-python.js'
|
|
11
|
-
import { fileURLToPath } from 'url'
|
|
12
|
-
|
|
13
|
-
const fs = gracefulFs.promises
|
|
14
|
-
const win = process.platform === 'win32'
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
1
|
+
import gracefulFs from 'graceful-fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import * as log from './log.js';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { processRelease } from './process-release.js';
|
|
6
|
+
import { findNodeDirectory } from './find-node-directory.js';
|
|
7
|
+
import { createConfigGypi } from './create-config-gypi.js';
|
|
8
|
+
import { format as msgFormat } from 'util';
|
|
9
|
+
import { findAccessibleSync } from './util.js';
|
|
10
|
+
import { PythonFinder } from './find-python.js';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
const fs = gracefulFs.promises, win = process.platform === 'win32', __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
14
|
|
|
17
15
|
// 条件加载:仅在 Windows 上需要
|
|
18
|
-
let findVisualStudio = null
|
|
16
|
+
let findVisualStudio = null, nodeDir, vsInfo = null;
|
|
19
17
|
if (win) {
|
|
20
|
-
const { VisualStudioFinder } = await import('./find-visualstudio.js')
|
|
21
|
-
findVisualStudio = VisualStudioFinder.findVisualStudio
|
|
18
|
+
const { VisualStudioFinder } = await import('./find-visualstudio.js');
|
|
19
|
+
findVisualStudio = VisualStudioFinder.findVisualStudio;
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
/**
|
|
25
23
|
* 生成构建文件(Makefile / MSVC 工程)
|
|
26
24
|
*/
|
|
27
25
|
const configure = async (gyp, argv) => {
|
|
28
|
-
const buildDir = path.resolve('build')
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// 指定了 --nodedir,用它作为开发文件目录
|
|
43
|
-
nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir())
|
|
44
|
-
log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir)
|
|
45
|
-
} else {
|
|
46
|
-
// 未指定 --nodedir,先确保 Node 依赖已安装
|
|
47
|
-
if ('v' + release.version !== process.version) {
|
|
48
|
-
// 指定了 --target,确定目标版本
|
|
49
|
-
log.verbose('get node dir', 'compiling against --target node version: %s', release.version)
|
|
50
|
-
} else {
|
|
51
|
-
// 未指定 --target,使用当前主机 Node 版本
|
|
52
|
-
log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version)
|
|
26
|
+
const buildDir = path.resolve('build'), configNames = ['config.gypi', 'common.gypi'], configs = [],
|
|
27
|
+
release = processRelease(argv, gyp, process.version, process.release),
|
|
28
|
+
python = await PythonFinder.findPython(gyp.opts.python),
|
|
29
|
+
runGyp = async () => {
|
|
30
|
+
if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) {
|
|
31
|
+
if (win) {
|
|
32
|
+
log.verbose('gyp', 'gyp format was not specified; forcing "msvs"');
|
|
33
|
+
// 非 Windows 强制使用 make 目标
|
|
34
|
+
argv.push('-f', ('format' in gyp.opts) ? gyp.opts.format : 'msvs');
|
|
35
|
+
} else {
|
|
36
|
+
log.verbose('gyp', 'gyp format was not specified; forcing "make"');
|
|
37
|
+
// 非 Windows 强制使用 make 目标
|
|
38
|
+
argv.push('-f', ('format' in gyp.opts) ? gyp.opts.format : 'make');
|
|
39
|
+
}
|
|
53
40
|
}
|
|
54
41
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
configs.forEach(config => argv.push('-I', config)); // 引入所有找到的 .gypi 文件
|
|
43
|
+
// AIX 和 z/OS 需要设置导出文件路径,其中包含链接所需符号
|
|
44
|
+
let nodeExpFile, nodeRootDir, candidates, logprefix = 'find exports file';
|
|
45
|
+
if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
|
|
46
|
+
const ext = process.platform === 'os390' ? 'x' : 'exp';
|
|
47
|
+
nodeRootDir = findNodeDirectory();
|
|
48
|
+
|
|
49
|
+
if (process.platform === 'aix' || process.platform === 'os400')
|
|
50
|
+
candidates = ['include/node/node', 'out/Release/node', 'out/Debug/node', 'node'].map(file => file + '.' + ext);
|
|
51
|
+
else
|
|
52
|
+
candidates = [
|
|
53
|
+
'out/Release/lib.target/libnode', 'out/Debug/lib.target/libnode', 'out/Release/obj.target/libnode',
|
|
54
|
+
'out/Debug/obj.target/libnode', 'lib/libnode'].map(file => file + '.' + ext);
|
|
55
|
+
|
|
56
|
+
nodeExpFile = findAccessibleSync(logprefix, nodeRootDir, candidates);
|
|
57
|
+
if (nodeExpFile !== undefined) log.verbose(logprefix, 'Found exports file: %s', nodeExpFile);
|
|
58
|
+
else {
|
|
59
|
+
const msg = msgFormat('Could not find node.%s file in %s', ext, nodeRootDir);
|
|
60
|
+
log.error(logprefix, 'Could not find exports file');
|
|
61
|
+
throw new Error(msg);
|
|
62
|
+
}
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
// z/OS 需要设置 zoslib 头文件目录,其中包含 v8config.h 引用的头文件
|
|
66
|
+
let zoslibIncDir;
|
|
67
|
+
if (process.platform === 'os390') {
|
|
68
|
+
logprefix = "find zoslib's zos-base.h:";
|
|
69
|
+
let msg, zoslibIncPath = process.env.ZOSLIB_INCLUDES;
|
|
70
|
+
if (zoslibIncPath) {
|
|
71
|
+
zoslibIncPath = findAccessibleSync(logprefix, zoslibIncPath, ['zos-base.h']);
|
|
72
|
+
if (zoslibIncPath === undefined) {
|
|
73
|
+
msg = msgFormat('Could not find zos-base.h file in the directory set ' +
|
|
74
|
+
'in ZOSLIB_INCLUDES environment variable: %s; set it ' +
|
|
75
|
+
'to the correct path, or unset it to search %s', process.env.ZOSLIB_INCLUDES, nodeRootDir)
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
candidates = [
|
|
79
|
+
'include/node/zoslib/zos-base.h', 'include/zoslib/zos-base.h', 'zoslib/include/zos-base.h',
|
|
80
|
+
'install/include/node/zoslib/zos-base.h'
|
|
81
|
+
]
|
|
82
|
+
zoslibIncPath = findAccessibleSync(logprefix, nodeRootDir, candidates);
|
|
83
|
+
if (zoslibIncPath === undefined) {
|
|
84
|
+
msg = msgFormat('Could not find any of %s in directory %s; set ' +
|
|
85
|
+
'environmant variable ZOSLIB_INCLUDES to the path ' +
|
|
86
|
+
'that contains zos-base.h', candidates.toString(), nodeRootDir)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (zoslibIncPath !== undefined) {
|
|
90
|
+
zoslibIncDir = path.dirname(zoslibIncPath);
|
|
91
|
+
log.verbose(logprefix, "Found zoslib's zos-base.h in: %s", zoslibIncDir);
|
|
92
|
+
} else if (release.version.split('.')[0] >= 16) {
|
|
93
|
+
// zoslib 只随 Node v16 及以上发布
|
|
94
|
+
log.error(logprefix, msg);
|
|
95
|
+
throw new Error(msg);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
75
98
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
// 这段逻辑移植自旧的 `gyp_addon` Python 文件
|
|
100
|
+
const gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py'),
|
|
101
|
+
addonGypi = path.resolve(__dirname, '..', 'addon.gypi');
|
|
102
|
+
let commonGypi = path.resolve(nodeDir, 'include/node/common.gypi');
|
|
103
|
+
try {
|
|
104
|
+
await fs.stat(commonGypi);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
commonGypi = path.resolve(nodeDir, 'common.gypi');
|
|
107
|
+
}
|
|
83
108
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path
|
|
88
|
-
}
|
|
89
|
-
const configPath = await createConfigGypi({ gyp, buildDir, nodeDir, vsInfo, python })
|
|
90
|
-
configs.push(configPath)
|
|
91
|
-
return findConfigs()
|
|
92
|
-
}
|
|
109
|
+
let outputDir = 'build';
|
|
110
|
+
if (win) outputDir = buildDir; // Windows 需要绝对路径
|
|
111
|
+
const nodeGypDir = path.resolve(__dirname, '..');
|
|
93
112
|
|
|
94
|
-
|
|
95
|
-
const name = configNames.shift()
|
|
96
|
-
if (!name) {
|
|
97
|
-
return runGyp()
|
|
98
|
-
}
|
|
113
|
+
let nodeLibFile = path.join(nodeDir, !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', release.name + '.lib');
|
|
99
114
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
configs.push(fullPath)
|
|
106
|
-
} catch (err) {
|
|
107
|
-
// ENOENT 时继续检查下一个 gypi 文件名
|
|
108
|
-
if (err.code !== 'ENOENT') {
|
|
109
|
-
throw err
|
|
115
|
+
argv.push('-I', addonGypi), argv.push('-I', commonGypi), argv.push('-Dlibrary=shared_library');
|
|
116
|
+
argv.push('-Dvisibility=default'), argv.push('-Dnode_root_dir=' + nodeDir);
|
|
117
|
+
if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
|
|
118
|
+
argv.push('-Dnode_exp_file=' + nodeExpFile);
|
|
119
|
+
if (process.platform === 'os390' && zoslibIncDir) argv.push('-Dzoslib_include_dir=' + zoslibIncDir);
|
|
110
120
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
argv.push('-Dnode_gyp_dir=' + nodeGypDir);
|
|
122
|
+
|
|
123
|
+
// 这样做是为了让 Cygwin 环境正常工作,否则未转义的 '\' 会被吃掉,
|
|
124
|
+
// 导致路径错误,如 c:parentFolderfolderanotherFolder 而非 c:\parentFolder\folder\anotherFolder
|
|
125
|
+
if (win) nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\');
|
|
126
|
+
argv.push('-Dnode_lib_file=' + nodeLibFile), argv.push('-Dmodule_root_dir=' + process.cwd());
|
|
127
|
+
argv.push('-Dnode_engine=' + (gyp.opts.node_engine || process.jsEngine || 'v8'));
|
|
128
|
+
argv.push('--depth=.'), argv.push('--no-parallel');
|
|
129
|
+
argv.push('--generator-output', outputDir); // 告诉 gyp 把 Makefile/Solution 文件写到 output_dir
|
|
130
|
+
// 使用 find-visualstudio 探测到的实际 toolset(v140/v141/v142/v143/v145...),
|
|
131
|
+
// 不再硬编码,以兼容 VS2013+ 各版本
|
|
118
132
|
if (win) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
argv.push('-f', ('format' in gyp.opts) ? gyp.opts.format : 'msvs')
|
|
122
|
-
} else {
|
|
123
|
-
log.verbose('gyp', 'gyp format was not specified; forcing "make"')
|
|
124
|
-
// 非 Windows 强制使用 make 目标
|
|
125
|
-
argv.push('-f', ('format' in gyp.opts) ? gyp.opts.format : 'make')
|
|
133
|
+
if (vsInfo?.toolset) argv.push('-Gmsvs_toolset=' + vsInfo.toolset);
|
|
134
|
+
else log.warn('gyp', '未能探测到 VS toolset,将使用 gyp 默认值');
|
|
126
135
|
}
|
|
127
|
-
}
|
|
128
136
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
argv.
|
|
132
|
-
})
|
|
137
|
+
argv.push('-Goutput_dir=.'); // 告诉 make 把输出写到同一目录
|
|
138
|
+
argv.unshift('binding.gyp'); // 强制使用 binding.gyp 文件
|
|
139
|
+
argv.unshift(gypScript); // 从当前目标 nodedir 执行 `gyp`
|
|
133
140
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
let logprefix = 'find exports file'
|
|
139
|
-
if (process.platform === 'aix' || process.platform === 'os390' || process.platform === 'os400') {
|
|
140
|
-
const ext = process.platform === 'os390' ? 'x' : 'exp'
|
|
141
|
-
nodeRootDir = findNodeDirectory()
|
|
141
|
+
// 确保 python 使用该 node 包自带的文件
|
|
142
|
+
const pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
|
|
143
|
+
if (process.env.PYTHONPATH) pypath.push(process.env.PYTHONPATH);
|
|
144
|
+
process.env.PYTHONPATH = pypath.join(win ? ';' : ':');
|
|
142
145
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
'
|
|
147
|
-
|
|
148
|
-
'node'
|
|
149
|
-
].map(function (file) {
|
|
150
|
-
return file + '.' + ext
|
|
151
|
-
})
|
|
152
|
-
} else {
|
|
153
|
-
candidates = [
|
|
154
|
-
'out/Release/lib.target/libnode',
|
|
155
|
-
'out/Debug/lib.target/libnode',
|
|
156
|
-
'out/Release/obj.target/libnode',
|
|
157
|
-
'out/Debug/obj.target/libnode',
|
|
158
|
-
'lib/libnode'
|
|
159
|
-
].map(function (file) {
|
|
160
|
-
return file + '.' + ext
|
|
146
|
+
await new Promise((resolve, reject) => {
|
|
147
|
+
const cp = gyp.spawn(python, argv);
|
|
148
|
+
cp.on('exit', code => {
|
|
149
|
+
if (code !== 0) reject(new Error('`gyp` failed with exit code: ' + code));
|
|
150
|
+
else resolve(); // 完成
|
|
161
151
|
})
|
|
152
|
+
})
|
|
153
|
+
},
|
|
154
|
+
findConfigs = async () => {
|
|
155
|
+
const name = configNames.shift();
|
|
156
|
+
if (!name) return runGyp();
|
|
157
|
+
|
|
158
|
+
const fullPath = path.resolve(name);
|
|
159
|
+
log.verbose(name, 'checking for gypi file: %s', fullPath);
|
|
160
|
+
try {
|
|
161
|
+
await fs.stat(fullPath), log.verbose(name, 'found gypi file'), configs.push(fullPath);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
if (err.code !== 'ENOENT') throw err; // ENOENT 时继续检查下一个 gypi 文件名
|
|
162
164
|
}
|
|
163
165
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
throw new Error(msg)
|
|
166
|
+
return findConfigs();
|
|
167
|
+
},
|
|
168
|
+
createConfigFile = async () => {
|
|
169
|
+
if (win) {
|
|
170
|
+
process.env.GYP_MSVS_VERSION = Math.min(vsInfo.versionYear, 2015);
|
|
171
|
+
process.env.GYP_MSVS_OVERRIDE_PATH = vsInfo.path;
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
173
|
+
const configPath = await createConfigGypi({ gyp, buildDir, nodeDir, vsInfo, python });
|
|
174
|
+
configs.push(configPath);
|
|
175
|
+
return findConfigs();
|
|
176
|
+
},
|
|
177
|
+
createBuildDir = async () => {
|
|
178
|
+
log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir);
|
|
179
|
+
|
|
180
|
+
const isNew = await fs.mkdir(buildDir, { recursive: true });
|
|
181
|
+
log.verbose('build dir', '"build" dir needed to be created?', isNew ? 'Yes' : 'No');
|
|
182
|
+
vsInfo = win ? await findVisualStudio(release.semver, gyp.opts['msvs-version']) : null;
|
|
183
|
+
return createConfigFile();
|
|
184
|
+
},
|
|
185
|
+
getNodeDir = async () => {
|
|
186
|
+
// 此时 python 已确定
|
|
187
|
+
process.env.PYTHON = python;
|
|
188
|
+
|
|
189
|
+
if (gyp.opts.nodedir) {
|
|
190
|
+
// 指定了 --nodedir,用它作为开发文件目录
|
|
191
|
+
nodeDir = gyp.opts.nodedir.replace(/^~/, os.homedir());
|
|
192
|
+
log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir);
|
|
187
193
|
} else {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (zoslibIncPath === undefined) {
|
|
196
|
-
msg = msgFormat('Could not find any of %s in directory %s; set ' +
|
|
197
|
-
'environmant variable ZOSLIB_INCLUDES to the path ' +
|
|
198
|
-
'that contains zos-base.h', candidates.toString(), nodeRootDir)
|
|
194
|
+
// 未指定 --nodedir,先确保 Node 依赖已安装
|
|
195
|
+
if ('v' + release.version !== process.version) {
|
|
196
|
+
// 指定了 --target,确定目标版本
|
|
197
|
+
log.verbose('get node dir', 'compiling against --target node version: %s', release.version);
|
|
198
|
+
} else {
|
|
199
|
+
// 未指定 --target,使用当前主机 Node 版本
|
|
200
|
+
log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version);
|
|
199
201
|
}
|
|
200
|
-
}
|
|
201
|
-
if (zoslibIncPath !== undefined) {
|
|
202
|
-
zoslibIncDir = path.dirname(zoslibIncPath)
|
|
203
|
-
log.verbose(logprefix, "Found zoslib's zos-base.h in: %s", zoslibIncDir)
|
|
204
|
-
} else if (release.version.split('.')[0] >= 16) {
|
|
205
|
-
// zoslib 只随 Node v16 及以上发布
|
|
206
|
-
log.error(logprefix, msg)
|
|
207
|
-
throw new Error(msg)
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// 这段逻辑移植自旧的 `gyp_addon` Python 文件
|
|
212
|
-
const gypScript = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py')
|
|
213
|
-
const addonGypi = path.resolve(__dirname, '..', 'addon.gypi')
|
|
214
|
-
let commonGypi = path.resolve(nodeDir, 'include/node/common.gypi')
|
|
215
|
-
try {
|
|
216
|
-
await fs.stat(commonGypi)
|
|
217
|
-
} catch (err) {
|
|
218
|
-
commonGypi = path.resolve(nodeDir, 'common.gypi')
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
let outputDir = 'build'
|
|
222
|
-
if (win) {
|
|
223
|
-
// Windows 需要绝对路径
|
|
224
|
-
outputDir = buildDir
|
|
225
|
-
}
|
|
226
|
-
const nodeGypDir = path.resolve(__dirname, '..')
|
|
227
|
-
|
|
228
|
-
let nodeLibFile = path.join(nodeDir,
|
|
229
|
-
!gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)',
|
|
230
|
-
release.name + '.lib')
|
|
231
202
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
argv.push('-Dnode_exp_file=' + nodeExpFile)
|
|
239
|
-
if (process.platform === 'os390' && zoslibIncDir) {
|
|
240
|
-
argv.push('-Dzoslib_include_dir=' + zoslibIncDir)
|
|
203
|
+
if (!release.semver) throw new Error('版本号无效: ' + release.version); // 无法用 semver 解析版本字符串
|
|
204
|
+
// 如果指定了 tarball 选项,总是删除并重装 headers 到 devdir,
|
|
205
|
+
// 否则只在不存在时安装
|
|
206
|
+
gyp.opts.ensure = !gyp.opts.tarball, await gyp.commands.install([release.version]);
|
|
207
|
+
log.verbose('get node dir', 'target node version installed:', release.versionDir);
|
|
208
|
+
nodeDir = path.resolve(gyp.devDir, release.versionDir);
|
|
241
209
|
}
|
|
242
|
-
}
|
|
243
|
-
argv.push('-Dnode_gyp_dir=' + nodeGypDir)
|
|
244
|
-
|
|
245
|
-
// 这样做是为了让 Cygwin 环境正常工作,否则未转义的 '\' 会被吃掉,
|
|
246
|
-
// 导致路径错误,如 c:parentFolderfolderanotherFolder 而非 c:\parentFolder\folder\anotherFolder
|
|
247
|
-
if (win) {
|
|
248
|
-
nodeLibFile = nodeLibFile.replace(/\\/g, '\\\\')
|
|
249
|
-
}
|
|
250
|
-
argv.push('-Dnode_lib_file=' + nodeLibFile)
|
|
251
|
-
argv.push('-Dmodule_root_dir=' + process.cwd())
|
|
252
|
-
argv.push('-Dnode_engine=' +
|
|
253
|
-
(gyp.opts.node_engine || process.jsEngine || 'v8'))
|
|
254
|
-
argv.push('--depth=.')
|
|
255
|
-
argv.push('--no-parallel')
|
|
256
|
-
|
|
257
|
-
// 告诉 gyp 把 Makefile/Solution 文件写到 output_dir
|
|
258
|
-
argv.push('--generator-output', outputDir)
|
|
259
|
-
if (win) {
|
|
260
|
-
argv.push('-Gmsvs_toolset=v145')
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// 告诉 make 把输出写到同一目录
|
|
264
|
-
argv.push('-Goutput_dir=.')
|
|
265
|
-
|
|
266
|
-
// 强制使用 binding.gyp 文件
|
|
267
|
-
argv.unshift('binding.gyp')
|
|
268
|
-
|
|
269
|
-
// 从当前目标 nodedir 执行 `gyp`
|
|
270
|
-
argv.unshift(gypScript)
|
|
271
|
-
|
|
272
|
-
// 确保 python 使用该 node 包自带的文件
|
|
273
|
-
const pypath = [path.join(__dirname, '..', 'gyp', 'pylib')]
|
|
274
|
-
if (process.env.PYTHONPATH) {
|
|
275
|
-
pypath.push(process.env.PYTHONPATH)
|
|
276
|
-
}
|
|
277
|
-
process.env.PYTHONPATH = pypath.join(win ? ';' : ':')
|
|
278
|
-
|
|
279
|
-
await new Promise((resolve, reject) => {
|
|
280
|
-
const cp = gyp.spawn(python, argv)
|
|
281
|
-
cp.on('exit', (code) => {
|
|
282
|
-
if (code !== 0) {
|
|
283
|
-
reject(new Error('`gyp` failed with exit code: ' + code))
|
|
284
|
-
} else {
|
|
285
|
-
// 完成
|
|
286
|
-
resolve()
|
|
287
|
-
}
|
|
288
|
-
})
|
|
289
|
-
})
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
210
|
|
|
293
|
-
|
|
211
|
+
return createBuildDir();
|
|
212
|
+
};
|
|
213
|
+
return getNodeDir();
|
|
214
|
+
};
|
|
294
215
|
|
|
295
|
-
|
|
216
|
+
configure.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module';
|
|
217
|
+
export { configure };
|