From 357f053bad0e321bf16d7ed070be73c211e6b0ee Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Sun, 28 Aug 2022 00:21:09 -0700 Subject: [PATCH] Support specifying the visual studio version (#52) * feat: support specifying the visual studio version * fix: add upper bound for vswhere -version --- README.md | 2 ++ action.yml | 2 ++ index.js | 65 ++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 79b830f..59f62dd 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ jobs: - `uwp` – set `true` to build for Universal Windows Platform (i.e., for Windows Store) - `spectre` – set `true` to use Visual Studio libraries with [Spectre](https://meltdownattack.com) mitigations +- `vsversion` - The Visual Studio version to use. This can be the version number (e.g. 16.0 for 2019) or the year (e.g. "2019"). + ## Caveats ### Name conflicts with `shell: bash` diff --git a/action.yml b/action.yml index a8530e0..3799f17 100644 --- a/action.yml +++ b/action.yml @@ -12,6 +12,8 @@ inputs: description: VC++ compiler toolset version uwp: description: Build for Universal Windows Platform + vsversion: + description: The Visual Studio version to use. This can be the version number (e.g. 16.0 for 2019) or the year (e.g. "2019"). runs: using: node12 main: index.js diff --git a/index.js b/index.js index 10b1e48..9333da0 100644 --- a/index.js +++ b/index.js @@ -9,23 +9,67 @@ const PROGRAM_FILES = [process.env['ProgramFiles(x86)'], process.env['ProgramFil const EDITIONS = ['Enterprise', 'Professional', 'Community'] -const VERSIONS = ['2022', '2019', '2017'] +const YEARS = ['2022', '2019', '2017'] + +const VsYearVersion = { + '2022': '17.0', + '2019': '16.0', + '2017': '15.0', + '2015': '14.0', + '2013': '12.0', +} + +function vsversion_to_versionnumber(vsversion) { + if (Object.values(VsYearVersion).includes(vsversion)) { + return vsversion + } else { + if (vsversion in VsYearVersion) { + return VsYearVersion[vsversion] + } + } + return vsversion +} +exports.vsversion_to_versionnumber = vsversion_to_versionnumber + +function vsversion_to_year(vsversion) { + if (Object.keys(VsYearVersion).includes(vsversion)) { + return vsversion + } else { + for (const [year, ver] of Object.entries(VsYearVersion)) { + if (ver === vsversion) { + return year + } + } + } + return vsversion +} +exports.vsversion_to_year = vsversion_to_year const VSWHERE_PATH = `${PROGRAM_FILES_X86}\\Microsoft Visual Studio\\Installer` -function findWithVswhere(pattern) { +function findWithVswhere(pattern, version_pattern) { try { - let installationPath = child_process.execSync(`vswhere -products * -latest -prerelease -property installationPath`).toString().trim() + let installationPath = child_process.execSync(`vswhere -products * ${version_pattern} -prerelease -property installationPath`).toString().trim() return installationPath + '\\' + pattern } catch (e) { core.warning(`vswhere failed: ${e}`) } return null } +exports.findWithVswhere = findWithVswhere + +function findVcvarsall(vsversion) { + const vsversion_number = vsversion_to_versionnumber(vsversion) + let version_pattern + if (vsversion_number) { + const upper_bound = vsversion_number.split('.')[0] + '.9' + version_pattern = `-version "${vsversion_number},${upper_bound}"` + } else { + version_pattern = "-latest" + } -function findVcvarsall() { // If vswhere is available, ask it about the location of the latest Visual Studio. - let path = findWithVswhere('VC\\Auxiliary\\Build\\vcvarsall.bat') + let path = findWithVswhere('VC\\Auxiliary\\Build\\vcvarsall.bat', version_pattern) if (path && fs.existsSync(path)) { core.info(`Found with vswhere: ${path}`) return path @@ -34,8 +78,9 @@ function findVcvarsall() { // If that does not work, try the standard installation locations, // starting with the latest and moving to the oldest. + const years = vsversion ? [vsversion_to_year(vsversion)] : YEARS for (const prog_files of PROGRAM_FILES) { - for (const ver of VERSIONS) { + for (const ver of years) { for (const ed of EDITIONS) { path = `${prog_files}\\Microsoft Visual Studio\\${ver}\\${ed}\\VC\\Auxiliary\\Build\\vcvarsall.bat` core.info(`Trying standard location: ${path}`) @@ -58,6 +103,7 @@ function findVcvarsall() { throw new Error('Microsoft Visual Studio not found') } +exports.findVcvarsall = findVcvarsall function isPathVariable(name) { const pathLikeVariables = ['PATH', 'INCLUDE', 'LIB', 'LIBPATH'] @@ -75,7 +121,7 @@ function filterPathValue(path) { } /** See https://github.com/ilammy/msvc-dev-cmd#inputs */ -function setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre) { +function setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre, vsversion) { if (process.platform != 'win32') { core.info('This is not a Windows virtual environment, bye!') return @@ -114,7 +160,7 @@ function setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre) { args.push('-vcvars_spectre_libs=spectre') } - const vcvars = `"${findVcvarsall()}" ${args.join(' ')}` + const vcvars = `"${findVcvarsall(vsversion)}" ${args.join(' ')}` core.debug(`vcvars command-line: ${vcvars}`) const cmd_output_string = child_process.execSync(`set && cls && ${vcvars} && cls && set`, {shell: "cmd"}).toString() @@ -184,8 +230,9 @@ function main() { const toolset = core.getInput('toolset') const uwp = core.getInput('uwp') const spectre = core.getInput('spectre') + const vsversion = core.getInput('vsversion') - setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre) + setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre, vsversion) } try {