Skip to content

Commit c32fdcf

Browse files
authored
Add a lib.js to export functions without running main (#70)
1 parent 6357fb6 commit c32fdcf

File tree

2 files changed

+226
-224
lines changed

2 files changed

+226
-224
lines changed

index.js

Lines changed: 1 addition & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -1,228 +1,5 @@
1+
const { setupMSVCDevCmd } = require('./lib')
12
const core = require('@actions/core')
2-
const child_process = require('child_process')
3-
const fs = require('fs')
4-
const path = require('path')
5-
const process = require('process')
6-
7-
const PROGRAM_FILES_X86 = process.env['ProgramFiles(x86)']
8-
const PROGRAM_FILES = [process.env['ProgramFiles(x86)'], process.env['ProgramFiles']]
9-
10-
11-
const EDITIONS = ['Enterprise', 'Professional', 'Community', 'BuildTools']
12-
const YEARS = ['2022', '2019', '2017']
13-
14-
const VsYearVersion = {
15-
'2022': '17.0',
16-
'2019': '16.0',
17-
'2017': '15.0',
18-
'2015': '14.0',
19-
'2013': '12.0',
20-
}
21-
22-
function vsversion_to_versionnumber(vsversion) {
23-
if (Object.values(VsYearVersion).includes(vsversion)) {
24-
return vsversion
25-
} else {
26-
if (vsversion in VsYearVersion) {
27-
return VsYearVersion[vsversion]
28-
}
29-
}
30-
return vsversion
31-
}
32-
exports.vsversion_to_versionnumber = vsversion_to_versionnumber
33-
34-
function vsversion_to_year(vsversion) {
35-
if (Object.keys(VsYearVersion).includes(vsversion)) {
36-
return vsversion
37-
} else {
38-
for (const [year, ver] of Object.entries(VsYearVersion)) {
39-
if (ver === vsversion) {
40-
return year
41-
}
42-
}
43-
}
44-
return vsversion
45-
}
46-
exports.vsversion_to_year = vsversion_to_year
47-
48-
const VSWHERE_PATH = `${PROGRAM_FILES_X86}\\Microsoft Visual Studio\\Installer`
49-
50-
function findWithVswhere(pattern, version_pattern) {
51-
try {
52-
let installationPath = child_process.execSync(`vswhere -products * ${version_pattern} -prerelease -property installationPath`).toString().trim()
53-
return installationPath + '\\' + pattern
54-
} catch (e) {
55-
core.warning(`vswhere failed: ${e}`)
56-
}
57-
return null
58-
}
59-
exports.findWithVswhere = findWithVswhere
60-
61-
function findVcvarsall(vsversion) {
62-
const vsversion_number = vsversion_to_versionnumber(vsversion)
63-
let version_pattern
64-
if (vsversion_number) {
65-
const upper_bound = vsversion_number.split('.')[0] + '.9'
66-
version_pattern = `-version "${vsversion_number},${upper_bound}"`
67-
} else {
68-
version_pattern = "-latest"
69-
}
70-
71-
// If vswhere is available, ask it about the location of the latest Visual Studio.
72-
let path = findWithVswhere('VC\\Auxiliary\\Build\\vcvarsall.bat', version_pattern)
73-
if (path && fs.existsSync(path)) {
74-
core.info(`Found with vswhere: ${path}`)
75-
return path
76-
}
77-
core.info("Not found with vswhere")
78-
79-
// If that does not work, try the standard installation locations,
80-
// starting with the latest and moving to the oldest.
81-
const years = vsversion ? [vsversion_to_year(vsversion)] : YEARS
82-
for (const prog_files of PROGRAM_FILES) {
83-
for (const ver of years) {
84-
for (const ed of EDITIONS) {
85-
path = `${prog_files}\\Microsoft Visual Studio\\${ver}\\${ed}\\VC\\Auxiliary\\Build\\vcvarsall.bat`
86-
core.info(`Trying standard location: ${path}`)
87-
if (fs.existsSync(path)) {
88-
core.info(`Found standard location: ${path}`)
89-
return path
90-
}
91-
}
92-
}
93-
}
94-
core.info("Not found in standard locations")
95-
96-
// Special case for Visual Studio 2015 (and maybe earlier), try it out too.
97-
path = `${PROGRAM_FILES_X86}\\Microsoft Visual C++ Build Tools\\vcbuildtools.bat`
98-
if (fs.existsSync(path)) {
99-
core.info(`Found VS 2015: ${path}`)
100-
return path
101-
}
102-
core.info(`Not found in VS 2015 location: ${path}`)
103-
104-
throw new Error('Microsoft Visual Studio not found')
105-
}
106-
exports.findVcvarsall = findVcvarsall
107-
108-
function isPathVariable(name) {
109-
const pathLikeVariables = ['PATH', 'INCLUDE', 'LIB', 'LIBPATH']
110-
return pathLikeVariables.indexOf(name.toUpperCase()) != -1
111-
}
112-
113-
function filterPathValue(path) {
114-
let paths = path.split(';')
115-
// Remove duplicates by keeping the first occurance and preserving order.
116-
// This keeps path shadowing working as intended.
117-
function unique(value, index, self) {
118-
return self.indexOf(value) === index
119-
}
120-
return paths.filter(unique).join(';')
121-
}
122-
123-
/** See https://github.com/ilammy/msvc-dev-cmd#inputs */
124-
function setupMSVCDevCmd(arch, sdk, toolset, uwp, spectre, vsversion) {
125-
if (process.platform != 'win32') {
126-
core.info('This is not a Windows virtual environment, bye!')
127-
return
128-
}
129-
130-
// Add standard location of "vswhere" to PATH, in case it's not there.
131-
process.env.PATH += path.delimiter + VSWHERE_PATH
132-
133-
// There are all sorts of way the architectures are called. In addition to
134-
// values supported by Microsoft Visual C++, recognize some common aliases.
135-
let arch_aliases = {
136-
"win32": "x86",
137-
"win64": "x64",
138-
"x86_64": "x64",
139-
"x86-64": "x64",
140-
}
141-
// Ignore case when matching as that's what humans expect.
142-
if (arch.toLowerCase() in arch_aliases) {
143-
arch = arch_aliases[arch.toLowerCase()]
144-
}
145-
146-
// Due to the way Microsoft Visual C++ is configured, we have to resort to the following hack:
147-
// Call the configuration batch file and then output *all* the environment variables.
148-
149-
var args = [arch]
150-
if (uwp == 'true') {
151-
args.push('uwp')
152-
}
153-
if (sdk) {
154-
args.push(sdk)
155-
}
156-
if (toolset) {
157-
args.push(`-vcvars_ver=${toolset}`)
158-
}
159-
if (spectre == 'true') {
160-
args.push('-vcvars_spectre_libs=spectre')
161-
}
162-
163-
const vcvars = `"${findVcvarsall(vsversion)}" ${args.join(' ')}`
164-
core.debug(`vcvars command-line: ${vcvars}`)
165-
166-
const cmd_output_string = child_process.execSync(`set && cls && ${vcvars} && cls && set`, {shell: "cmd"}).toString()
167-
const cmd_output_parts = cmd_output_string.split('\f')
168-
169-
const old_environment = cmd_output_parts[0].split('\r\n')
170-
const vcvars_output = cmd_output_parts[1].split('\r\n')
171-
const new_environment = cmd_output_parts[2].split('\r\n')
172-
173-
// If vsvars.bat is given an incorrect command line, it will print out
174-
// an error and *still* exit successfully. Parse out errors from output
175-
// which don't look like environment variables, and fail if appropriate.
176-
const error_messages = vcvars_output.filter((line) => {
177-
if (line.match(/^\[ERROR.*\]/)) {
178-
// Don't print this particular line which will be confusing in output.
179-
if (!line.match(/Error in script usage. The correct usage is:$/)) {
180-
return true
181-
}
182-
}
183-
return false
184-
})
185-
if (error_messages.length > 0) {
186-
throw new Error('invalid parameters' + '\r\n' + error_messages.join('\r\n'))
187-
}
188-
189-
// Convert old environment lines into a dictionary for easier lookup.
190-
let old_env_vars = {}
191-
for (let string of old_environment) {
192-
const [name, value] = string.split('=')
193-
old_env_vars[name] = value
194-
}
195-
196-
// Now look at the new environment and export everything that changed.
197-
// These are the variables set by vsvars.bat. Also export everything
198-
// that was not there during the first sweep: those are new variables.
199-
core.startGroup('Environment variables')
200-
for (let string of new_environment) {
201-
// vsvars.bat likes to print some fluff at the beginning.
202-
// Skip lines that don't look like environment variables.
203-
if (!string.includes('=')) {
204-
continue;
205-
}
206-
let [name, new_value] = string.split('=')
207-
let old_value = old_env_vars[name]
208-
// For new variables "old_value === undefined".
209-
if (new_value !== old_value) {
210-
core.info(`Setting ${name}`)
211-
// Special case for a bunch of PATH-like variables: vcvarsall.bat
212-
// just prepends its stuff without checking if its already there.
213-
// This makes repeated invocations of this action fail after some
214-
// point, when the environment variable overflows. Avoid that.
215-
if (isPathVariable(name)) {
216-
new_value = filterPathValue(new_value)
217-
}
218-
core.exportVariable(name, new_value)
219-
}
220-
}
221-
core.endGroup()
222-
223-
core.info(`Configured Developer Command Prompt`)
224-
}
225-
exports.setupMSVCDevCmd = setupMSVCDevCmd
2263

2274
function main() {
2285
var arch = core.getInput('arch')

0 commit comments

Comments
 (0)