Support shell script to set environment variables for a kit

This commit is contained in:
pisker 2020-01-03 19:39:10 +01:00
Родитель 13e97676da
Коммит 6c6cab3b90
2 изменённых файлов: 93 добавлений и 1 удалений

Просмотреть файл

@ -35,6 +35,22 @@
"type": "string", "type": "string",
"description": "Architecture to target" "description": "Architecture to target"
}, },
"environmentVariablesShellScript": {
"type": "string",
"description": "Filename of a shell script which sets environment variables for the kit"
},
"environmentVariablesShellScriptDirectory": {
"type": "string",
"description": "Directory in which to change before running the shell script"
},
"environmentVariablesShellScriptArgs": {
"type": "array",
"description": "Arguments to pass to the shell script",
"items": {
"type": "string",
"description": "Argument to pass to the shell script"
}
},
"environmentVariables": { "environmentVariables": {
"type": "object", "type": "object",
"patternProperties": { "patternProperties": {

Просмотреть файл

@ -95,6 +95,21 @@ export interface Kit {
*/ */
visualStudioArchitecture?: string; visualStudioArchitecture?: string;
/**
* Filename of a shell script which sets environment variables for the kit
*/
environmentVariablesShellScript?: string;
/**
* List of arguments to pass to the shell script
*/
environmentVariablesShellScriptArgs?: string[];
/**
* Directory to switch to before running the shell script
*/
environmentVariablesShellScriptDirectory?: string;
/** /**
* Path to a CMake toolchain file. * Path to a CMake toolchain file.
*/ */
@ -580,6 +595,60 @@ async function collectDevBatVars(devbat: string, args: string[], major_version:
return vars; return vars;
} }
/**
* Gets the environment variables set by a shell script.
* @param kit The kit to get the environment variables for
*/
export async function getShellScriptEnvironment(kit: Kit): Promise<Map<string, string>|undefined> {
console.assert(kit.environmentVariablesShellScript);
const fname = Math.random().toString() + '.bat';
const batfname = `vs-cmt-${fname}`;
const envfname = batfname + '.env';
const batpath = path.join(paths.tmpDir, batfname); // path of batch file
const envpath = path.join(paths.tmpDir, envfname); // path of temp file in which the batch file writes the env vars to
const args = kit.environmentVariablesShellScriptArgs ? kit.environmentVariablesShellScriptArgs.map(arg => `"${arg}"`).join(" ") : "";
const bat = [`@echo off`];
if (kit.environmentVariablesShellScriptDirectory)
bat.push(`cd /d "${kit.environmentVariablesShellScriptDirectory}"`); // switch to directory if set
bat.push(`call "${kit.environmentVariablesShellScript}" ${args} || exit`); // call the shell script
bat.push(`set >> ${envpath}`); // write env vars to temp file
try {
await fs.unlink(envpath); // delete the temp file if it exists
} catch (error) {}
await fs.writeFile(batpath, bat.join('\r\n')); // write batch file
const res = await proc.execute(batpath, [], null, {shell: true, silent: true}).result; // run batch file
await fs.unlink(batpath); // delete batch file
const output = (res.stdout) ? res.stdout + (res.stderr || '') : res.stderr;
let env = '';
try {
/* When the bat running failed, envpath would not exist */
env = await fs.readFile(envpath, {encoding: 'utf8'});
await fs.unlink(envpath);
} catch (error) { log.error(error); }
if (!env || env === '') {
console.error(`Error running ${kit.environmentVariablesShellScript} with:`, output);
return;
}
// split and trim env vars
const vars
= env.split('\n').map(l => l.trim()).filter(l => l.length !== 0).reduce<Map<string, string>>((acc, line) => {
const mat = /(\w+)=?(.*)/.exec(line);
if (mat) {
acc.set(mat[1], mat[2]);
} else {
log.error(localize('error.parsing.environment', 'Error parsing environment variable: {0}', line));
}
return acc;
}, new Map());
log.debug(localize('ok.running', 'OK running {0}, env vars: {1}', kit.environmentVariablesShellScript, JSON.stringify([...vars])));
return vars;
}
/** /**
* Platform arguments for VS Generators * Platform arguments for VS Generators
*/ */
@ -755,7 +824,7 @@ export async function getVSKitEnvironment(kit: Kit): Promise<Map<string, string>
} }
export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionOptions): Promise<Map<string, string>> { export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionOptions): Promise<Map<string, string>> {
const host_env = objectPairs(process.env) as [string, string][]; var host_env = objectPairs(process.env) as [string, string][];
const kit_env = objectPairs(kit.environmentVariables || {}); const kit_env = objectPairs(kit.environmentVariables || {});
if (opts) { if (opts) {
for (const env_var of kit_env) { for (const env_var of kit_env) {
@ -769,6 +838,13 @@ export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionO
util.map(util.chain(host_env, kit_env, vs_vars), ([k, v]): [string, string] => [k.toLocaleUpperCase(), v])); util.map(util.chain(host_env, kit_env, vs_vars), ([k, v]): [string, string] => [k.toLocaleUpperCase(), v]));
} }
} }
if (kit.environmentVariablesShellScript) {
const shell_vars = await getShellScriptEnvironment(kit);
if (shell_vars) {
// replace hostvars with variables set by shell script
host_env = util.map(shell_vars, ([k, v]): [string, string] => [k.toLocaleUpperCase(), v]) as [string, string][];
}
}
const env = new Map(util.chain(host_env, kit_env)); const env = new Map(util.chain(host_env, kit_env));
if (env.has("CMT_MINGW_PATH")) { if (env.has("CMT_MINGW_PATH")) {
if (env.has("PATH")) { if (env.has("PATH")) {