@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/find-visualstudio.js
CHANGED
|
@@ -1,420 +1,324 @@
|
|
|
1
|
-
import * as log from './log.js'
|
|
2
|
-
import { existsSync } from 'fs'
|
|
3
|
-
import nodePath from 'path'
|
|
4
|
-
import { fileURLToPath } from 'url'
|
|
5
|
-
import { regSearchKeys, execFile } from './util.js'
|
|
6
|
-
|
|
7
|
-
const path = nodePath.win32
|
|
8
|
-
const __dirname = nodePath.dirname(fileURLToPath(import.meta.url))
|
|
1
|
+
import * as log from './log.js';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import nodePath from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { regSearchKeys, execFile } from './util.js';
|
|
9
6
|
|
|
7
|
+
const path = nodePath.win32, __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
10
8
|
/**
|
|
11
9
|
* Visual Studio 查找器:定位可用的 VS 安装
|
|
12
10
|
*/
|
|
13
11
|
class VisualStudioFinder {
|
|
14
|
-
static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio()
|
|
15
|
-
|
|
16
|
-
log = log.withPrefix('find VS')
|
|
12
|
+
static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio();
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
constructor
|
|
21
|
-
this.nodeSemver = nodeSemver
|
|
22
|
-
this.configMsvsVersion = configMsvsVersion
|
|
23
|
-
this.errorLog = []
|
|
24
|
-
this.validVersions = []
|
|
14
|
+
log = log.withPrefix('find VS');
|
|
15
|
+
regSearchKeys = regSearchKeys;
|
|
16
|
+
constructor(nodeSemver, configMsvsVersion) {
|
|
17
|
+
this.nodeSemver = nodeSemver, this.configMsvsVersion = configMsvsVersion, this.errorLog = [], this.validVersions = [];
|
|
25
18
|
}
|
|
26
19
|
|
|
27
20
|
// 以 verbose 级别记录日志,同时保存下来,出错时以 error 级别展示,便于诊断
|
|
28
|
-
addLog
|
|
29
|
-
this.log.verbose(message)
|
|
30
|
-
this.errorLog.push(message)
|
|
21
|
+
addLog(message) {
|
|
22
|
+
this.log.verbose(message), this.errorLog.push(message);
|
|
31
23
|
}
|
|
32
24
|
|
|
33
|
-
async findVisualStudio
|
|
34
|
-
this.configVersionYear = null
|
|
35
|
-
this.configPath = null
|
|
25
|
+
async findVisualStudio() {
|
|
26
|
+
this.configVersionYear = null, this.configPath = null;
|
|
36
27
|
if (this.configMsvsVersion) {
|
|
37
|
-
this.addLog('msvs_version was set from command line or npm config')
|
|
28
|
+
this.addLog('msvs_version was set from command line or npm config');
|
|
38
29
|
if (this.configMsvsVersion.match(/^\d{4}$/)) {
|
|
39
|
-
this.configVersionYear = parseInt(this.configMsvsVersion, 10)
|
|
40
|
-
this.addLog(
|
|
41
|
-
`- looking for Visual Studio version ${this.configVersionYear}`)
|
|
30
|
+
this.configVersionYear = parseInt(this.configMsvsVersion, 10);
|
|
31
|
+
this.addLog(`- looking for Visual Studio version ${this.configVersionYear}`);
|
|
42
32
|
} else {
|
|
43
|
-
this.configPath = path.resolve(this.configMsvsVersion)
|
|
44
|
-
this.addLog(
|
|
45
|
-
`- looking for Visual Studio installed in "${this.configPath}"`)
|
|
33
|
+
this.configPath = path.resolve(this.configMsvsVersion);
|
|
34
|
+
this.addLog(`- looking for Visual Studio installed in "${this.configPath}"`);
|
|
46
35
|
}
|
|
47
|
-
} else {
|
|
48
|
-
this.addLog('msvs_version not set from command line or npm config')
|
|
49
36
|
}
|
|
37
|
+
else this.addLog('msvs_version not set from command line or npm config');
|
|
50
38
|
|
|
51
39
|
if (process.env.VCINSTALLDIR) {
|
|
52
|
-
this.envVcInstallDir =
|
|
53
|
-
path.resolve(process.env.VCINSTALLDIR, '..')
|
|
40
|
+
this.envVcInstallDir = path.resolve(process.env.VCINSTALLDIR, '..');
|
|
54
41
|
this.addLog('running in VS Command Prompt, installation path is:\n' +
|
|
55
|
-
`"${this.envVcInstallDir}"\n- will only use this version`)
|
|
56
|
-
} else {
|
|
57
|
-
this.addLog('VCINSTALLDIR not set, not running in VS Command Prompt')
|
|
42
|
+
`"${this.envVcInstallDir}"\n- will only use this version`);
|
|
58
43
|
}
|
|
44
|
+
else this.addLog('VCINSTALLDIR not set, not running in VS Command Prompt');
|
|
59
45
|
|
|
60
46
|
const checks = [
|
|
61
|
-
() => this.findVisualStudio2017OrNewer(),
|
|
62
|
-
|
|
63
|
-
() => this.findVisualStudio2013()
|
|
64
|
-
]
|
|
47
|
+
() => this.findVisualStudio2017OrNewer(), () => this.findVisualStudio2015(), () => this.findVisualStudio2013()
|
|
48
|
+
];
|
|
65
49
|
|
|
66
50
|
for (const check of checks) {
|
|
67
|
-
const info = await check()
|
|
68
|
-
if (info)
|
|
69
|
-
return this.succeed(info)
|
|
70
|
-
}
|
|
51
|
+
const info = await check();
|
|
52
|
+
if (info) return this.succeed(info);
|
|
71
53
|
}
|
|
72
54
|
|
|
73
|
-
return this.fail()
|
|
55
|
+
return this.fail();
|
|
74
56
|
}
|
|
75
57
|
|
|
76
|
-
succeed
|
|
58
|
+
succeed(info) {
|
|
77
59
|
this.log.info(`using VS${info.versionYear} (${info.version}) found at:` +
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return info
|
|
60
|
+
`\n"${info.path}"` + '\nrun with --verbose for detailed information');
|
|
61
|
+
return info;
|
|
81
62
|
}
|
|
82
63
|
|
|
83
|
-
fail
|
|
84
|
-
if (this.configMsvsVersion && this.envVcInstallDir)
|
|
64
|
+
fail() {
|
|
65
|
+
if (this.configMsvsVersion && this.envVcInstallDir)
|
|
85
66
|
this.errorLog.push(
|
|
86
|
-
'msvs_version does not match this VS Command Prompt or the',
|
|
87
|
-
|
|
88
|
-
} else if (this.configMsvsVersion) {
|
|
67
|
+
'msvs_version does not match this VS Command Prompt or the', 'installation cannot be used.');
|
|
68
|
+
else if (this.configMsvsVersion) {
|
|
89
69
|
// 指定了 msvs_version 但没找到 VS,输出可接受的版本
|
|
90
|
-
this.errorLog.push('')
|
|
70
|
+
this.errorLog.push('');
|
|
91
71
|
if (this.validVersions) {
|
|
92
|
-
this.errorLog.push('valid versions for msvs_version:')
|
|
93
|
-
this.validVersions.forEach(
|
|
94
|
-
this.errorLog.push(`- "${version}"`)
|
|
95
|
-
})
|
|
96
|
-
} else {
|
|
97
|
-
this.errorLog.push('no valid versions for msvs_version were found')
|
|
72
|
+
this.errorLog.push('valid versions for msvs_version:');
|
|
73
|
+
this.validVersions.forEach(version => this.errorLog.push(`- "${version}"`));
|
|
98
74
|
}
|
|
75
|
+
else this.errorLog.push('no valid versions for msvs_version were found');
|
|
99
76
|
}
|
|
100
77
|
|
|
101
|
-
const errorLog = this.errorLog.join('\n')
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
this.log.error(`\n${errorLog}\n\n${infoLog}\n`)
|
|
115
|
-
throw new Error('Could not find any Visual Studio installation to use')
|
|
78
|
+
const errorLog = this.errorLog.join('\n'),
|
|
79
|
+
// Windows 80 列控制台,用到 X 标记列之前(含日志前缀共 79 字符,可用 62 字符):
|
|
80
|
+
infoLog = [
|
|
81
|
+
'**************************************************************',
|
|
82
|
+
'You need to install the latest version of Visual Studio',
|
|
83
|
+
'including the "Desktop development with C++" workload.',
|
|
84
|
+
'For more information consult the documentation at:',
|
|
85
|
+
'https://github.com/nodejs/node-gyp#on-windows',
|
|
86
|
+
'**************************************************************'
|
|
87
|
+
].join('\n');
|
|
88
|
+
|
|
89
|
+
this.log.error(`\n${errorLog}\n\n${infoLog}\n`);
|
|
90
|
+
throw new Error('未找到可用的 Visual Studio 安装');
|
|
116
91
|
}
|
|
117
92
|
|
|
118
93
|
// 调用 PowerShell 脚本,获取 Visual Studio 2017 或更新版本的信息
|
|
119
|
-
async findVisualStudio2017OrNewer
|
|
120
|
-
const ps = path.join(process.env.SystemRoot, 'System32',
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
'&{Add-Type -Path \'' + csFile + '\';' + '[VisualStudioConfiguration.Main]::PrintJson()}'
|
|
129
|
-
]
|
|
130
|
-
|
|
131
|
-
this.log.silly('Running', ps, psArgs)
|
|
132
|
-
const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' })
|
|
133
|
-
return this.parseData(err, stdout, stderr)
|
|
94
|
+
async findVisualStudio2017OrNewer() {
|
|
95
|
+
const ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe'),
|
|
96
|
+
csFile = path.join(__dirname, 'Find-VisualStudio.cs'),
|
|
97
|
+
psArgs = ['-ExecutionPolicy', 'Unrestricted', '-NoProfile', '-Command',
|
|
98
|
+
'&{Add-Type -Path \'' + csFile + '\';' + '[VisualStudioConfiguration.Main]::PrintJson()}'];
|
|
99
|
+
|
|
100
|
+
this.log.silly('Running', ps, psArgs);
|
|
101
|
+
const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' });
|
|
102
|
+
return this.parseData(err, stdout, stderr);
|
|
134
103
|
}
|
|
135
104
|
|
|
136
105
|
// 解析 PowerShell 脚本输出,寻找可用的 Visual Studio 2017 或更新版本
|
|
137
|
-
parseData
|
|
106
|
+
parseData(err, stdout, stderr) {
|
|
138
107
|
this.log.silly('PS stderr = %j', stderr)
|
|
139
108
|
|
|
140
109
|
const failPowershell = () => {
|
|
141
|
-
this.addLog(
|
|
142
|
-
|
|
143
|
-
return null
|
|
110
|
+
this.addLog(`could not use PowerShell to find Visual Studio 2017 or newer,
|
|
111
|
+
try re-running with \'--loglevel silly\' for more details`);
|
|
112
|
+
return null;
|
|
144
113
|
}
|
|
145
114
|
|
|
146
115
|
if (err) {
|
|
147
|
-
this.log.silly('PS err = %j', err && (err.stack || err))
|
|
148
|
-
return failPowershell()
|
|
116
|
+
this.log.silly('PS err = %j', err && (err.stack || err));
|
|
117
|
+
return failPowershell();
|
|
149
118
|
}
|
|
150
119
|
|
|
151
|
-
let vsInfo
|
|
120
|
+
let vsInfo;
|
|
152
121
|
try {
|
|
153
|
-
vsInfo = JSON.parse(stdout)
|
|
122
|
+
vsInfo = JSON.parse(stdout);
|
|
154
123
|
} catch (e) {
|
|
155
|
-
this.log.silly('PS stdout = %j', stdout)
|
|
156
|
-
|
|
157
|
-
return failPowershell()
|
|
124
|
+
this.log.silly('PS stdout = %j', stdout), this.log.silly(e);
|
|
125
|
+
return failPowershell();
|
|
158
126
|
}
|
|
159
127
|
|
|
160
128
|
if (!Array.isArray(vsInfo)) {
|
|
161
|
-
this.log.silly('PS stdout = %j', stdout)
|
|
162
|
-
return failPowershell()
|
|
129
|
+
this.log.silly('PS stdout = %j', stdout);
|
|
130
|
+
return failPowershell();
|
|
163
131
|
}
|
|
164
132
|
|
|
165
133
|
vsInfo = vsInfo.map((info) => {
|
|
166
|
-
this.log.silly(`processing installation: "${info.path}"`)
|
|
167
|
-
info.path = path.resolve(info.path)
|
|
168
|
-
const ret = this.getVersionInfo(info)
|
|
169
|
-
ret.path = info.path
|
|
170
|
-
ret.msBuild = this.getMSBuild(info, ret.versionYear)
|
|
171
|
-
ret.toolset = this.getToolset(info, ret.versionYear)
|
|
172
|
-
ret.sdk = this.getSDK(info)
|
|
173
|
-
return ret
|
|
134
|
+
this.log.silly(`processing installation: "${info.path}"`);
|
|
135
|
+
info.path = path.resolve(info.path);
|
|
136
|
+
const ret = this.getVersionInfo(info);
|
|
137
|
+
ret.path = info.path;
|
|
138
|
+
ret.msBuild = this.getMSBuild(info, ret.versionYear);
|
|
139
|
+
ret.toolset = this.getToolset(info, ret.versionYear);
|
|
140
|
+
ret.sdk = this.getSDK(info);
|
|
141
|
+
return ret;
|
|
174
142
|
})
|
|
175
|
-
this.log.silly('vsInfo:', vsInfo)
|
|
143
|
+
this.log.silly('vsInfo:', vsInfo);
|
|
176
144
|
|
|
177
145
|
// 去掉未来版本或版本号解析失败的项
|
|
178
|
-
vsInfo = vsInfo.filter(
|
|
179
|
-
if (info.versionYear)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
this.addLog(`unknown version "${info.version}" found at "${info.path}"`)
|
|
183
|
-
return false
|
|
146
|
+
vsInfo = vsInfo.filter(info => {
|
|
147
|
+
if (info.versionYear) return true;
|
|
148
|
+
this.addLog(`unknown version "${info.version}" found at "${info.path}"`);
|
|
149
|
+
return false;
|
|
184
150
|
})
|
|
185
151
|
|
|
186
152
|
// 排序:新版本在前
|
|
187
153
|
vsInfo.sort((a, b) => b.versionYear - a.versionYear)
|
|
188
154
|
|
|
189
155
|
for (let i = 0; i < vsInfo.length; ++i) {
|
|
190
|
-
const info = vsInfo[i]
|
|
191
|
-
this.addLog(`checking VS${info.versionYear} (${info.version}) found ` +
|
|
192
|
-
`at:\n"${info.path}"`)
|
|
193
|
-
|
|
194
|
-
if (info.msBuild) {
|
|
195
|
-
this.addLog('- found "Visual Studio C++ core features"')
|
|
196
|
-
} else {
|
|
197
|
-
this.addLog('- "Visual Studio C++ core features" missing')
|
|
198
|
-
continue
|
|
199
|
-
}
|
|
156
|
+
const info = vsInfo[i];
|
|
157
|
+
this.addLog(`checking VS${info.versionYear} (${info.version}) found ` + `at:\n"${info.path}"`);
|
|
200
158
|
|
|
201
|
-
if (info.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
continue
|
|
159
|
+
if (info.msBuild) this.addLog('- found "Visual Studio C++ core features"');
|
|
160
|
+
else {
|
|
161
|
+
this.addLog('- "Visual Studio C++ core features" missing');
|
|
162
|
+
continue;
|
|
206
163
|
}
|
|
207
164
|
|
|
208
|
-
if (info.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
continue
|
|
165
|
+
if (info.toolset) this.addLog(`- found VC++ toolset: ${info.toolset}`);
|
|
166
|
+
else {
|
|
167
|
+
this.addLog('- missing any VC++ toolset');
|
|
168
|
+
continue;
|
|
213
169
|
}
|
|
214
170
|
|
|
215
|
-
if (
|
|
216
|
-
|
|
171
|
+
if (info.sdk) this.addLog(`- found Windows SDK: ${info.sdk}`);
|
|
172
|
+
else {
|
|
173
|
+
this.addLog('- missing any Windows SDK');
|
|
174
|
+
continue;
|
|
217
175
|
}
|
|
218
176
|
|
|
177
|
+
if (!this.checkConfigVersion(info.versionYear, info.path)) continue;
|
|
219
178
|
return info
|
|
220
179
|
}
|
|
221
180
|
|
|
222
|
-
this.addLog(
|
|
223
|
-
|
|
224
|
-
return null
|
|
181
|
+
this.addLog('could not find a version of Visual Studio 2017 or newer to use');
|
|
182
|
+
return null;
|
|
225
183
|
}
|
|
226
184
|
|
|
227
185
|
// 辅助:解析版本信息
|
|
228
|
-
getVersionInfo
|
|
229
|
-
const match = /^(\d+)\.(\d+)
|
|
186
|
+
getVersionInfo(info) {
|
|
187
|
+
const match = /^(\d+)\.(\d+)\./.exec(info.version);
|
|
230
188
|
if (!match) {
|
|
231
|
-
this.log.silly('- failed to parse version:', info.version)
|
|
232
|
-
return {}
|
|
233
|
-
}
|
|
234
|
-
this.log.silly('- version match = %j', match)
|
|
235
|
-
const ret = {
|
|
236
|
-
version: info.version,
|
|
237
|
-
versionMajor: parseInt(match[1], 10),
|
|
238
|
-
versionMinor: parseInt(match[2], 10)
|
|
189
|
+
this.log.silly('- failed to parse version:', info.version);
|
|
190
|
+
return {};
|
|
239
191
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (ret.versionMajor === 17) {
|
|
249
|
-
ret.versionYear = 2022
|
|
250
|
-
return ret
|
|
251
|
-
}
|
|
252
|
-
if (ret.versionMajor === 18) {
|
|
253
|
-
ret.versionYear = 2026
|
|
254
|
-
return ret
|
|
192
|
+
|
|
193
|
+
this.log.silly('- version match = %j', match);
|
|
194
|
+
const versionMajor = parseInt(match[1], 10), versionMinor = parseInt(match[2], 10),
|
|
195
|
+
VERSION_YEAR = { 15: 2017, 16: 2019, 17: 2022, 18: 2026, }, versionYear = VERSION_YEAR[versionMajor];
|
|
196
|
+
|
|
197
|
+
if (!versionYear) {
|
|
198
|
+
this.log.silly('- unsupported version:', versionMajor);
|
|
199
|
+
return {};
|
|
255
200
|
}
|
|
256
|
-
|
|
257
|
-
return {}
|
|
201
|
+
|
|
202
|
+
return { version: info.version, versionMajor, versionMinor, versionYear };
|
|
258
203
|
}
|
|
259
204
|
|
|
260
|
-
msBuildPathExists
|
|
261
|
-
return existsSync(path)
|
|
205
|
+
msBuildPathExists(path) {
|
|
206
|
+
return existsSync(path);
|
|
262
207
|
}
|
|
263
208
|
|
|
264
209
|
// 辅助:解析 MSBuild 信息
|
|
265
|
-
getMSBuild
|
|
266
|
-
const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base'
|
|
267
|
-
|
|
268
|
-
|
|
210
|
+
getMSBuild(info, versionYear) {
|
|
211
|
+
const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base',
|
|
212
|
+
msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe'),
|
|
213
|
+
msbuildPathArm64 = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'arm64', 'MSBuild.exe');
|
|
269
214
|
if (info.packages.indexOf(pkg) !== -1) {
|
|
270
215
|
this.log.silly('- found VC.MSBuild.Base')
|
|
271
|
-
if (versionYear === 2017)
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
if (versionYear === 2019) {
|
|
275
|
-
return msbuildPath
|
|
276
|
-
}
|
|
216
|
+
if (versionYear === 2017) return path.join(info.path, 'MSBuild', '15.0', 'Bin', 'MSBuild.exe');
|
|
217
|
+
if (versionYear === 2019) return msbuildPath;
|
|
277
218
|
}
|
|
278
219
|
/**
|
|
279
220
|
* Visual Studio 2022 没有 MSBuild 包。
|
|
280
221
|
* ARM64 上编译的支持从 MSVC 14.32.31326 起加入,
|
|
281
222
|
* 因此用户设备是 ARM64 时优先使用它。
|
|
282
223
|
*/
|
|
283
|
-
if (process.arch === 'arm64' && this.msBuildPathExists(msbuildPathArm64))
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return msbuildPath
|
|
287
|
-
}
|
|
288
|
-
return null
|
|
224
|
+
if (process.arch === 'arm64' && this.msBuildPathExists(msbuildPathArm64)) return msbuildPathArm64;
|
|
225
|
+
else if (this.msBuildPathExists(msbuildPath)) return msbuildPath;
|
|
226
|
+
return null;
|
|
289
227
|
}
|
|
290
228
|
|
|
291
229
|
// 辅助:解析 toolset 信息
|
|
292
|
-
getToolset
|
|
293
|
-
const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
if (versionYear === 2017) {
|
|
305
|
-
return 'v141'
|
|
306
|
-
} else if (versionYear === 2019) {
|
|
307
|
-
return 'v142'
|
|
308
|
-
} else if (versionYear === 2022) {
|
|
309
|
-
return 'v143'
|
|
310
|
-
} else if (versionYear === 2026) {
|
|
311
|
-
return 'v145'
|
|
312
|
-
}
|
|
313
|
-
this.log.silly('- invalid versionYear:', versionYear)
|
|
314
|
-
return null
|
|
230
|
+
getToolset(info, versionYear) {
|
|
231
|
+
const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', express = 'Microsoft.VisualStudio.WDExpress';
|
|
232
|
+
if (info.packages.indexOf(pkg) !== -1) this.log.silly('- found VC.Tools.x86.x64');
|
|
233
|
+
else if (info.packages.indexOf(express) !== -1) this.log.silly('- found Visual Studio Express (looking for toolset)');
|
|
234
|
+
else return null;
|
|
235
|
+
|
|
236
|
+
if (versionYear === 2017) return 'v141'
|
|
237
|
+
else if (versionYear === 2019) return 'v142';
|
|
238
|
+
else if (versionYear === 2022) return 'v143';
|
|
239
|
+
else if (versionYear === 2026) return 'v145';
|
|
240
|
+
this.log.silly('- invalid versionYear:', versionYear);
|
|
241
|
+
return null;
|
|
315
242
|
}
|
|
316
243
|
|
|
317
244
|
// 辅助:解析 Windows SDK 信息
|
|
318
|
-
getSDK
|
|
319
|
-
const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK'
|
|
320
|
-
|
|
321
|
-
|
|
245
|
+
getSDK(info) {
|
|
246
|
+
const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK',
|
|
247
|
+
win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.',
|
|
248
|
+
win11SDKPrefix = 'Microsoft.VisualStudio.Component.Windows11SDK.';
|
|
322
249
|
|
|
323
|
-
let Win10or11SDKVer = 0
|
|
250
|
+
let Win10or11SDKVer = 0;
|
|
324
251
|
info.packages.forEach((pkg) => {
|
|
325
|
-
if (!pkg.startsWith(win10SDKPrefix) && !pkg.startsWith(win11SDKPrefix))
|
|
326
|
-
return
|
|
327
|
-
}
|
|
252
|
+
if (!pkg.startsWith(win10SDKPrefix) && !pkg.startsWith(win11SDKPrefix)) return;
|
|
328
253
|
const parts = pkg.split('.')
|
|
329
254
|
if (parts.length > 5 && parts[5] !== 'Desktop') {
|
|
330
|
-
this.log.silly('- ignoring non-Desktop Win10/11SDK:', pkg)
|
|
331
|
-
return
|
|
255
|
+
this.log.silly('- ignoring non-Desktop Win10/11SDK:', pkg);
|
|
256
|
+
return;
|
|
332
257
|
}
|
|
333
|
-
const foundSdkVer = parseInt(parts[4], 10)
|
|
258
|
+
const foundSdkVer = parseInt(parts[4], 10);
|
|
334
259
|
if (isNaN(foundSdkVer)) {
|
|
335
260
|
// Microsoft.VisualStudio.Component.Windows10SDK.IpOverUsb
|
|
336
|
-
this.log.silly('- failed to parse Win10/11SDK number:', pkg)
|
|
337
|
-
return
|
|
261
|
+
this.log.silly('- failed to parse Win10/11SDK number:', pkg);
|
|
262
|
+
return;
|
|
338
263
|
}
|
|
339
|
-
this.log.silly('- found Win10/11SDK:', foundSdkVer)
|
|
340
|
-
Win10or11SDKVer = Math.max(Win10or11SDKVer, foundSdkVer)
|
|
264
|
+
this.log.silly('- found Win10/11SDK:', foundSdkVer);
|
|
265
|
+
Win10or11SDKVer = Math.max(Win10or11SDKVer, foundSdkVer);
|
|
341
266
|
})
|
|
342
267
|
|
|
343
|
-
if (Win10or11SDKVer !== 0) {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
return '8.1'
|
|
268
|
+
if (Win10or11SDKVer !== 0) return `10.0.${Win10or11SDKVer}.0`;
|
|
269
|
+
else if (info.packages.indexOf(win8SDK) !== -1) {
|
|
270
|
+
this.log.silly('- found Win8SDK');
|
|
271
|
+
return '8.1';
|
|
348
272
|
}
|
|
349
|
-
return null
|
|
273
|
+
return null;
|
|
350
274
|
}
|
|
351
275
|
|
|
352
276
|
// 查找可用的 Visual Studio 2015
|
|
353
|
-
async findVisualStudio2015
|
|
277
|
+
async findVisualStudio2015() {
|
|
354
278
|
if (this.nodeSemver.major >= 19) {
|
|
355
|
-
this.addLog(
|
|
356
|
-
|
|
357
|
-
return null
|
|
279
|
+
this.addLog('not looking for VS2015 as it is only supported up to Node.js 18');
|
|
280
|
+
return null;
|
|
358
281
|
}
|
|
359
|
-
return this.findOldVS({
|
|
360
|
-
version: '14.0',
|
|
361
|
-
versionMajor: 14,
|
|
362
|
-
versionMinor: 0,
|
|
363
|
-
versionYear: 2015,
|
|
364
|
-
toolset: 'v140'
|
|
365
|
-
})
|
|
282
|
+
return this.findOldVS({ version: '14.0', versionMajor: 14, versionMinor: 0, versionYear: 2015, toolset: 'v140' });
|
|
366
283
|
}
|
|
367
284
|
|
|
368
285
|
// 查找可用的 Visual Studio 2013
|
|
369
|
-
async findVisualStudio2013
|
|
286
|
+
async findVisualStudio2013() {
|
|
370
287
|
if (this.nodeSemver.major >= 9) {
|
|
371
|
-
this.addLog(
|
|
372
|
-
|
|
373
|
-
return null
|
|
288
|
+
this.addLog('not looking for VS2013 as it is only supported up to Node.js 8')
|
|
289
|
+
return null;
|
|
374
290
|
}
|
|
375
|
-
return this.findOldVS({
|
|
376
|
-
version: '12.0',
|
|
377
|
-
versionMajor: 12,
|
|
378
|
-
versionMinor: 0,
|
|
379
|
-
versionYear: 2013,
|
|
380
|
-
toolset: 'v120'
|
|
381
|
-
})
|
|
291
|
+
return this.findOldVS({ version: '12.0', versionMajor: 12, versionMinor: 0, versionYear: 2013, toolset: 'v120' });
|
|
382
292
|
}
|
|
383
293
|
|
|
384
294
|
// 辅助:VS2013 和 VS2015 的公共代码
|
|
385
|
-
async findOldVS
|
|
295
|
+
async findOldVS(info) {
|
|
386
296
|
const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7',
|
|
387
|
-
'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7']
|
|
388
|
-
|
|
297
|
+
'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7'],
|
|
298
|
+
regMSBuild = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions';
|
|
389
299
|
|
|
390
|
-
this.addLog(`looking for Visual Studio ${info.versionYear}`)
|
|
300
|
+
this.addLog(`looking for Visual Studio ${info.versionYear}`);
|
|
391
301
|
try {
|
|
392
|
-
let res = await this.regSearchKeys(regVC7, info.version, [])
|
|
393
|
-
const vsPath = path.resolve(res, '..')
|
|
394
|
-
this.addLog(`- found in "${vsPath}"`)
|
|
395
|
-
const msBuildRegOpts = process.arch === 'ia32' ? [] : ['/reg:32']
|
|
302
|
+
let res = await this.regSearchKeys(regVC7, info.version, []);
|
|
303
|
+
const msBuildRegOpts = process.arch === 'ia32' ? [] : ['/reg:32'], vsPath = path.resolve(res, '..');
|
|
304
|
+
this.addLog(`- found in "${vsPath}"`);
|
|
396
305
|
|
|
397
306
|
try {
|
|
398
|
-
res = await this.regSearchKeys([`${regMSBuild}\\${info.version}`], 'MSBuildToolsPath', msBuildRegOpts)
|
|
307
|
+
res = await this.regSearchKeys([`${regMSBuild}\\${info.version}`], 'MSBuildToolsPath', msBuildRegOpts);
|
|
399
308
|
} catch (err) {
|
|
400
|
-
this.addLog('- could not find MSBuild in registry for this version')
|
|
401
|
-
return null
|
|
309
|
+
this.addLog('- could not find MSBuild in registry for this version');
|
|
310
|
+
return null;
|
|
402
311
|
}
|
|
403
312
|
|
|
404
|
-
const msBuild = path.join(res, 'MSBuild.exe')
|
|
405
|
-
this.addLog(`- MSBuild in "${msBuild}"`)
|
|
406
|
-
|
|
407
|
-
if (!this.checkConfigVersion(info.versionYear, vsPath)) {
|
|
408
|
-
return null
|
|
409
|
-
}
|
|
313
|
+
const msBuild = path.join(res, 'MSBuild.exe');
|
|
314
|
+
this.addLog(`- MSBuild in "${msBuild}"`);
|
|
410
315
|
|
|
411
|
-
info.
|
|
412
|
-
info.msBuild = msBuild
|
|
413
|
-
info
|
|
414
|
-
return info
|
|
316
|
+
if (!this.checkConfigVersion(info.versionYear, vsPath)) return null;
|
|
317
|
+
info.path = vsPath, info.msBuild = msBuild, info.sdk = null;
|
|
318
|
+
return info;
|
|
415
319
|
} catch (err) {
|
|
416
|
-
this.addLog('- not found')
|
|
417
|
-
return null
|
|
320
|
+
this.addLog('- not found');
|
|
321
|
+
return null;
|
|
418
322
|
}
|
|
419
323
|
}
|
|
420
324
|
|
|
@@ -422,27 +326,24 @@ class VisualStudioFinder {
|
|
|
422
326
|
// - 把它加入 validVersions,用于在指定版本未找到时输出;
|
|
423
327
|
// - 检查是否是请求的版本;
|
|
424
328
|
// - 检查是否匹配 Visual Studio 命令提示符。
|
|
425
|
-
checkConfigVersion
|
|
426
|
-
this.validVersions.push(versionYear)
|
|
427
|
-
this.validVersions.push(vsPath)
|
|
329
|
+
checkConfigVersion(versionYear, vsPath) {
|
|
330
|
+
this.validVersions.push(versionYear), this.validVersions.push(vsPath);
|
|
428
331
|
|
|
429
332
|
if (this.configVersionYear && this.configVersionYear !== versionYear) {
|
|
430
|
-
this.addLog('- msvs_version does not match this version')
|
|
431
|
-
return false
|
|
333
|
+
this.addLog('- msvs_version does not match this version');
|
|
334
|
+
return false;
|
|
432
335
|
}
|
|
433
|
-
if (this.configPath &&
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return false
|
|
336
|
+
if (this.configPath && path.relative(this.configPath, vsPath) !== '') {
|
|
337
|
+
this.addLog('- msvs_version does not point to this installation');
|
|
338
|
+
return false;
|
|
437
339
|
}
|
|
438
|
-
if (this.envVcInstallDir &&
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return false
|
|
340
|
+
if (this.envVcInstallDir && path.relative(this.envVcInstallDir, vsPath) !== '') {
|
|
341
|
+
this.addLog('- does not match this Visual Studio Command Prompt');
|
|
342
|
+
return false;
|
|
442
343
|
}
|
|
443
344
|
|
|
444
|
-
return true
|
|
345
|
+
return true;
|
|
445
346
|
}
|
|
446
347
|
}
|
|
447
348
|
|
|
448
|
-
export { VisualStudioFinder }
|
|
349
|
+
export { VisualStudioFinder }
|