diff --git a/src/expand.ts b/src/expand.ts index cc73f06215..eed78766ac 100644 --- a/src/expand.ts +++ b/src/expand.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import {createLogger} from './logging'; import {EnvironmentVariables} from './proc'; -import {mergeEnvironment, normalizeEnvironmentVarname, replaceAll, fixPaths, errorToString} from './util'; +import {mergeEnvironment, replaceAll, fixPaths, errorToString, envGetValue} from './util'; import * as nls from 'vscode-nls'; nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); @@ -149,7 +149,7 @@ export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { while ((mat = env_re.exec(tmpl))) { const full = mat[0]; const varname = mat[1]; - const repl = fixPaths(env[normalizeEnvironmentVarname(varname)]) || ''; + const repl = fixPaths(envGetValue(env, varname) ?? ''); subs.set(full, repl); } @@ -157,7 +157,7 @@ export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { while ((mat = env_re2.exec(tmpl))) { const full = mat[0]; const varname = mat[1]; - const repl = fixPaths(env[normalizeEnvironmentVarname(varname)]) || ''; + const repl = fixPaths(envGetValue(env, varname) ?? ''); subs.set(full, repl); } @@ -165,7 +165,7 @@ export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { while ((mat = env_re3.exec(tmpl))) { const full = mat[0]; const varname = mat[1]; - const repl = fixPaths(env[normalizeEnvironmentVarname(varname)]) || ''; + const repl = fixPaths(envGetValue(env, varname) ?? ''); subs.set(full, repl); } @@ -173,7 +173,7 @@ export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { while ((mat = penv_re.exec(tmpl))) { const full = mat[0]; const varname = mat[1]; - const repl = fixPaths(process.env[normalizeEnvironmentVarname(varname)] || '') || ''; + const repl = fixPaths(envGetValue(process.env, varname) ?? ''); subs.set(full, repl); } @@ -181,7 +181,7 @@ export async function expandStringHelper(tmpl: string, opts: ExpansionOptions) { while ((mat = vendor_re.exec(tmpl))) { const full = mat[0]; const varname = mat[1]; - const repl = fixPaths(process.env[normalizeEnvironmentVarname(varname)] || '') || ''; + const repl = fixPaths(envGetValue(process.env, varname) ?? ''); subs.set(full, repl); } diff --git a/src/kit.ts b/src/kit.ts index a08e518c8a..542125ddb6 100644 --- a/src/kit.ts +++ b/src/kit.ts @@ -1028,7 +1028,7 @@ export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionO if (kit.environmentSetupScript) { const shell_vars = await getShellScriptEnvironment(kit, opts); if (shell_vars) { - host_env = util.map(shell_vars, ([k, v]): [string, string] => [k.toLocaleUpperCase(), v]) as [string, string][]; + host_env = util.map(shell_vars, ([k, v]): [string, string] => [k, v]) as [string, string][]; } } if (host_env === undefined) { @@ -1039,7 +1039,7 @@ export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionO const vs_vars = await getVSKitEnvironment(kit); if (vs_vars) { return new Map( - 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, v])); } } const env = new Map(util.chain(host_env, kit_env)); @@ -1052,30 +1052,25 @@ export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionO if (cCompiler) { path_list.push(path.dirname(cCompiler)); } - const cmt_mingw_path = env.get("CMT_MINGW_PATH"); + const cmt_mingw_path = util.envGetValue(env, "CMT_MINGW_PATH"); if (cmt_mingw_path) { path_list.push(cmt_mingw_path); } - let path_key : string | undefined = undefined; - if (env.has("PATH")) { - path_key = "PATH"; - } else if (env.has("Path")) { - path_key = "Path"; - } - if (path_key) { - path_list.unshift(env.get(path_key) ?? ''); - env.set(path_key, path_list.join(';')); + const env_path = util.envGetValue(env, 'PATH'); + if (env_path) { + path_list.unshift(env_path); } + util.envSet(env, 'PATH', path_list.join(';')); } return env; } export async function findCLCompilerPath(env: Map): Promise { - const path_var = util.find(env.entries(), ([key, _val]) => key.toLocaleLowerCase() === 'path'); + const path_var = util.envGet(env, 'PATH'); if (!path_var) { return null; } - const path_ext_var = util.find(env.entries(), ([key, _val]) => key.toLocaleLowerCase() === 'pathext'); + const path_ext_var = util.envGet(env, 'PATHEXT'); if (!path_ext_var) { return null; } @@ -1120,9 +1115,10 @@ export async function scanForKits(cmakeTools: CMakeTools | undefined, opt?: KitS const scan_paths = new Set(); // Search directories on `PATH` for compiler binaries - if (process.env.hasOwnProperty('PATH')) { + const env_path = util.envGetValue(process.env, 'PATH'); + if (env_path) { const sep = isWin32 ? ';' : ':'; - for (const dir of (process.env.PATH as string).split(sep)) { + for (const dir of env_path.split(sep)) { scan_paths.add(dir); } } @@ -1146,8 +1142,9 @@ export async function scanForKits(cmakeTools: CMakeTools | undefined, opt?: KitS const clang_paths = new Set(); // LLVM_ROOT environment variable location - if (process.env.hasOwnProperty('LLVM_ROOT')) { - const llvm_root = path.normalize(process.env.LLVM_ROOT as string + "\\bin"); + const env_llvm_root = util.envGetValue(process.env, 'LLVM_ROOT'); + if (env_llvm_root) { + const llvm_root = path.normalize(env_llvm_root + "\\bin"); clang_paths.add(llvm_root); } @@ -1187,8 +1184,9 @@ export async function scanForKitsIfNeeded(cmt: CMakeTools) : Promise { const kitsVersionCurrent = 2; // Scan also when there is no kits version saved in the state. + const env_cmt_testing = util.envGetValue(process.env, 'CMT_TESTING'); if ((!kitsVersionSaved || kitsVersionSaved !== kitsVersionCurrent) && - process.env['CMT_TESTING'] !== '1' && !kitsController.KitsController.isScanningForKits()) { + env_cmt_testing !== '1' && !kitsController.KitsController.isScanningForKits()) { log.info(localize('silent.kits.rescan', 'Detected kits definition version change from {0} to {1}. Silently scanning for kits.', kitsVersionSaved, kitsVersionCurrent)); await kitsController.KitsController.scanForKits(cmt); cmt.extensionContext.globalState.update('kitsVersionSaved', kitsVersionCurrent); diff --git a/src/util.ts b/src/util.ts index e30efdd0a5..010bf2d665 100644 --- a/src/util.ts +++ b/src/util.ts @@ -212,6 +212,85 @@ export function find(iter: Iterable, predicate: (value: T) => boolean): T| return undefined; } +function envKeyEqual(key1: string, key2: string): boolean { + if (process.platform == "win32") { + // On win32, environment variable key are case insensitive + return key1.toLocaleLowerCase() === key2.toLocaleLowerCase(); + } else { + return key1 === key2; + } +} + +/** + * Get an environment variable item from the environment map + * @param env The environment map to retrieve key + * @param expectKey The environment key + * @return [key, value] pair of the find environment or undefined when not found + */ +export function envGet( + env: Map | NodeJS.ProcessEnv, + expectKey: string +): [string, string] | undefined { + if (env instanceof Map) { + return find(env.entries(), ([key, _val]) => envKeyEqual(key, expectKey)); + } else { + for (const key of Object.keys(env)) { + if (envKeyEqual(key, expectKey)) { + return [key, env[key] as string]; + } + } + } + return undefined; +} + +/** + * Get an environment variable item from the environment map + * @param env The environment map to retrieve key + * @param expectKey The environment key + * @return The environment value for the expectKey + */ +export function envGetValue( + env: Map | NodeJS.ProcessEnv, + expectKey: string +): string | undefined { + const envItem = envGet(env, expectKey); + if (envItem) { + return expectKey[1]; + } + return undefined; +} + +function envUpdate( + env: Map | NodeJS.ProcessEnv, + insertKey: string, + insertValue: string +) { + if (env instanceof Map) { + env.set(insertKey, insertValue); + } else { + env[insertKey] = insertValue; + } +} + +/** + * Set an environment variable item + * @param env The environment map to update + * @param insertKey The environment key + * @param insertValue The environment value + */ +export function envSet( + env: Map | NodeJS.ProcessEnv, + insertKey: string, + insertValue: string +) { + const existItem = envGet(env, insertKey); + if (existItem) { + envUpdate(env, existItem[0], insertValue); + } else { + envUpdate(env, insertKey, insertValue); + } +} + /** * Generate a random integral value. * @param min Minimum value @@ -363,24 +442,13 @@ export function* flatMap(rng: Iterable, fn: (item: In) => Iterable< export function mergeEnvironment(...env: EnvironmentVariables[]): EnvironmentVariables { return env.reduce((acc, vars) => { - if (process.platform === 'win32') { - // Env vars on windows are case insensitive, so we take the ones from - // active env and overwrite the ones in our current process env - const norm_vars = Object.getOwnPropertyNames(vars).reduce((acc2, key: string) => { - acc2[normalizeEnvironmentVarname(key)] = vars[key]; - return acc2; - }, {}); - return {...acc, ...norm_vars}; - } else { - return {...acc, ...vars}; + for (const newEnvItem of Object.entries(vars)) { + envSet(acc, newEnvItem[0], newEnvItem[1]); } + return acc; }, {}); } -export function normalizeEnvironmentVarname(varname: string) { - return process.platform == 'win32' ? varname.toUpperCase() : varname; -} - export function parseCompileDefinition(str: string): [string, string|null] { if (/^\w+$/.test(str)) { return [str, null];