Files
msvc-dev-cmd/index.js
T
Alexei Lozovsky 87f7e3e8ba Async cleanup and improved logging (#21)
* Avoid unnecessary async-await

Since this is basically a linear script, we don't *really* need all this
async fluff, despite Node.js having a predisposition for async calls.
For one, it does not make much sense to immediately await an async call.
There is a synchronous version of exec -- execSync -- for that.

Suggested-by: Amin Yahyaabadi <aminyahyaabadi74@gmail.com>

* Make logging more verbose

Provide more insight in what paths are tried and where we have found
Visual Studio. Use info level so that it's visible without Actions
debugging being enabled. That way the users get to see a bit more
of the decision making process.
2020-12-13 08:03:03 +02:00

126 lines
3.8 KiB
JavaScript

const core = require('@actions/core')
const child_process = require('child_process')
const fs = require('fs')
const path = require('path')
const process = require('process')
const PROGRAM_FILES_X86 = process.env['ProgramFiles(x86)']
const EDITIONS = ['Enterprise', 'Professional', 'Community']
const VERSIONS = ['2019', '2017']
const VSWHERE_PATH = `${PROGRAM_FILES_X86}\\Microsoft Visual Studio\\Installer`
const InterestingVariables = [
'INCLUDE',
'LIB',
'LIBPATH',
'VCINSTALLDIR',
'Path',
'Platform',
'VisualStudioVersion',
/^VCTools/,
/^VSCMD_/,
/^WindowsSDK/i,
]
function findWithVswhere(pattern) {
try {
let installationPath = child_process.execSync(`vswhere -products * -latest -prerelease -property installationPath`).toString().trim()
return installationPath + '\\' + pattern
} catch (e) {
core.warning(`vswhere failed: ${e}`)
}
return null
}
function findVcvarsall() {
// If vswhere is available, ask it about the location of the latest Visual Studio.
let path = findWithVswhere('VC\\Auxiliary\\Build\\vcvarsall.bat')
if (path && fs.existsSync(path)) {
core.info(`Found with vswhere: ${path}`)
return path
}
core.info("Not found with vswhere")
// If that does not work, try the standard installation locations,
// starting with the latest and moving to the oldest.
for (const ver of VERSIONS) {
for (const ed of EDITIONS) {
path = `${PROGRAM_FILES_X86}\\Microsoft Visual Studio\\${ver}\\${ed}\\VC\\Auxiliary\\Build\\vcvarsall.bat`
core.info(`Trying standard location: ${path}`)
if (fs.existsSync(path)) {
core.info(`Found standard location: ${path}`)
return path
}
}
}
core.info("Not found in standard locations")
// Special case for Visual Studio 2015 (and maybe earlier), try it out too.
path = `${PROGRAM_FILES_X86}\\Microsoft Visual C++ Build Tools\\vcbuildtools.bat`
if (fs.existsSync(path)) {
core.info(`Found VS 2015: ${path}`)
return path
}
core.info(`Not found in VS 2015 location: ${path}`)
throw new Error('Microsoft Visual Studio not found')
}
function main() {
if (process.platform != 'win32') {
core.info('This is not a Windows virtual environment, bye!')
return
}
// Add standard location of "vswhere" to PATH, in case it's not there.
process.env.PATH += path.delimiter + VSWHERE_PATH
const arch = core.getInput('arch')
const sdk = core.getInput('sdk')
const toolset = core.getInput('toolset')
const uwp = core.getInput('uwp')
const spectre = core.getInput('spectre')
// Due to the way Microsoft Visual C++ is configured, we have to resort to the following hack:
// Call the configuration batch file and then output *all* the environment variables.
var args = [arch]
if (uwp == 'true') {
args.push('uwp')
}
if (sdk) {
args.push(sdk)
}
if (toolset) {
args.push(`-vcvars_ver=${toolset}`)
}
if (spectre == 'true') {
args.push('-vcvars_spectre_libs=spectre')
}
const command = `"${findVcvarsall()}" ${args.join(' ')} && set`
core.debug(`Running: ${command}`)
const environment = child_process.execSync(command, {shell: "cmd"}).toString().split('\r\n')
for (let string of environment) {
const [name, value] = string.split('=')
for (let pattern of InterestingVariables) {
if (name.match(pattern)) {
core.exportVariable(name, value)
break
}
}
}
core.info(`Configured Developer Command Prompt`)
}
try {
main()
}
catch (e) {
core.setFailed('Could not setup Developer Command Prompt: ' + e.message)
}