Skip to content

Commit

Permalink
Support usage of env vars for Kit.toolchainFile (#991)
Browse files Browse the repository at this point in the history
* Support usage of env vars for Kit.toolchainFile

* add support for ${workspaceFolder:+}

* update changelog

* rewording

Co-authored-by: Andreea Isac <48239328+andreeis@users.noreply.github.com>
  • Loading branch information
bobbrow and andreeis authored Oct 7, 2020
1 parent 0eb594a commit 4c3b678
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# What's New?

## 1.5.0
Improvements:
- Support variables for Kit.toolchainFile. [#991](https://github.com/microsoft/vscode-cmake-tools/pull/991)[#1056](https://github.com/microsoft/vscode-cmake-tools/issues/1056) [@blakehurd](https://github.com/blakehurd)/[@bobbrow](https://github.com/bobbrow)

## 1.4.2
Improvements:
- Added new variable substitution command: `${command:cmake.launchTargetFilename}`. [#632](https://github.com/microsoft/vscode-cmake-tools/issues/632) [@ebai101](https://github.com/ebai101)
Expand Down
20 changes: 16 additions & 4 deletions src/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,37 @@ export async function expandString(tmpl: string, opts: ExpansionOptions) {
}
}

const env_re = /\$\{env:(.+?)\}/g;
const env_re = /\$\{env:(.+)\}/g;
while ((mat = env_re.exec(tmpl))) {
const full = mat[0];
const varname = mat[1];
const repl = fixPaths(env[normalizeEnvironmentVarname(varname)]) || '';
subs.set(full, repl);
}

const env_re2 = /\$\{env\.(.+?)\}/g;
const env_re2 = /\$\{env\.(.+)\}/g;
while ((mat = env_re2.exec(tmpl))) {
const full = mat[0];
const varname = mat[1];
const repl = fixPaths(env[normalizeEnvironmentVarname(varname)]) || '';
subs.set(full, repl);
}

if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
const folder_re = /\$\{workspaceFolder:(.+)\}/g;
while (mat = folder_re.exec(tmpl)) {
const full = mat[0];
const folderName = mat[1];
const f = vscode.workspace.workspaceFolders.find(folder => folder.name.toLocaleLowerCase() === folderName.toLocaleLowerCase());
if (f) {
subs.set(full, f.uri.fsPath);
}
}
}

if (opts.variantVars) {
const variants = opts.variantVars;
const variant_regex = /\$\{variant:(.+?)\}/g;
const variant_regex = /\$\{variant:(.+)\}/g;
while ((mat = variant_regex.exec(tmpl))) {
const full = mat[0];
const varname = mat[1];
Expand All @@ -119,7 +131,7 @@ export async function expandString(tmpl: string, opts: ExpansionOptions) {
}
}

const command_re = /\$\{command:(.+?)\}/g;
const command_re = /\$\{command:(.+)\}/g;
while ((mat = command_re.exec(tmpl))) {
const full = mat[0];
const command = mat[1];
Expand Down
20 changes: 19 additions & 1 deletion src/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,24 @@ export async function descriptionForKit(kit: Kit): Promise<string> {
return localize('unspecified.let.cmake.guess', 'Unspecified (Let CMake guess what compilers and environment to use)');
}

async function expandKitVariables(kit: Kit): Promise<Kit> {
if (kit.toolchainFile) {
kit.toolchainFile = await expand.expandString(kit.toolchainFile, {
vars: {
buildKit: kit.name,
buildType: '${buildType}', // Unsupported variable substitutions use identity.
generator: '${generator}',
userHome: paths.userHome,
workspaceFolder: '${workspaceFolder}',
workspaceFolderBasename: '${workspaceFolderBasename}',
workspaceRoot: '${workspaceRoot}',
workspaceRootFolderName: '${workspaceRootFolderName}'
}
});
}
return kit;
}

export async function readKitsFile(filepath: string): Promise<Kit[]> {
if (!await fs.exists(filepath)) {
log.debug(localize('not.reading.nonexistent.kit', 'Not reading non-existent kits file: {0}', filepath));
Expand All @@ -1062,7 +1080,7 @@ export async function readKitsFile(filepath: string): Promise<Kit[]> {
}
const kits = kits_raw as Kit[];
log.info(localize('successfully.loaded.kits', 'Successfully loaded {0} kits from {1}', kits.length, filepath));
return dropNulls(kits);
return Promise.all(dropNulls(kits).map(expandKitVariables));
}

function convertMingwDirsToSearchPaths(mingwDirs: string[]): string[] {
Expand Down
20 changes: 19 additions & 1 deletion test/unit-tests/kitmanager.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {readKitsFile, getShellScriptEnvironment} from '@cmt/kit';
import {expect} from '@test/util';
import * as path from 'path';
import * as vscode from 'vscode';
import paths from '@cmt/paths';
import {fs} from '@cmt/pr';

Expand All @@ -11,8 +12,14 @@ function getTestResourceFilePath(filename: string): string {
return path.normalize(path.join(here, '../../../test/unit-tests', filename));
}

// for safety, ensure we reset the state of the process.env after every test since we're manipulating it in this suite.
const env = {...process.env};

suite('Kits test', async () => {
teardown(() => {
process.env = env;
});

test('Test load of kit from test file', async () => {
const kits = await readKitsFile(getTestResourceFilePath('test_kit.json'));
const names = kits.map(k => k.name);
Expand All @@ -21,11 +28,22 @@ suite('Kits test', async () => {
'CompilerKit 2',
'CompilerKit 3 with PreferredGenerator',
'ToolchainKit 1',
'ToolchainKit 2',
'ToolchainKit 3',
'VSCode Kit 1',
'VSCode Kit 2',
]);
});

test('Test use of env var in toolchain kit specified from test file', async () => {
process.env.CMAKE_TOOLS_TEST_SOME_ENV_VAR = "Test";
const folderName = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.fsPath : "";
const kits = await readKitsFile(getTestResourceFilePath('test_kit.json'));

expect(kits.filter(k => "ToolchainKit 2" === k.name)[0].toolchainFile).to.eq("Test/toolchain.cmake");
expect(kits.filter(k => "ToolchainKit 3" === k.name)[0].toolchainFile).to.eq(`${folderName}/toolchain.cmake`);
});

test('Test load env vars from shell script', async() => {
const fname_extension = process.platform == 'win32' ? 'bat' : 'sh';
const fname = `cmake-kit-test-${Math.random().toString()}.${fname_extension}`;
Expand All @@ -50,4 +68,4 @@ suite('Kits test', async () => {
expect(env_vars_arr).to.deep.include(['TESTVAR13', 'cde']);
}
});
});
});
8 changes: 8 additions & 0 deletions test/unit-tests/test_kit.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
"name": "ToolchainKit 1",
"toolchainFile": "toolchain.cmake"
},
{
"name": "ToolchainKit 2",
"toolchainFile": "${env:CMAKE_TOOLS_TEST_SOME_ENV_VAR}/toolchain.cmake"
},
{
"name": "ToolchainKit 3",
"toolchainFile": "${workspaceFolder:test-project-without-cmakelists}/toolchain.cmake"
},
{
"name": "VSCode Kit 1",
"visualStudio": "Visual Studio 2015",
Expand Down

0 comments on commit 4c3b678

Please sign in to comment.