Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read cmake file API on open #1909

Merged
merged 22 commits into from
Jun 21, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions src/cmake-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export enum ConfigureType {
Normal,
Clean,
Cache,
Auto
}

export enum ConfigureTrigger {
Expand Down Expand Up @@ -358,9 +359,9 @@ export class CMakeTools implements vscode.Disposable, api.CMakeToolsAPI {
/**
* Event fired when the code model from CMake is updated
*/
get codeModel() { return this._codeModel.value; }
get onCodeModelChanged() { return this._codeModel.changeEvent; }
private readonly _codeModel = new Property<codemodel_api.CodeModelContent|null>(null);
get codeModelContent() { return this._codeModelContent.value; }
get onCodeModelChanged() { return this._codeModelContent.changeEvent; }
private readonly _codeModelContent = new Property<codemodel_api.CodeModelContent|null>(null);
private _codeModelDriverSub: vscode.Disposable|null = null;

private readonly _communicationModeSub = this.workspaceContext.config.onChange('cmakeCommunicationMode', () => {
Expand Down Expand Up @@ -904,8 +905,8 @@ export class CMakeTools implements vscode.Disposable, api.CMakeToolsAPI {
}
const drv = await this._cmakeDriver;
console.assert(drv !== null, 'Null driver immediately after creation?');
if (drv instanceof codemodel_api.CodeModelDriver) {
this._codeModelDriverSub = drv.onCodeModelChanged(cm => { this._codeModel.set(cm); });
if (drv && !(drv instanceof LegacyCMakeDriver)) {
this._codeModelDriverSub = drv.onCodeModelChanged(cm => { this._codeModelContent.set(cm); });
}
}

Expand Down Expand Up @@ -991,6 +992,24 @@ export class CMakeTools implements vscode.Disposable, api.CMakeToolsAPI {
}

configureInternal(trigger: ConfigureTrigger = ConfigureTrigger.api, extra_args: string[] = [], type: ConfigureType = ConfigureType.Normal): Thenable<number> {
// Don't show a progress bar when the extension is running an internal auto-configuration.
if (type === ConfigureType.Auto) {
// TODO: title: localize('autoconfiguring.project', 'Configuring project')
return new Promise(async (resolve) => {
const drv = await this.getCMakeDriverInstance();
if (drv) {
const retc: number = await drv.configure(trigger, []);
if (retc === 0) {
await this._refreshCompileDatabase(drv.expansionOptions);
}
await this._ctestController.reloadTests(drv);
this._onReconfiguredEmitter.fire();
resolve(retc);
} else {
resolve(-1);
}
});
}
return vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
Expand Down
10 changes: 5 additions & 5 deletions src/cpptools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export interface CodeModelParams {
/**
* The CMake codemodel content. This is the important one.
*/
codeModel: codemodel_api.CodeModelContent;
codeModelContent: codemodel_api.CodeModelContent;
/**
* The contents of the CMakeCache.txt, which also provides supplementary
* configuration information.
Expand Down Expand Up @@ -413,9 +413,9 @@ export class CppConfigurationProvider implements cpt.CustomConfigurationProvider
const lang = fileGroup.language === "RC" ? undefined : fileGroup.language;
// First try to get toolchain values directly reported by CMake. Check the
// group's language compiler, then the C++ compiler, then the C compiler.
const comp_toolchains = opts.codeModel.toolchains?.get(lang ?? "")
|| opts.codeModel.toolchains?.get('CXX')
|| opts.codeModel.toolchains?.get('C');
const comp_toolchains: codemodel_api.CodeModelToolchain | undefined = opts.codeModelContent.toolchains?.get(lang ?? "")
|| opts.codeModelContent.toolchains?.get('CXX')
|| opts.codeModelContent.toolchains?.get('C');
// If none of those work, fall back to the same order, but in the cache.
const comp_cache = opts.cache.get(`CMAKE_${lang}_COMPILER`)
|| opts.cache.get('CMAKE_CXX_COMPILER')
Expand Down Expand Up @@ -525,7 +525,7 @@ export class CppConfigurationProvider implements cpt.CustomConfigurationProvider
let hadMissingCompilers = false;
this._workspaceBrowseConfiguration = {browsePath: []};
this._activeTarget = opts.activeTarget;
for (const config of opts.codeModel.configurations) {
for (const config of opts.codeModelContent.configurations) {
for (const project of config.projects) {
for (const target of project.targets) {
// Now some shenanigans since header files don't have config data:
Expand Down
6 changes: 5 additions & 1 deletion src/drivers/cmakefileapi/api_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,11 @@ export async function loadToolchains(filename: string): Promise<Map<string, Code

return toolchains.toolchains.reduce((acc, el) => {
if (el.compiler.path) {
acc.set(el.language, { path: el.compiler.path, target: el.compiler.target });
if (el.compiler.target) {
acc.set(el.language, { path: el.compiler.path, target: el.compiler.target });
} else {
acc.set(el.language, { path: el.compiler.path });
}
}
return acc;
}, new Map<string, CodeModelToolchain>());
Expand Down
23 changes: 16 additions & 7 deletions src/drivers/cmfileapi-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
loadToolchains
} from '@cmt/drivers/cmakefileapi/api_helpers';
import * as codemodel from '@cmt/drivers/codemodel-driver-interface';
import {CMakePreconditionProblemSolver} from '@cmt/drivers/driver';
import {CMakeDriver, CMakePreconditionProblemSolver} from '@cmt/drivers/driver';
import {CMakeGenerator, Kit} from '@cmt/kit';
import * as logging from '@cmt/logging';
import {fs} from '@cmt/pr';
Expand All @@ -37,7 +37,7 @@ const log = logging.createLogger('cmakefileapi-driver');
/**
* The CMake driver with FileApi of CMake >= 3.15.0
*/
export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
export class CMakeFileApiDriver extends CMakeDriver {
private constructor(cmake: CMakeExecutable,
readonly config: ConfigurationReader,
workspaceRootPath: string|null,
Expand Down Expand Up @@ -66,6 +66,7 @@ export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
}

private _needsReconfigure = true;
private _isConfiguredatLeastOnce = false;

/**
* Watcher for the CMake cache file on disk.
Expand Down Expand Up @@ -199,6 +200,13 @@ export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
}

async doConfigure(args_: string[], outputConsumer?: proc.OutputConsumer): Promise<number> {
if (!this._isConfiguredatLeastOnce && !this.config.configureOnOpen) { // if configureonopen false update code model, only first time, hasconfiguredyet?
this._needsReconfigure = true;
this._isConfiguredatLeastOnce = true;
await this.updateCodeModel();
return 0;
}

const api_path = this.getCMakeFileApiPath();
await createQueryFileForApi(api_path);

Expand Down Expand Up @@ -235,9 +243,9 @@ export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
log.trace(res.stdout);
if (res.retc === 0) {
this._needsReconfigure = false;
this._isConfiguredatLeastOnce = true;
await this.updateCodeModel();
}

return res.retc === null ? -1 : res.retc;
}

Expand Down Expand Up @@ -273,7 +281,7 @@ export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
throw Error('No code model object found');
}
this._target_map = await loadConfigurationTargetMap(reply_path, codemodel_obj.jsonFile);
this._codeModel = await loadExtCodeModelContent(reply_path, codemodel_obj.jsonFile);
this._codeModelContent = await loadExtCodeModelContent(reply_path, codemodel_obj.jsonFile);

// load toolchains
const toolchains_obj = indexFile.objects.find((value: index_api.Index.ObjectKind) => value.kind === 'toolchains');
Expand All @@ -288,15 +296,16 @@ export class CMakeFileApiDriver extends codemodel.CodeModelDriver {
'This version of CMake does not support the "toolchains" object kind. Compiler paths will be determined by reading CMakeCache.txt.'));
}
} else {
this._codeModel.toolchains = await loadToolchains(path.join(reply_path, toolchains_obj.jsonFile));
this._codeModelContent.toolchains = await loadToolchains(path.join(reply_path, toolchains_obj.jsonFile));
}

this._codeModelChanged.fire(this._codeModel);
this._codeModelChanged.fire(this._codeModelContent);
}
return indexFile !== null;
}

private _codeModel: codemodel.CodeModelContent|null = null;
private _codeModelContent: codemodel.CodeModelContent|null = null;
get codeModelContent() { return this._codeModelContent; }

get cmakeCacheEntries(): Map<string, api.CacheEntryProperties> { return this._cache; }
get generatorName(): string|null { return this._generatorInformation ? this._generatorInformation.name : null; }
Expand Down
10 changes: 8 additions & 2 deletions src/drivers/cms-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {CacheEntryProperties, ExecutableTarget, RichTarget} from '@cmt/api';
import * as cache from '@cmt/cache';
import * as cms from '@cmt/drivers/cms-client';
import * as codemodel from '@cmt/drivers/codemodel-driver-interface';
import {CMakePreconditionProblemSolver} from '@cmt/drivers/driver';
import {CMakeDriver, CMakePreconditionProblemSolver} from '@cmt/drivers/driver';
import {Kit, CMakeGenerator} from '@cmt/kit';
import {createLogger} from '@cmt/logging';
import * as proc from '@cmt/proc';
Expand All @@ -29,7 +29,8 @@ export class NoGeneratorError extends Error {
message: string = localize('no.usable.generator.found', 'No usable generator found.');
}

export class CMakeServerClientDriver extends codemodel.CodeModelDriver {
export class CMakeServerClientDriver extends CMakeDriver {

private constructor(cmake: CMakeExecutable, readonly config: ConfigurationReader, workspaceFolder: string | null, preconditionHandler: CMakePreconditionProblemSolver) {
super(cmake, config, workspaceFolder, preconditionHandler);
this.config.onChange('environment', () => this._restartClient());
Expand Down Expand Up @@ -384,6 +385,10 @@ export class CMakeServerClientDriver extends codemodel.CodeModelDriver {
});
}

get codeModelContent(): codemodel.CodeModelContent | null {
return null;
}

static async create(cmake: CMakeExecutable,
config: ConfigurationReader,
useCMakePresets: boolean,
Expand All @@ -402,6 +407,7 @@ export class CMakeServerClientDriver extends codemodel.CodeModelDriver {
testPreset,
preferredGenerators);
}

}

/**
Expand Down
21 changes: 0 additions & 21 deletions src/drivers/codemodel-driver-interface.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
import {CMakeDriver} from '@cmt/drivers/driver';
import * as vscode from 'vscode';

/**
* This file contains the API description between IDE parts and the CMake model driver.
* This API CodeModel contains only the current required CMake code model parts.
* There is more information provided by CMake than is mapped.
*/

/**
* Describes all required methods for access to the build code model of the driver
*/
export abstract class CodeModelDriver extends CMakeDriver {
/**
* Event registration for code model updates
*
* This event is fired after update of the code model, like after cmake configuration.
*/
abstract onCodeModelChanged: vscode.Event<CodeModelContent|null>;
}

export type TargetTypeString
= ('STATIC_LIBRARY'|'MODULE_LIBRARY'|'SHARED_LIBRARY'|'OBJECT_LIBRARY'|'EXECUTABLE'|'UTILITY'|'INTERFACE_LIBRARY');

Expand Down
33 changes: 29 additions & 4 deletions src/drivers/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {ConfigureArguments, VariantOption} from '@cmt/variant';
import * as nls from 'vscode-nls';
import { majorVersionSemver, minorVersionSemver, parseTargetTriple, TargetTriple } from '@cmt/triple';
import * as preset from '@cmt/preset';
import * as codemodel from '@cmt/drivers/codemodel-driver-interface';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -86,12 +87,20 @@ export abstract class CMakeDriver implements vscode.Disposable {
* Check if we need to reconfigure, such as if an important file has changed
*/
abstract checkNeedsReconfigure(): Promise<boolean>;
/**
* Event registration for code model updates
*
* This event is fired after update of the code model, like after cmake configuration.
*/
abstract onCodeModelChanged: vscode.Event<codemodel.CodeModelContent|null>;

/**
* List of targets known to CMake
*/
abstract get targets(): api.Target[];

abstract get codeModelContent(): codemodel.CodeModelContent|null;

/**
* List of executable targets known to CMake
*/
Expand Down Expand Up @@ -1095,6 +1104,8 @@ export abstract class CMakeDriver implements vscode.Disposable {
}

async configure(trigger: ConfigureTrigger, extra_args: string[], consumer?: proc.OutputConsumer, withoutCmakeSettings: boolean = false): Promise<number> {
// Check if this is an automatic configuration and adjust the logging messages based on that.
elahehrashedi marked this conversation as resolved.
Show resolved Hide resolved
const autoConfigInternal: boolean = (trigger === ConfigureTrigger.configureOnOpen && !this.config.configureOnOpen) ? true : false;
if (this.configRunning) {
await this.preconditionHandler(CMakePreconditionProblems.ConfigureIsAlreadyRunning);
return -1;
Expand All @@ -1108,13 +1119,18 @@ export abstract class CMakeDriver implements vscode.Disposable {
// _beforeConfigureOrBuild needs to refresh expansions early because it reads various settings
// (example: cmake.sourceDirectory).
await this._refreshExpansions();
log.debug(localize('start.configure', 'Start configure'), extra_args);
if (!autoConfigInternal) {
log.debug(localize('start.configure', 'Start configure'), extra_args);
} else {
log.debug(localize('start.auto.configure', 'Start auto configure'), extra_args);
}

const pre_check_ok = await this._beforeConfigureOrBuild();
if (!pre_check_ok) {
return -2;
}

// Cache flags will construct the command line for cmake.
const init_cache_flags = this.generateInitCacheFlags();

let expanded_flags: string[];
Expand All @@ -1139,7 +1155,9 @@ export abstract class CMakeDriver implements vscode.Disposable {
async (value: string) => expand.expandString(value, {...opts, envOverride: expanded_configure_env}));
expanded_flags = await Promise.all(expanded_flags_promises);
}
log.trace(localize('cmake.flags.are', 'CMake flags are {0}', JSON.stringify(expanded_flags)));
if (!autoConfigInternal) {
log.trace(localize('cmake.flags.are', 'CMake flags are {0}', JSON.stringify(expanded_flags)));
}

// A more complete round of expansions
await this._refreshExpansions();
Expand Down Expand Up @@ -1235,11 +1253,17 @@ export abstract class CMakeDriver implements vscode.Disposable {
telemetryMeasures['ErrorCount'] = retc ? 1 : 0;
}
}
telemetry.logEvent('configure', telemetryProperties, telemetryMeasures);
if (!autoConfigInternal) {
telemetry.logEvent('configure', telemetryProperties, telemetryMeasures);
}

return retc;
} catch {
log.info(localize('configure.failed', 'Failed to configure project'));
if (!autoConfigInternal) {
log.info(localize('configure.failed', 'Failed to configure project'));
} else {
log.info(localize('auto.configure.failed', 'Failed to auto configure project'));
}
return -1;
} finally {
this.configRunning = false;
Expand Down Expand Up @@ -1603,4 +1627,5 @@ export abstract class CMakeDriver implements vscode.Disposable {
await inst._baseInit(useCMakePresets, kit, configurePreset, buildPreset, testPreset, preferredGenerators);
return inst;
}

}
7 changes: 7 additions & 0 deletions src/drivers/legacy-driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import * as util from '@cmt/util';
import { ConfigurationReader } from '@cmt/config';
import * as nls from 'vscode-nls';
import { BuildPreset, ConfigurePreset, TestPreset } from '@cmt/preset';
import { CodeModelContent } from './codemodel-driver-interface';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -164,4 +165,10 @@ export class LegacyCMakeDriver extends CMakeDriver {
const gen = this.cmakeCache.get('CMAKE_GENERATOR');
return gen ? gen.as<string>() : null;
}

get codeModelContent(): CodeModelContent | null {
return null;
}
get onCodeModelChanged() { return new vscode.EventEmitter<null>().event; }

}
Loading