Skip to content
Merged
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ Inputs
------

- `vswhere`: Path to `vswhere.exe` (default system-installed copy).
- `arch`: Build architecture (default `amd64`).
- `host_arch`: Host architecture override.
- `host_arch`: Host architecture override (defaults to the processor architecture).
- `arch`: Build architecture (defaults to the value of host_arch).
- `winsdk`: WinSDK version override.
- `toolset_version`: Build toolset version override.
- `components`: List of required VS components, semi-colon separated. (default `Microsoft.VisualStudio.Component.VC.Tools.x86.x64`)
- `components`: List of required VS components, semi-colon separated. (includes the latest toolset for `arch` by default)
- `verbose`: Display information about the installation that `vswhere` selects.

Outputs
Expand Down
8 changes: 4 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ inputs:
description: 'Name or path to vswhere.exr'
default: 'vswhere.exe'
arch:
description: 'Target build architecture'
default: 'amd64'
description: "Determines the 'arch' argument to vcvarsall (x86, amd64/x64, arm, arm64, or arm64ec). Defaults to the value of host_arch."
default: ''
host_arch:
description: 'Host architecture (x86, x86_amd64, or amd64)'
description: "Determines the 'host_arch' parameter to vcvarsall (x86, amd64/x64, or arm64). Defaults to the current processor architecture."
default: ''
winsdk:
description: 'Overrides the default WinSDK version'
Expand All @@ -21,7 +21,7 @@ inputs:
default: ''
components:
description: 'List of components required in the selected VS installation (semi-colon separated)'
default: 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
default: ''
verbose:
description: 'Display additional information about the VS Installation'
default: false
Expand Down
125 changes: 87 additions & 38 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2836,28 +2836,51 @@ const index_process = __nccwpck_require__(932)
const path = __nccwpck_require__(928)
const spawn = (__nccwpck_require__(317).spawnSync)

try {
// this job has nothing to do on non-Windows platforms
if (index_process.platform != 'win32') {
index_process.exit(0)
/// Gets the inputs to this action, with default values filled in.
function getInputs() {
// Default to the native processor as the host architecture
// vsdevcmd accepts both amd64 and x64
const hostArch = core.getInput('host_arch') || index_process.env['PROCESSOR_ARCHITECTURE'].toLowerCase() // amd64, x86 or arm64
const arch = core.getInput('arch') || hostArch
const toolsetVersion = core.getInput('toolset_version') || null

const components = core.getInput('components').split(';').filter(s => s.length != 0)
if (!toolsetVersion) {
// Include the latest target architecture compiler toolset by default
if (arch === 'arm64')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM64')
else if (arch === 'arm64ec')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM64EC')
else if (arch == 'arm')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM')
else
components.push('Microsoft.VisualStudio.Component.VC.Tools.x86.x64')
}

const arch = core.getInput('arch') || 'amd64'
const hostArch = core.getInput('host_arch') || ''
const toolsetVersion = core.getInput('toolset_version') || ''
const winsdk = core.getInput('winsdk') || ''
const vswhere = core.getInput('vswhere') || 'vswhere.exe'
const components = core.getInput('components') || 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
const verbose = core.getInput('verbose') || false
return {
"host_arch": hostArch,
"arch": arch,
"toolset_version": toolsetVersion,
"winsdk": core.getInput('winsdk') || null,
"vswhere": core.getInput('vswhere') || null,
"components": components,
// Action inputs are stringly-typed, and Boolean("false") === true, so prefer:
"verbose": String(core.getInput('verbose')) === "true"
}
}

function findVSWhere(inputs) {
const vswhere = inputs.vswhere || 'vswhere.exe'
const vsInstallerPath = path.win32.join(index_process.env['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer')
const vswherePath = path.win32.resolve(vsInstallerPath, vswhere)

console.log(`vswhere: ${vswherePath}`)
return vswherePath
}

function findVSInstallDir(inputs) {
const vswherePath = findVSWhere(inputs)

const requiresArg = components
.split(';')
.filter(s => s.length != 0)
const requiresArg = inputs.components
.map(comp => ['-requires', comp])
.reduce((arr, pair) => arr.concat(pair), [])

Expand All @@ -2870,43 +2893,69 @@ try {

console.log(`$ ${vswherePath} ${vswhereArgs.join(' ')}`)

const vswhereResult = spawn(vswherePath, vswhereArgs, {encoding: 'utf8'})
const vswhereResult = spawn(vswherePath, vswhereArgs, { encoding: 'utf8' })
if (vswhereResult.error) throw vswhereResult.error

if (verbose) {
const args = [
'-nologo',
'-latest',
'-products', '*',
].concat(requiresArg)
const details = spawn(vswherePath, args, { encoding: 'utf8' })
console.log(details.output.join(''))
if (inputs.verbose) {
const args = [
'-nologo',
'-latest',
'-products', '*',
].concat(requiresArg)
const details = spawn(vswherePath, args, { encoding: 'utf8' })
console.log(details.output.join(''))
}

const installPathList = vswhereResult.output.filter(s => !!s).map(s => s.trim())
if (installPathList.length == 0) throw new Error('Could not find compatible VS installation')

const installPath = installPathList[installPathList.length - 1]
console.log(`install: ${installPath}`)
return installPath
}

function getVSDevCmdArgs(inputs) {
// Default to the native processor as the host architecture
// vsdevcmd accepts both amd64 and x64
const hostArch = inputs.host_arch || index_process.env['PROCESSOR_ARCHITECTURE'].toLowerCase() // amd64, x86 or arm64

// Default to the host architecture as the target architecture
const arch = inputs.arch || hostArch

const args = [
`-host_arch=${hostArch}`,
`-arch=${arch}`
]

if (inputs.toolsetVersion)
vsDevCmdArgs.push(`-vcvars_ver=${toolsetVersion}`)
if (inputs.winsdk)
args.push(`-winsdk=${winsdk}`)

return args
}

try {
// this job has nothing to do on non-Windows platforms
if (index_process.platform != 'win32') {
index_process.exit(0)
}

var inputs = getInputs()

const installPath = findVSInstallDir(inputs)
core.setOutput('install_path', installPath)

const vsDevCmdPath = path.win32.join(installPath, 'Common7', 'Tools', 'vsdevcmd.bat')
console.log(`vsdevcmd: ${vsDevCmdPath}`)

const vsDevCmdArgs = [ vsDevCmdPath, `-arch=${arch}` ]
if (hostArch != '')
vsDevCmdArgs.push(`-host_arch=${hostArch}`)
if (toolsetVersion != '')
vsDevCmdArgs.push(`-vcvars_ver=${toolsetVersion}`)
if (winsdk != '')
vsDevCmdArgs.push(`-winsdk=${winsdk}`)

const cmdArgs = [ '/q', '/k'].concat(vsDevCmdArgs, ['&&', 'set'])

const vsDevCmdArgs = getVSDevCmdArgs(inputs)
const cmdArgs = ['/q', '/k', vsDevCmdPath, ...vsDevCmdArgs, '&&', 'set']
console.log(`$ cmd ${cmdArgs.join(' ')}`)

const cmdResult = spawn('cmd', cmdArgs, {encoding: 'utf8'})
const cmdResult = spawn('cmd', cmdArgs, { encoding: 'utf8' })
if (cmdResult.error) throw cmdResult.error

const cmdOutput = cmdResult.output
.filter(s => !!s)
.map(s => s.split('\n'))
Expand All @@ -2920,9 +2969,9 @@ try {
const newEnvVars = completeEnv
.filter(([key, _]) => !index_process.env[key])
const newPath = completeEnv
.filter(([key, _]) => key == 'Path')
.map(([_, value]) => value)
.join(';');
.filter(([key, _]) => key == 'Path')
.map(([_, value]) => value)
.join(';');

for (const [key, value] of newEnvVars) {
core.exportVariable(key, value)
Expand Down
125 changes: 87 additions & 38 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,51 @@ const process = require('process')
const path = require('path')
const spawn = require('child_process').spawnSync

try {
// this job has nothing to do on non-Windows platforms
if (process.platform != 'win32') {
process.exit(0)
/// Gets the inputs to this action, with default values filled in.
function getInputs() {
// Default to the native processor as the host architecture
// vsdevcmd accepts both amd64 and x64
const hostArch = core.getInput('host_arch') || process.env['PROCESSOR_ARCHITECTURE'].toLowerCase() // amd64, x86 or arm64
const arch = core.getInput('arch') || hostArch
const toolsetVersion = core.getInput('toolset_version') || null

const components = core.getInput('components').split(';').filter(s => s.length != 0)
if (!toolsetVersion) {
// Include the latest target architecture compiler toolset by default
if (arch === 'arm64')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM64')
else if (arch === 'arm64ec')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM64EC')
else if (arch == 'arm')
components.push('Microsoft.VisualStudio.Component.VC.Tools.ARM')
else
components.push('Microsoft.VisualStudio.Component.VC.Tools.x86.x64')
}

const arch = core.getInput('arch') || 'amd64'
const hostArch = core.getInput('host_arch') || ''
const toolsetVersion = core.getInput('toolset_version') || ''
const winsdk = core.getInput('winsdk') || ''
const vswhere = core.getInput('vswhere') || 'vswhere.exe'
const components = core.getInput('components') || 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64'
const verbose = core.getInput('verbose') || false
return {
"host_arch": hostArch,
"arch": arch,
"toolset_version": toolsetVersion,
"winsdk": core.getInput('winsdk') || null,
"vswhere": core.getInput('vswhere') || null,
"components": components,
// Action inputs are stringly-typed, and Boolean("false") === true, so prefer:
"verbose": String(core.getInput('verbose')) === "true"
}
}

function findVSWhere(inputs) {
const vswhere = inputs.vswhere || 'vswhere.exe'
const vsInstallerPath = path.win32.join(process.env['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer')
const vswherePath = path.win32.resolve(vsInstallerPath, vswhere)

console.log(`vswhere: ${vswherePath}`)
return vswherePath
}

const requiresArg = components
.split(';')
.filter(s => s.length != 0)
function findVSInstallDir(inputs) {
const vswherePath = findVSWhere(inputs)

const requiresArg = inputs.components
.map(comp => ['-requires', comp])
.reduce((arr, pair) => arr.concat(pair), [])

Expand All @@ -37,43 +60,69 @@ try {

console.log(`$ ${vswherePath} ${vswhereArgs.join(' ')}`)

const vswhereResult = spawn(vswherePath, vswhereArgs, {encoding: 'utf8'})
const vswhereResult = spawn(vswherePath, vswhereArgs, { encoding: 'utf8' })
if (vswhereResult.error) throw vswhereResult.error

if (verbose) {
const args = [
'-nologo',
'-latest',
'-products', '*',
].concat(requiresArg)
const details = spawn(vswherePath, args, { encoding: 'utf8' })
console.log(details.output.join(''))
if (inputs.verbose) {
const args = [
'-nologo',
'-latest',
'-products', '*',
].concat(requiresArg)
const details = spawn(vswherePath, args, { encoding: 'utf8' })
console.log(details.output.join(''))
}

const installPathList = vswhereResult.output.filter(s => !!s).map(s => s.trim())
if (installPathList.length == 0) throw new Error('Could not find compatible VS installation')

const installPath = installPathList[installPathList.length - 1]
console.log(`install: ${installPath}`)
return installPath
}

function getVSDevCmdArgs(inputs) {
// Default to the native processor as the host architecture
// vsdevcmd accepts both amd64 and x64
const hostArch = inputs.host_arch || process.env['PROCESSOR_ARCHITECTURE'].toLowerCase() // amd64, x86 or arm64

// Default to the host architecture as the target architecture
const arch = inputs.arch || hostArch

const args = [
`-host_arch=${hostArch}`,
`-arch=${arch}`
]

if (inputs.toolsetVersion)
vsDevCmdArgs.push(`-vcvars_ver=${toolsetVersion}`)
if (inputs.winsdk)
args.push(`-winsdk=${winsdk}`)

return args
}

try {
// this job has nothing to do on non-Windows platforms
if (process.platform != 'win32') {
process.exit(0)
}

var inputs = getInputs()

const installPath = findVSInstallDir(inputs)
core.setOutput('install_path', installPath)

const vsDevCmdPath = path.win32.join(installPath, 'Common7', 'Tools', 'vsdevcmd.bat')
console.log(`vsdevcmd: ${vsDevCmdPath}`)

const vsDevCmdArgs = [ vsDevCmdPath, `-arch=${arch}` ]
if (hostArch != '')
vsDevCmdArgs.push(`-host_arch=${hostArch}`)
if (toolsetVersion != '')
vsDevCmdArgs.push(`-vcvars_ver=${toolsetVersion}`)
if (winsdk != '')
vsDevCmdArgs.push(`-winsdk=${winsdk}`)

const cmdArgs = [ '/q', '/k'].concat(vsDevCmdArgs, ['&&', 'set'])

const vsDevCmdArgs = getVSDevCmdArgs(inputs)
const cmdArgs = ['/q', '/k', vsDevCmdPath, ...vsDevCmdArgs, '&&', 'set']
console.log(`$ cmd ${cmdArgs.join(' ')}`)

const cmdResult = spawn('cmd', cmdArgs, {encoding: 'utf8'})
const cmdResult = spawn('cmd', cmdArgs, { encoding: 'utf8' })
if (cmdResult.error) throw cmdResult.error

const cmdOutput = cmdResult.output
.filter(s => !!s)
.map(s => s.split('\n'))
Expand All @@ -87,9 +136,9 @@ try {
const newEnvVars = completeEnv
.filter(([key, _]) => !process.env[key])
const newPath = completeEnv
.filter(([key, _]) => key == 'Path')
.map(([_, value]) => value)
.join(';');
.filter(([key, _]) => key == 'Path')
.map(([_, value]) => value)
.join(';');

for (const [key, value] of newEnvVars) {
core.exportVariable(key, value)
Expand Down