This commit is contained in:
vector-of-bool 2016-11-16 22:26:13 -07:00
Родитель 681999506b
Коммит f0c7b1b9ca
5 изменённых файлов: 139 добавлений и 17 удалений

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

@ -45,6 +45,7 @@
"onCommand:cmake.quickStart",
"onCommand:cmake.debugTarget",
"onCommand:cmake.selectDebugTarget",
"onCommand:cmake.selectEnvironments",
"workspaceContains:CMakeLists.txt"
],
"main": "./out/src/extension",
@ -119,6 +120,11 @@
"command": "cmake.selectDebugTarget",
"title": "Select a Target to Debug",
"category": "CMake"
},
{
"command": "cmake.selectEnvironments",
"title": "Select active build environments",
"category": "CMake"
}
],
"configuration": {

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

@ -602,6 +602,7 @@ export class CMakeTools {
private _debugTargetButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 3.1);
private _testStatusButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 3.05);
private _warningMessage = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 3);
private _environmentSelectionButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 200);
private _failingTestDecorationType = vscode.window.createTextEditorDecorationType({
borderColor: 'rgba(255, 0, 0, 0.2)',
borderWidth: '1px',
@ -1090,21 +1091,80 @@ export class CMakeTools {
this._refreshStatusBarItems();
}
public activeEnvironments : Maybe<string[]> = null;
public activateEnvironment(name: string) {
const env = this.availableEnvironments.get(name);
if (!env) {
throw new Error(`Invalid environment named ${name}`);
}
if (!this.activeEnvironments) {
throw new Error(`Invalid state: Environments not yet loaded!`);
}
this.activeEnvironments.push(name);
this._refreshStatusBarItems();
this._workspaceCacheContent.activeEnvironments = this.activeEnvironments;
this._writeWorkspaceCacheContent();
}
public deactivateEnvironment(name: string) {
if (!this.activeEnvironments) {
throw new Error('Invalid state: Environments not yet loaded!');
}
const idx = this.activeEnvironments.indexOf(name);
if (idx >= 0) {
this.activeEnvironments.splice(idx, 1);
this._refreshStatusBarItems();
}
this._workspaceCacheContent.activeEnvironments = this.activeEnvironments;
this._writeWorkspaceCacheContent();
}
private _availableEnvironments : Map<string, Map<string, string>> = new Map();
public get availableEnvironments() : Map<string, Map<string, string>> {
return this._availableEnvironments;
}
private _loadingEnvironments: Promise<void>;
public get loadingEnvironments() : Promise<void> {
return this._loadingEnvironments;
}
public async selectEnvironments(): Promise<void> {
await this.loadingEnvironments;
const entries = Array.from(this.availableEnvironments.keys())
.map(name => ({
name: name,
label: this.activeEnvironments!.indexOf(name) >= 0
? `$(check) ${name}`
: name,
description: '',
}));
const chosen = await vscode.window.showQuickPick(entries);
if (!chosen) {
return;
}
this.activeEnvironments!.indexOf(chosen.name) >= 0
? this.deactivateEnvironment(chosen.name)
: this.activateEnvironment(chosen.name);
}
private async _init(ctx: vscode.ExtensionContext): Promise<void> {
environment.availableEnvironments().map(
pr => pr.then(env => {
if (env.variables) {
console.log(`Detected env ${env.name}`);
}
}).catch(e => {
console.error(e);
})
);
this._channel = new ThrottledOutputChannel('CMake/Build');
//this._channel = vscode.window.createOutputChannel('CMake/Build');
this._ctestChannel = vscode.window.createOutputChannel('CTest Results');
this._diagnostics = vscode.languages.createDiagnosticCollection('cmake-build-diags');
// Start loading up available environments early, this may take a few seconds
const env_promises = environment.availableEnvironments();
for (const pr of env_promises) {
pr.then(env => {
if (env.variables) {
console.log(`Detected available environemt "${env.name}"`);
this._availableEnvironments.set(env.name, env.variables);
}
});
}
const watcher = this._variantWatcher = vscode.workspace.createFileSystemWatcher(path.join(vscode.workspace.rootPath, 'cmake-variants.*'));
watcher.onDidChange(this._reloadVariants.bind(this));
watcher.onDidCreate(this._reloadVariants.bind(this));
@ -1137,6 +1197,19 @@ export class CMakeTools {
this._reloadConfiguration();
});
this._loadingEnvironments = Promise.all(env_promises);
this._loadingEnvironments.then(() => {
// All environments have been detected, now we can update the UI
this.activeEnvironments = [];
const envs = this._workspaceCacheContent.activeEnvironments || [];
envs.map(e => {
if (this.availableEnvironments.has(e)) {
this.activateEnvironment(e);
}
});
this._refreshStatusBarItems();
}).catch(e => console.error(e));
if (this.config.initialBuildType !== null) {
vscode.window.showWarningMessage('The "cmake.initialBuildType" setting is now deprecated and will no longer be used.');
}
@ -1204,6 +1277,7 @@ export class CMakeTools {
this._debugButton.text = '$(bug)';
this._debugTargetButton.hide();
}
this._environmentSelectionButton.show();
} else {
this._cmakeToolsStatusItem.hide();
this._buildButton.hide();
@ -1211,6 +1285,7 @@ export class CMakeTools {
this._testStatusButton.hide();
this._debugButton.hide();
this._debugTargetButton.hide();
this._environmentSelectionButton.hide();
}
if (this._testStatusButton.text == '') {
this._testStatusButton.hide();
@ -1249,6 +1324,22 @@ export class CMakeTools {
this._debugButton.tooltip = 'Run the debugger on the selected target executable';
this._debugTargetButton.text = this.currentDebugTarget || '[No target selected for debugging]';
this._debugTargetButton.command = 'cmake.selectDebugTarget';
this._environmentSelectionButton.command = 'cmake.selectEnvironments';
if (this.activeEnvironments !== null) {
if (this.activeEnvironments.length) {
this._environmentSelectionButton.text = `Working in ${this.activeEnvironments.join(', ')}`;
} else {
if (this.availableEnvironments.size !== 0) {
this._environmentSelectionButton.text = 'Select a build environment...';
} else {
// No environments available. No need to show this button
this._environmentSelectionButton.hide();
}
}
} else {
this._environmentSelectionButton.text = 'Detecting available build environments...';
}
}
public get projectName() {
@ -1362,17 +1453,31 @@ export class CMakeTools {
options: ExecuteOptions = {silent: false, environment: {}},
parser: util.OutputParser = new NullParser())
: Promise<ExecutionResult> {
return new Promise<ExecutionResult>((resolve, _) => {
return new Promise<ExecutionResult>(async (resolve, _) => {
await this.loadingEnvironments;
const silent: boolean = options && options.silent || false;
console.info('Execute cmake with arguments:', args);
const pipe = proc.spawn(this.config.cmakePath, args, {
env: Object.assign(
Object.assign({
{
// We set NINJA_STATUS to force Ninja to use the format
// that we would like to parse
NINJA_STATUS: '[%f/%t %p] '
}, options.environment),
},
options.environment,
this.config.environment,
this.activeEnvironments!.reduce<any>(
(acc, name) => {
const env_ = this.availableEnvironments.get(name);
console.assert(env_);
const env = env_!;
for (const entry of env.entries()) {
acc[entry[0]] = entry[1];
}
return acc;
},
{}
),
process.env
)
});

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

@ -1,5 +1,6 @@
import * as path from 'path';
import * as proc from 'child_process';
import * as fs from 'fs';
import * as vscode from 'vscode';
@ -8,7 +9,7 @@ import {util} from './util';
type Maybe<T> = util.Maybe<T>;
interface Environment {
export interface Environment {
name: string;
variables: Maybe<Map<string, string>>;
}
@ -22,7 +23,7 @@ const ENVIRONMENTS: EnvironmentProvider[] = [{
// Detect Visual C++ environments
async tryCreateEnvironment(progfiles, dist, arch): Promise<Environment> {
const vcvarsall = path.join(progfiles, dist, 'VC/vcvarsall.bat');
const name = `${dist} ${arch}`;
const name = `${dist} - ${arch}`;
if (!await async.exists(vcvarsall)) {
return {name, variables: null};
}
@ -40,7 +41,7 @@ const ENVIRONMENTS: EnvironmentProvider[] = [{
await util.ensureDirectory(path.dirname(batpath));
await util.writeFile(batpath, bat.join('\r\n'));
const prom = new Promise<Maybe<string>>((resolve, reject) => {
const pipe = proc.spawn(batpath, [], {shell: true, env: {}});
const pipe = proc.spawn(batpath, [], {shell: true});
let stdout_acc = '';
pipe.stdout.on('data', (data) => {
stdout_acc += data.toString();
@ -49,10 +50,15 @@ const ENVIRONMENTS: EnvironmentProvider[] = [{
resolve(stdout_acc);
});
pipe.on('exit', (code) => {
fs.unlink(batpath, err => {
if (err) {
console.error(`Error removing temporary batch file!`, err);
}
});
if (code) {
resolve(null);
}
})
});
});
const output = await prom;
if (!output) {
@ -79,7 +85,10 @@ const ENVIRONMENTS: EnvironmentProvider[] = [{
return [];
}
const progfile_dirs = [`C:\\Program Files`, `C:\\Program Files (x86)`];
const dists = ['Microsoft Visual Studio 14.0'];
const dists = [
'Microsoft Visual Studio 12.0',
'Microsoft Visual Studio 14.0',
];
const archs = ['x86', 'amd64'];
type PEnv = Promise<Maybe<Environment>>;
const prom_environments = progfile_dirs.reduce<PEnv[]>(

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

@ -27,6 +27,7 @@ export async function activate(context: vscode.ExtensionContext) {
'stop',
'debugTarget',
'selectDebugTarget',
'selectEnvironments',
]) {
context.subscriptions.push(register('cmake.' + key, cmake[key as string]));
}

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

@ -116,6 +116,7 @@ export namespace util {
export interface WorkspaceCache {
variant?: Maybe<VariantCombination>;
activeEnvironments?: string[];
};
export function normalizePath(p: string, normalize_case=true): string {