From d38af2e0c2a81b12cd221b1f8517fb89e609d62c Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 9 Jul 2024 23:13:40 +0800 Subject: [PATCH] feat: allow VCINSTALLDIR to specify a portable instance (#3036) --- lib/find-visualstudio.js | 46 +++++++++++++++++++++++++++++++++- test/test-find-visualstudio.js | 25 ++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/lib/find-visualstudio.js b/lib/find-visualstudio.js index a78e763480..2dc1930fd7 100644 --- a/lib/find-visualstudio.js +++ b/lib/find-visualstudio.js @@ -54,8 +54,10 @@ class VisualStudioFinder { } const checks = [ + () => this.findVisualStudio2019OrNewerFromSpecifiedLocation(), () => this.findVisualStudio2019OrNewerUsingSetupModule(), () => this.findVisualStudio2019OrNewer(), + () => this.findVisualStudio2017FromSpecifiedLocation(), () => this.findVisualStudio2017UsingSetupModule(), () => this.findVisualStudio2017(), () => this.findVisualStudio2015(), @@ -116,6 +118,48 @@ class VisualStudioFinder { throw new Error('Could not find any Visual Studio installation to use') } + async findVisualStudio2019OrNewerFromSpecifiedLocation () { + return this.findVSFromSpecifiedLocation([2019, 2022]) + } + + async findVisualStudio2017FromSpecifiedLocation () { + if (this.nodeSemver.major >= 22) { + this.addLog( + 'not looking for VS2017 as it is only supported up to Node.js 21') + return null + } + return this.findVSFromSpecifiedLocation([2017]) + } + + async findVSFromSpecifiedLocation (supportedYears) { + if (!this.envVcInstallDir) { + return null + } + const info = { + path: path.resolve(this.envVcInstallDir), + // Assume the version specified by the user is correct. + // Since Visual Studio 2015, the Developer Command Prompt sets the + // VSCMD_VER environment variable which contains the version information + // for Visual Studio. + // https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022 + version: process.env.VSCMD_VER, + packages: [ + 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + // Assume MSBuild exists. It will be checked in processing. + 'Microsoft.VisualStudio.VC.MSBuild.Base' + ] + } + + // Is there a better way to get SDK information? + const envWindowsSDKVersion = process.env.WindowsSDKVersion + const sdkVersionMatched = envWindowsSDKVersion?.match(/^(\d+)\.(\d+)\.(\d+)\..*/) + if (sdkVersionMatched) { + info.packages.push(`Microsoft.VisualStudio.Component.Windows10SDK.${sdkVersionMatched[3]}.Desktop`) + } + // pass for further processing + return this.processData([info], supportedYears) + } + async findVisualStudio2019OrNewerUsingSetupModule () { return this.findNewVSUsingSetupModule([2019, 2022]) } @@ -321,7 +365,7 @@ class VisualStudioFinder { // Helper - process version information getVersionInfo (info) { - const match = /^(\d+)\.(\d+)\..*/.exec(info.version) + const match = /^(\d+)\.(\d+)(?:\..*)?/.exec(info.version) if (!match) { this.log.silly('- failed to parse version:', info.version) return {} diff --git a/test/test-find-visualstudio.js b/test/test-find-visualstudio.js index 2c3f4e1981..9cad33eb4e 100644 --- a/test/test-find-visualstudio.js +++ b/test/test-find-visualstudio.js @@ -782,4 +782,29 @@ describe('find-visualstudio', function () { assert.ok(/find .* Visual Studio/i.test(err), 'expect error') assert.ok(!info, 'no data') }) + + it('run on a portable VS Command Prompt with sufficient environs', async function () { + process.env.VCINSTALLDIR = 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC' + process.env.VSCMD_VER = '16.0' + process.env.WindowsSDKVersion = '10.0.17763.0' + + const finder = new TestVisualStudioFinder(semverV1, null) + + allVsVersions(finder) + const { err, info } = await finder.findVisualStudio() + assert.strictEqual(err, null) + assert.deepStrictEqual(info, { + msBuild: 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\' + + 'Community\\MSBuild\\Current\\Bin\\MSBuild.exe', + path: + 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community', + sdk: '10.0.17763.0', + toolset: 'v142', + // Assume version in the environ is correct. + version: '16.0', + versionMajor: 16, + versionMinor: 0, + versionYear: 2019 + }) + }) })