Skip to content

Commit

Permalink
Using consistence function for environment set and get to fix the
Browse files Browse the repository at this point in the history
gap between windows and unix.

Fixes

#1592

Signed-off-by: Yonggang Luo <[email protected]>
  • Loading branch information
lygstate committed Apr 13, 2021
1 parent 8f4a36f commit e42c865
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 39 deletions.
12 changes: 6 additions & 6 deletions src/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 })();
Expand Down Expand Up @@ -149,39 +149,39 @@ 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);
}

const env_re2 = RegExp(`\\$\\{env\\.(${varValueRegexp})\\}`, "g");
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);
}

const env_re3 = RegExp(`\\$env\\{(${varValueRegexp})\\}`, "g");
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);
}

const penv_re = RegExp(`\\$penv\\{(${varValueRegexp})\\}`, "g");
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);
}

const vendor_re = RegExp(`\\$vendor\\{(${varValueRegexp})\\}`, "g");
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);
}

Expand Down
36 changes: 17 additions & 19 deletions src/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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));
Expand All @@ -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<string, string>): Promise<string|null> {
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;
}
Expand Down Expand Up @@ -1120,9 +1115,10 @@ export async function scanForKits(cmakeTools: CMakeTools | undefined, opt?: KitS
const scan_paths = new Set<string>();

// 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);
}
}
Expand All @@ -1146,8 +1142,9 @@ export async function scanForKits(cmakeTools: CMakeTools | undefined, opt?: KitS
const clang_paths = new Set<string>();

// 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);
}

Expand Down Expand Up @@ -1187,8 +1184,9 @@ export async function scanForKitsIfNeeded(cmt: CMakeTools) : Promise<boolean> {
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);
Expand Down
96 changes: 82 additions & 14 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,85 @@ export function find<T>(iter: Iterable<T>, 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<string, string> | 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<string, string> | NodeJS.ProcessEnv,
expectKey: string
): string | undefined {
const envItem = envGet(env, expectKey);
if (envItem) {
return expectKey[1];
}
return undefined;
}

function envUpdate(
env: Map<string, string> | 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<string, string> | 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
Expand Down Expand Up @@ -363,24 +442,13 @@ export function* flatMap<In, Out>(rng: Iterable<In>, 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<EnvironmentVariables>((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];
Expand Down

0 comments on commit e42c865

Please sign in to comment.