11cb0ef41Sopenharmony_ci'use strict' 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst log = require('./log') 41cb0ef41Sopenharmony_ciconst { existsSync } = require('fs') 51cb0ef41Sopenharmony_ciconst { win32: path } = require('path') 61cb0ef41Sopenharmony_ciconst { regSearchKeys, execFile } = require('./util') 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciclass VisualStudioFinder { 91cb0ef41Sopenharmony_ci static findVisualStudio = (...args) => new VisualStudioFinder(...args).findVisualStudio() 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci log = log.withPrefix('find VS') 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci regSearchKeys = regSearchKeys 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci constructor (nodeSemver, configMsvsVersion) { 161cb0ef41Sopenharmony_ci this.nodeSemver = nodeSemver 171cb0ef41Sopenharmony_ci this.configMsvsVersion = configMsvsVersion 181cb0ef41Sopenharmony_ci this.errorLog = [] 191cb0ef41Sopenharmony_ci this.validVersions = [] 201cb0ef41Sopenharmony_ci } 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci // Logs a message at verbose level, but also saves it to be displayed later 231cb0ef41Sopenharmony_ci // at error level if an error occurs. This should help diagnose the problem. 241cb0ef41Sopenharmony_ci addLog (message) { 251cb0ef41Sopenharmony_ci this.log.verbose(message) 261cb0ef41Sopenharmony_ci this.errorLog.push(message) 271cb0ef41Sopenharmony_ci } 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci async findVisualStudio () { 301cb0ef41Sopenharmony_ci this.configVersionYear = null 311cb0ef41Sopenharmony_ci this.configPath = null 321cb0ef41Sopenharmony_ci if (this.configMsvsVersion) { 331cb0ef41Sopenharmony_ci this.addLog('msvs_version was set from command line or npm config') 341cb0ef41Sopenharmony_ci if (this.configMsvsVersion.match(/^\d{4}$/)) { 351cb0ef41Sopenharmony_ci this.configVersionYear = parseInt(this.configMsvsVersion, 10) 361cb0ef41Sopenharmony_ci this.addLog( 371cb0ef41Sopenharmony_ci `- looking for Visual Studio version ${this.configVersionYear}`) 381cb0ef41Sopenharmony_ci } else { 391cb0ef41Sopenharmony_ci this.configPath = path.resolve(this.configMsvsVersion) 401cb0ef41Sopenharmony_ci this.addLog( 411cb0ef41Sopenharmony_ci `- looking for Visual Studio installed in "${this.configPath}"`) 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci } else { 441cb0ef41Sopenharmony_ci this.addLog('msvs_version not set from command line or npm config') 451cb0ef41Sopenharmony_ci } 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci if (process.env.VCINSTALLDIR) { 481cb0ef41Sopenharmony_ci this.envVcInstallDir = 491cb0ef41Sopenharmony_ci path.resolve(process.env.VCINSTALLDIR, '..') 501cb0ef41Sopenharmony_ci this.addLog('running in VS Command Prompt, installation path is:\n' + 511cb0ef41Sopenharmony_ci `"${this.envVcInstallDir}"\n- will only use this version`) 521cb0ef41Sopenharmony_ci } else { 531cb0ef41Sopenharmony_ci this.addLog('VCINSTALLDIR not set, not running in VS Command Prompt') 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci const checks = [ 571cb0ef41Sopenharmony_ci () => this.findVisualStudio2017OrNewer(), 581cb0ef41Sopenharmony_ci () => this.findVisualStudio2015(), 591cb0ef41Sopenharmony_ci () => this.findVisualStudio2013() 601cb0ef41Sopenharmony_ci ] 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci for (const check of checks) { 631cb0ef41Sopenharmony_ci const info = await check() 641cb0ef41Sopenharmony_ci if (info) { 651cb0ef41Sopenharmony_ci return this.succeed(info) 661cb0ef41Sopenharmony_ci } 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci return this.fail() 701cb0ef41Sopenharmony_ci } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci succeed (info) { 731cb0ef41Sopenharmony_ci this.log.info(`using VS${info.versionYear} (${info.version}) found at:` + 741cb0ef41Sopenharmony_ci `\n"${info.path}"` + 751cb0ef41Sopenharmony_ci '\nrun with --verbose for detailed information') 761cb0ef41Sopenharmony_ci return info 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci fail () { 801cb0ef41Sopenharmony_ci if (this.configMsvsVersion && this.envVcInstallDir) { 811cb0ef41Sopenharmony_ci this.errorLog.push( 821cb0ef41Sopenharmony_ci 'msvs_version does not match this VS Command Prompt or the', 831cb0ef41Sopenharmony_ci 'installation cannot be used.') 841cb0ef41Sopenharmony_ci } else if (this.configMsvsVersion) { 851cb0ef41Sopenharmony_ci // If msvs_version was specified but finding VS failed, print what would 861cb0ef41Sopenharmony_ci // have been accepted 871cb0ef41Sopenharmony_ci this.errorLog.push('') 881cb0ef41Sopenharmony_ci if (this.validVersions) { 891cb0ef41Sopenharmony_ci this.errorLog.push('valid versions for msvs_version:') 901cb0ef41Sopenharmony_ci this.validVersions.forEach((version) => { 911cb0ef41Sopenharmony_ci this.errorLog.push(`- "${version}"`) 921cb0ef41Sopenharmony_ci }) 931cb0ef41Sopenharmony_ci } else { 941cb0ef41Sopenharmony_ci this.errorLog.push('no valid versions for msvs_version were found') 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci const errorLog = this.errorLog.join('\n') 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci // For Windows 80 col console, use up to the column before the one marked 1011cb0ef41Sopenharmony_ci // with X (total 79 chars including logger prefix, 62 chars usable here): 1021cb0ef41Sopenharmony_ci // X 1031cb0ef41Sopenharmony_ci const infoLog = [ 1041cb0ef41Sopenharmony_ci '**************************************************************', 1051cb0ef41Sopenharmony_ci 'You need to install the latest version of Visual Studio', 1061cb0ef41Sopenharmony_ci 'including the "Desktop development with C++" workload.', 1071cb0ef41Sopenharmony_ci 'For more information consult the documentation at:', 1081cb0ef41Sopenharmony_ci 'https://github.com/nodejs/node-gyp#on-windows', 1091cb0ef41Sopenharmony_ci '**************************************************************' 1101cb0ef41Sopenharmony_ci ].join('\n') 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci this.log.error(`\n${errorLog}\n\n${infoLog}\n`) 1131cb0ef41Sopenharmony_ci throw new Error('Could not find any Visual Studio installation to use') 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci // Invoke the PowerShell script to get information about Visual Studio 2017 1171cb0ef41Sopenharmony_ci // or newer installations 1181cb0ef41Sopenharmony_ci async findVisualStudio2017OrNewer () { 1191cb0ef41Sopenharmony_ci const ps = path.join(process.env.SystemRoot, 'System32', 1201cb0ef41Sopenharmony_ci 'WindowsPowerShell', 'v1.0', 'powershell.exe') 1211cb0ef41Sopenharmony_ci const csFile = path.join(__dirname, 'Find-VisualStudio.cs') 1221cb0ef41Sopenharmony_ci const psArgs = [ 1231cb0ef41Sopenharmony_ci '-ExecutionPolicy', 1241cb0ef41Sopenharmony_ci 'Unrestricted', 1251cb0ef41Sopenharmony_ci '-NoProfile', 1261cb0ef41Sopenharmony_ci '-Command', 1271cb0ef41Sopenharmony_ci '&{Add-Type -Path \'' + csFile + '\';' + '[VisualStudioConfiguration.Main]::PrintJson()}' 1281cb0ef41Sopenharmony_ci ] 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci this.log.silly('Running', ps, psArgs) 1311cb0ef41Sopenharmony_ci const [err, stdout, stderr] = await execFile(ps, psArgs, { encoding: 'utf8' }) 1321cb0ef41Sopenharmony_ci return this.parseData(err, stdout, stderr) 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci // Parse the output of the PowerShell script and look for an installation 1361cb0ef41Sopenharmony_ci // of Visual Studio 2017 or newer to use 1371cb0ef41Sopenharmony_ci parseData (err, stdout, stderr) { 1381cb0ef41Sopenharmony_ci this.log.silly('PS stderr = %j', stderr) 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci const failPowershell = () => { 1411cb0ef41Sopenharmony_ci this.addLog( 1421cb0ef41Sopenharmony_ci 'could not use PowerShell to find Visual Studio 2017 or newer, try re-running with \'--loglevel silly\' for more details') 1431cb0ef41Sopenharmony_ci return null 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci if (err) { 1471cb0ef41Sopenharmony_ci this.log.silly('PS err = %j', err && (err.stack || err)) 1481cb0ef41Sopenharmony_ci return failPowershell() 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci let vsInfo 1521cb0ef41Sopenharmony_ci try { 1531cb0ef41Sopenharmony_ci vsInfo = JSON.parse(stdout) 1541cb0ef41Sopenharmony_ci } catch (e) { 1551cb0ef41Sopenharmony_ci this.log.silly('PS stdout = %j', stdout) 1561cb0ef41Sopenharmony_ci this.log.silly(e) 1571cb0ef41Sopenharmony_ci return failPowershell() 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci if (!Array.isArray(vsInfo)) { 1611cb0ef41Sopenharmony_ci this.log.silly('PS stdout = %j', stdout) 1621cb0ef41Sopenharmony_ci return failPowershell() 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci vsInfo = vsInfo.map((info) => { 1661cb0ef41Sopenharmony_ci this.log.silly(`processing installation: "${info.path}"`) 1671cb0ef41Sopenharmony_ci info.path = path.resolve(info.path) 1681cb0ef41Sopenharmony_ci const ret = this.getVersionInfo(info) 1691cb0ef41Sopenharmony_ci ret.path = info.path 1701cb0ef41Sopenharmony_ci ret.msBuild = this.getMSBuild(info, ret.versionYear) 1711cb0ef41Sopenharmony_ci ret.toolset = this.getToolset(info, ret.versionYear) 1721cb0ef41Sopenharmony_ci ret.sdk = this.getSDK(info) 1731cb0ef41Sopenharmony_ci return ret 1741cb0ef41Sopenharmony_ci }) 1751cb0ef41Sopenharmony_ci this.log.silly('vsInfo:', vsInfo) 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci // Remove future versions or errors parsing version number 1781cb0ef41Sopenharmony_ci vsInfo = vsInfo.filter((info) => { 1791cb0ef41Sopenharmony_ci if (info.versionYear) { 1801cb0ef41Sopenharmony_ci return true 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci this.addLog(`unknown version "${info.version}" found at "${info.path}"`) 1831cb0ef41Sopenharmony_ci return false 1841cb0ef41Sopenharmony_ci }) 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci // Sort to place newer versions first 1871cb0ef41Sopenharmony_ci vsInfo.sort((a, b) => b.versionYear - a.versionYear) 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci for (let i = 0; i < vsInfo.length; ++i) { 1901cb0ef41Sopenharmony_ci const info = vsInfo[i] 1911cb0ef41Sopenharmony_ci this.addLog(`checking VS${info.versionYear} (${info.version}) found ` + 1921cb0ef41Sopenharmony_ci `at:\n"${info.path}"`) 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci if (info.msBuild) { 1951cb0ef41Sopenharmony_ci this.addLog('- found "Visual Studio C++ core features"') 1961cb0ef41Sopenharmony_ci } else { 1971cb0ef41Sopenharmony_ci this.addLog('- "Visual Studio C++ core features" missing') 1981cb0ef41Sopenharmony_ci continue 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci if (info.toolset) { 2021cb0ef41Sopenharmony_ci this.addLog(`- found VC++ toolset: ${info.toolset}`) 2031cb0ef41Sopenharmony_ci } else { 2041cb0ef41Sopenharmony_ci this.addLog('- missing any VC++ toolset') 2051cb0ef41Sopenharmony_ci continue 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci if (info.sdk) { 2091cb0ef41Sopenharmony_ci this.addLog(`- found Windows SDK: ${info.sdk}`) 2101cb0ef41Sopenharmony_ci } else { 2111cb0ef41Sopenharmony_ci this.addLog('- missing any Windows SDK') 2121cb0ef41Sopenharmony_ci continue 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci if (!this.checkConfigVersion(info.versionYear, info.path)) { 2161cb0ef41Sopenharmony_ci continue 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci return info 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci this.addLog( 2231cb0ef41Sopenharmony_ci 'could not find a version of Visual Studio 2017 or newer to use') 2241cb0ef41Sopenharmony_ci return null 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci // Helper - process version information 2281cb0ef41Sopenharmony_ci getVersionInfo (info) { 2291cb0ef41Sopenharmony_ci const match = /^(\d+)\.(\d+)\..*/.exec(info.version) 2301cb0ef41Sopenharmony_ci if (!match) { 2311cb0ef41Sopenharmony_ci this.log.silly('- failed to parse version:', info.version) 2321cb0ef41Sopenharmony_ci return {} 2331cb0ef41Sopenharmony_ci } 2341cb0ef41Sopenharmony_ci this.log.silly('- version match = %j', match) 2351cb0ef41Sopenharmony_ci const ret = { 2361cb0ef41Sopenharmony_ci version: info.version, 2371cb0ef41Sopenharmony_ci versionMajor: parseInt(match[1], 10), 2381cb0ef41Sopenharmony_ci versionMinor: parseInt(match[2], 10) 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci if (ret.versionMajor === 15) { 2411cb0ef41Sopenharmony_ci ret.versionYear = 2017 2421cb0ef41Sopenharmony_ci return ret 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci if (ret.versionMajor === 16) { 2451cb0ef41Sopenharmony_ci ret.versionYear = 2019 2461cb0ef41Sopenharmony_ci return ret 2471cb0ef41Sopenharmony_ci } 2481cb0ef41Sopenharmony_ci if (ret.versionMajor === 17) { 2491cb0ef41Sopenharmony_ci ret.versionYear = 2022 2501cb0ef41Sopenharmony_ci return ret 2511cb0ef41Sopenharmony_ci } 2521cb0ef41Sopenharmony_ci this.log.silly('- unsupported version:', ret.versionMajor) 2531cb0ef41Sopenharmony_ci return {} 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci msBuildPathExists (path) { 2571cb0ef41Sopenharmony_ci return existsSync(path) 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci // Helper - process MSBuild information 2611cb0ef41Sopenharmony_ci getMSBuild (info, versionYear) { 2621cb0ef41Sopenharmony_ci const pkg = 'Microsoft.VisualStudio.VC.MSBuild.Base' 2631cb0ef41Sopenharmony_ci const msbuildPath = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'MSBuild.exe') 2641cb0ef41Sopenharmony_ci const msbuildPathArm64 = path.join(info.path, 'MSBuild', 'Current', 'Bin', 'arm64', 'MSBuild.exe') 2651cb0ef41Sopenharmony_ci if (info.packages.indexOf(pkg) !== -1) { 2661cb0ef41Sopenharmony_ci this.log.silly('- found VC.MSBuild.Base') 2671cb0ef41Sopenharmony_ci if (versionYear === 2017) { 2681cb0ef41Sopenharmony_ci return path.join(info.path, 'MSBuild', '15.0', 'Bin', 'MSBuild.exe') 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci if (versionYear === 2019) { 2711cb0ef41Sopenharmony_ci return msbuildPath 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci /** 2751cb0ef41Sopenharmony_ci * Visual Studio 2022 doesn't have the MSBuild package. 2761cb0ef41Sopenharmony_ci * Support for compiling _on_ ARM64 was added in MSVC 14.32.31326, 2771cb0ef41Sopenharmony_ci * so let's leverage it if the user has an ARM64 device. 2781cb0ef41Sopenharmony_ci */ 2791cb0ef41Sopenharmony_ci if (process.arch === 'arm64' && this.msBuildPathExists(msbuildPathArm64)) { 2801cb0ef41Sopenharmony_ci return msbuildPathArm64 2811cb0ef41Sopenharmony_ci } else if (this.msBuildPathExists(msbuildPath)) { 2821cb0ef41Sopenharmony_ci return msbuildPath 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci return null 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci // Helper - process toolset information 2881cb0ef41Sopenharmony_ci getToolset (info, versionYear) { 2891cb0ef41Sopenharmony_ci const pkg = 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64' 2901cb0ef41Sopenharmony_ci const express = 'Microsoft.VisualStudio.WDExpress' 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci if (info.packages.indexOf(pkg) !== -1) { 2931cb0ef41Sopenharmony_ci this.log.silly('- found VC.Tools.x86.x64') 2941cb0ef41Sopenharmony_ci } else if (info.packages.indexOf(express) !== -1) { 2951cb0ef41Sopenharmony_ci this.log.silly('- found Visual Studio Express (looking for toolset)') 2961cb0ef41Sopenharmony_ci } else { 2971cb0ef41Sopenharmony_ci return null 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci if (versionYear === 2017) { 3011cb0ef41Sopenharmony_ci return 'v141' 3021cb0ef41Sopenharmony_ci } else if (versionYear === 2019) { 3031cb0ef41Sopenharmony_ci return 'v142' 3041cb0ef41Sopenharmony_ci } else if (versionYear === 2022) { 3051cb0ef41Sopenharmony_ci return 'v143' 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci this.log.silly('- invalid versionYear:', versionYear) 3081cb0ef41Sopenharmony_ci return null 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci // Helper - process Windows SDK information 3121cb0ef41Sopenharmony_ci getSDK (info) { 3131cb0ef41Sopenharmony_ci const win8SDK = 'Microsoft.VisualStudio.Component.Windows81SDK' 3141cb0ef41Sopenharmony_ci const win10SDKPrefix = 'Microsoft.VisualStudio.Component.Windows10SDK.' 3151cb0ef41Sopenharmony_ci const win11SDKPrefix = 'Microsoft.VisualStudio.Component.Windows11SDK.' 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci let Win10or11SDKVer = 0 3181cb0ef41Sopenharmony_ci info.packages.forEach((pkg) => { 3191cb0ef41Sopenharmony_ci if (!pkg.startsWith(win10SDKPrefix) && !pkg.startsWith(win11SDKPrefix)) { 3201cb0ef41Sopenharmony_ci return 3211cb0ef41Sopenharmony_ci } 3221cb0ef41Sopenharmony_ci const parts = pkg.split('.') 3231cb0ef41Sopenharmony_ci if (parts.length > 5 && parts[5] !== 'Desktop') { 3241cb0ef41Sopenharmony_ci this.log.silly('- ignoring non-Desktop Win10/11SDK:', pkg) 3251cb0ef41Sopenharmony_ci return 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci const foundSdkVer = parseInt(parts[4], 10) 3281cb0ef41Sopenharmony_ci if (isNaN(foundSdkVer)) { 3291cb0ef41Sopenharmony_ci // Microsoft.VisualStudio.Component.Windows10SDK.IpOverUsb 3301cb0ef41Sopenharmony_ci this.log.silly('- failed to parse Win10/11SDK number:', pkg) 3311cb0ef41Sopenharmony_ci return 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci this.log.silly('- found Win10/11SDK:', foundSdkVer) 3341cb0ef41Sopenharmony_ci Win10or11SDKVer = Math.max(Win10or11SDKVer, foundSdkVer) 3351cb0ef41Sopenharmony_ci }) 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci if (Win10or11SDKVer !== 0) { 3381cb0ef41Sopenharmony_ci return `10.0.${Win10or11SDKVer}.0` 3391cb0ef41Sopenharmony_ci } else if (info.packages.indexOf(win8SDK) !== -1) { 3401cb0ef41Sopenharmony_ci this.log.silly('- found Win8SDK') 3411cb0ef41Sopenharmony_ci return '8.1' 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci return null 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci // Find an installation of Visual Studio 2015 to use 3471cb0ef41Sopenharmony_ci async findVisualStudio2015 () { 3481cb0ef41Sopenharmony_ci if (this.nodeSemver.major >= 19) { 3491cb0ef41Sopenharmony_ci this.addLog( 3501cb0ef41Sopenharmony_ci 'not looking for VS2015 as it is only supported up to Node.js 18') 3511cb0ef41Sopenharmony_ci return null 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci return this.findOldVS({ 3541cb0ef41Sopenharmony_ci version: '14.0', 3551cb0ef41Sopenharmony_ci versionMajor: 14, 3561cb0ef41Sopenharmony_ci versionMinor: 0, 3571cb0ef41Sopenharmony_ci versionYear: 2015, 3581cb0ef41Sopenharmony_ci toolset: 'v140' 3591cb0ef41Sopenharmony_ci }) 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci // Find an installation of Visual Studio 2013 to use 3631cb0ef41Sopenharmony_ci async findVisualStudio2013 () { 3641cb0ef41Sopenharmony_ci if (this.nodeSemver.major >= 9) { 3651cb0ef41Sopenharmony_ci this.addLog( 3661cb0ef41Sopenharmony_ci 'not looking for VS2013 as it is only supported up to Node.js 8') 3671cb0ef41Sopenharmony_ci return null 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci return this.findOldVS({ 3701cb0ef41Sopenharmony_ci version: '12.0', 3711cb0ef41Sopenharmony_ci versionMajor: 12, 3721cb0ef41Sopenharmony_ci versionMinor: 0, 3731cb0ef41Sopenharmony_ci versionYear: 2013, 3741cb0ef41Sopenharmony_ci toolset: 'v120' 3751cb0ef41Sopenharmony_ci }) 3761cb0ef41Sopenharmony_ci } 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci // Helper - common code for VS2013 and VS2015 3791cb0ef41Sopenharmony_ci async findOldVS (info) { 3801cb0ef41Sopenharmony_ci const regVC7 = ['HKLM\\Software\\Microsoft\\VisualStudio\\SxS\\VC7', 3811cb0ef41Sopenharmony_ci 'HKLM\\Software\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7'] 3821cb0ef41Sopenharmony_ci const regMSBuild = 'HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions' 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ci this.addLog(`looking for Visual Studio ${info.versionYear}`) 3851cb0ef41Sopenharmony_ci try { 3861cb0ef41Sopenharmony_ci let res = await this.regSearchKeys(regVC7, info.version, []) 3871cb0ef41Sopenharmony_ci const vsPath = path.resolve(res, '..') 3881cb0ef41Sopenharmony_ci this.addLog(`- found in "${vsPath}"`) 3891cb0ef41Sopenharmony_ci const msBuildRegOpts = process.arch === 'ia32' ? [] : ['/reg:32'] 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci try { 3921cb0ef41Sopenharmony_ci res = await this.regSearchKeys([`${regMSBuild}\\${info.version}`], 'MSBuildToolsPath', msBuildRegOpts) 3931cb0ef41Sopenharmony_ci } catch (err) { 3941cb0ef41Sopenharmony_ci this.addLog('- could not find MSBuild in registry for this version') 3951cb0ef41Sopenharmony_ci return null 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci const msBuild = path.join(res, 'MSBuild.exe') 3991cb0ef41Sopenharmony_ci this.addLog(`- MSBuild in "${msBuild}"`) 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci if (!this.checkConfigVersion(info.versionYear, vsPath)) { 4021cb0ef41Sopenharmony_ci return null 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci info.path = vsPath 4061cb0ef41Sopenharmony_ci info.msBuild = msBuild 4071cb0ef41Sopenharmony_ci info.sdk = null 4081cb0ef41Sopenharmony_ci return info 4091cb0ef41Sopenharmony_ci } catch (err) { 4101cb0ef41Sopenharmony_ci this.addLog('- not found') 4111cb0ef41Sopenharmony_ci return null 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci } 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci // After finding a usable version of Visual Studio: 4161cb0ef41Sopenharmony_ci // - add it to validVersions to be displayed at the end if a specific 4171cb0ef41Sopenharmony_ci // version was requested and not found; 4181cb0ef41Sopenharmony_ci // - check if this is the version that was requested. 4191cb0ef41Sopenharmony_ci // - check if this matches the Visual Studio Command Prompt 4201cb0ef41Sopenharmony_ci checkConfigVersion (versionYear, vsPath) { 4211cb0ef41Sopenharmony_ci this.validVersions.push(versionYear) 4221cb0ef41Sopenharmony_ci this.validVersions.push(vsPath) 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci if (this.configVersionYear && this.configVersionYear !== versionYear) { 4251cb0ef41Sopenharmony_ci this.addLog('- msvs_version does not match this version') 4261cb0ef41Sopenharmony_ci return false 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci if (this.configPath && 4291cb0ef41Sopenharmony_ci path.relative(this.configPath, vsPath) !== '') { 4301cb0ef41Sopenharmony_ci this.addLog('- msvs_version does not point to this installation') 4311cb0ef41Sopenharmony_ci return false 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci if (this.envVcInstallDir && 4341cb0ef41Sopenharmony_ci path.relative(this.envVcInstallDir, vsPath) !== '') { 4351cb0ef41Sopenharmony_ci this.addLog('- does not match this Visual Studio Command Prompt') 4361cb0ef41Sopenharmony_ci return false 4371cb0ef41Sopenharmony_ci } 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci return true 4401cb0ef41Sopenharmony_ci } 4411cb0ef41Sopenharmony_ci} 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_cimodule.exports = VisualStudioFinder 444