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

Fix1914 - Variable substitution stopped working with release 1.7 #3268

Closed
Closed
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Bug Fixes:
- When using CMake presets, the Project Status View now shows the build target along with the build preset. [PR #3241](https://github.com/microsoft/vscode-cmake-tools/pull/3241)
- Fix per-folder browse configurations returning incorrect information. [#3155](https://github.com/microsoft/vscode-cmake-tools/issues/3155)
- IntelliSense resolves headers coming from MacOS frameworks. CMake 3.27 or later is required. [#2324](https://github.com/microsoft/vscode-cmake-tools/issues/2324)
- Support variable expansion in sourceDirectory setting related to various kit info. [#1914](https://github.com/microsoft/vscode-cmake-tools/issues/1914)
- Allow configure settings to override the usual arguments the extension is usually passing to cmake. Don't have unremovable options. [#1639](https://github.com/microsoft/vscode-cmake-tools/issues/1639)
- Fix triggers of "Bad CMake Executable" error message. [#2368](https://github.com/microsoft/vscode-cmake-tools/issues/2368)
- Don't ignore empty cache string variables when configuring from presets. [#1842](https://github.com/microsoft/vscode-cmake-tools/issues/1842)
Expand Down
37 changes: 30 additions & 7 deletions src/cmakeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,9 @@ export class CMakeProject {
}
if (selectedFile) {
const newSourceDirectory = path.dirname(selectedFile);
await this.setSourceDir(await util.normalizeAndVerifySourceDir(newSourceDirectory, CMakeDriver.sourceDirExpansionOptions(this.workspaceContext.folder.uri.fsPath)));
await this.setSourceDir(await util.normalizeAndVerifySourceDir(newSourceDirectory,
await CMakeDriver.sourceDirExpansionOptions(this.workspaceContext.folder.uri.fsPath, this.getActiveKit(),
(await this.getCMakeDriverInstance())?.generatorName)));
void vscode.workspace.getConfiguration('cmake', this.workspaceFolder.uri).update("sourceDirectory", this._sourceDir);
if (config) {
// Updating sourceDirectory here, at the beginning of the configure process,
Expand Down Expand Up @@ -913,7 +915,10 @@ export class CMakeProject {
*/
private async init(sourceDirectory: string) {
log.debug(localize('second.phase.init', 'Starting CMake Tools second-phase init'));
await this.setSourceDir(await util.normalizeAndVerifySourceDir(sourceDirectory, CMakeDriver.sourceDirExpansionOptions(this.workspaceContext.folder.uri.fsPath)));
this.kitsController = await KitsController.init(this);
await this.setSourceDir(await util.normalizeAndVerifySourceDir(sourceDirectory,
await CMakeDriver.sourceDirExpansionOptions(this.workspaceContext.folder.uri.fsPath, this.getActiveKit(),
(await this.getCMakeDriverInstance())?.generatorName)));
this.hideBuildButton = (this.workspaceContext.config.statusbar.advanced?.build?.visibility === "hidden") ? true : false;
this.hideDebugButton = (this.workspaceContext.config.statusbar.advanced?.debug?.visibility === "hidden") ? true : false;
this.hideLaunchButton = (this.workspaceContext.config.statusbar.advanced?.launch?.visibility === "hidden") ? true : false;
Expand Down Expand Up @@ -941,7 +946,6 @@ export class CMakeProject {

this.statusMessage.set(localize('ready.status', 'Ready'));

this.kitsController = await KitsController.init(this);
this.presetsController = await PresetsController.init(this, this.kitsController, this.isMultiProjectFolder);

await this.doUseCMakePresetsChange();
Expand Down Expand Up @@ -1011,6 +1015,27 @@ export class CMakeProject {
return this.presetsController.onUserPresetsChanged(listener);
}

/**
* Calculate which kit object should be used for variable exapansion.
* Obviously, the active kit if set but otherwise, since variable expansion may need kit information before the active kit is determined
* (like very early during project load) then deduce from previous user selection which was saved in the workspace state.
* Do not change any flow related to how and when this.activeKit is set. When it is null, this method just returns a kit (if we find one)
* but without setting it as active here.
*/
public getActiveKit(): Kit | null {
if (this.activeKit) {
return this.activeKit;
}

const kitName: string | null = this.workspaceContext.state.getActiveKitName(this.folderName, this.isMultiProjectFolder);
if (kitName) {
// It remembers a kit. Find it in the kits avail in this dir:
return this.kitsController.availableKits.find(k => k.name === kitName) || null;
}

return null;
}

async initializeKitOrPresets() {
if (this.useCMakePresets) {
const latestConfigPresetName = this.workspaceContext.state.getConfigurePresetName(this.folderName, this.isMultiProjectFolder);
Expand All @@ -1024,10 +1049,8 @@ export class CMakeProject {
}
} else {
// Check if the CMakeProject remembers what kit it was last using in this dir:
const kitName = this.workspaceContext.state.getActiveKitName(this.folderName, this.isMultiProjectFolder);
if (kitName) {
// It remembers a kit. Find it in the kits avail in this dir:
const kit = this.kitsController.availableKits.find(k => k.name === kitName) || null;
const kit = this.getActiveKit();
if (kit) {
// Set the kit: (May do nothing if no kit was found)
await this.setKit(kit);
}
Expand Down
26 changes: 22 additions & 4 deletions src/drivers/cmakeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { getValue } from '@cmt/preset';
import { CacheEntry } from '@cmt/cache';
import { CMakeBuildRunner } from '@cmt/cmakeBuildRunner';
import { DebuggerInformation } from '@cmt/debug/debuggerConfigureDriver';
import { getActiveProject } from '@cmt/extension';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
Expand Down Expand Up @@ -358,7 +359,6 @@ export abstract class CMakeDriver implements vscode.Disposable {

// Fill in default replacements
const vars: expand.KitContextVars = {
buildKit: this._kit ? this._kit.name : '__unknownkit__',
buildType: this.currentBuildType,
generator: this.generatorName || 'null',
workspaceFolder: ws_root,
Expand All @@ -367,6 +367,7 @@ export abstract class CMakeDriver implements vscode.Disposable {
workspaceRoot: ws_root,
workspaceRootFolderName: path.basename(ws_root),
userHome: paths.userHome,
buildKit: this._kit?.name ?? '__unknownkit__',
buildKitVendor: this._kitDetect?.vendor ?? '__unknow_vendor__',
buildKitTriple: this._kitDetect?.triple ?? '__unknow_triple__',
buildKitVersion: version,
Expand All @@ -390,12 +391,28 @@ export abstract class CMakeDriver implements vscode.Disposable {
return { vars, variantVars };
}

static sourceDirExpansionOptions(workspaceFolderFspath: string | null): expand.ExpansionOptions {
static async sourceDirExpansionOptions(workspaceFolderFspath: string | null, kit?: Kit | null, generatorName?: string | null): Promise<expand.ExpansionOptions> {
const ws_root = util.lightNormalizePath(workspaceFolderFspath || '.');

// Fill in default replacements
if (!kit) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same worry here, I'm not sure we want to be using kits every time the cmakeDriver uses this method, since couldn't a preset use this method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect point, I'll rethink and be back with an update.

kit = getActiveProject()?.getActiveKit();
}
const kitDetect: KitDetect | undefined = kit ? await getKitDetect(kit) : undefined;
const target: Partial<TargetTriple> = parseTargetTriple(kitDetect?.triple ?? '') ?? {};
const version = kitDetect?.version ?? '0.0';

const vars: expand.MinimalPresetContextVars = {
generator: 'generator',
generator: generatorName ?? 'generator',
buildKit: kit?.name ?? '__unknownkit__',
buildKitVendor: kitDetect?.vendor ?? '__unknow_vendor__',
buildKitTriple: kitDetect?.triple ?? '__unknow_triple__',
buildKitVersion: version,
buildKitHostOs: process.platform,
buildKitTargetOs: target.targetOs ?? '__unknow_target_os__',
buildKitTargetArch: target.targetArch ?? '__unknow_target_arch__',
buildKitVersionMajor: majorVersionSemver(version),
buildKitVersionMinor: minorVersionSemver(version),
workspaceFolder: ws_root,
workspaceFolderBasename: path.basename(ws_root),
sourceDir: '${sourceDir}',
Expand Down Expand Up @@ -680,7 +697,8 @@ export abstract class CMakeDriver implements vscode.Disposable {

private async _refreshExpansions(configurePreset?: preset.ConfigurePreset | null) {
return this.doRefreshExpansions(async () => {
this.sourceDir = await util.normalizeAndVerifySourceDir(this.sourceDirUnexpanded, CMakeDriver.sourceDirExpansionOptions(this.workspaceFolder));
this.sourceDir = await util.normalizeAndVerifySourceDir(this.sourceDirUnexpanded,
await CMakeDriver.sourceDirExpansionOptions(this.workspaceFolder, this._kit, this._generator?.name));

const opts = this.expansionOptions;
opts.envOverride = await this.getConfigureEnvironment(configurePreset);
Expand Down
2 changes: 1 addition & 1 deletion src/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ async function expandStringHelper(input: string, opts: ExpansionOptions) {
if (key !== 'dollar') {
// Replace dollar sign at the very end of the expanding process
const replacement = replacements[key];
if (!replacement) {
if (replacement === undefined) {
log.warning(localize('invalid.variable.reference', 'Invalid variable reference {0} in string: {1}', full, input));
} else {
subs.set(full, replacement);
Expand Down
17 changes: 16 additions & 1 deletion src/presetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import rollbar from '@cmt/rollbar';
import { ExpansionOptions } from '@cmt/expand';
import paths from '@cmt/paths';
import { KitsController } from '@cmt/kitsController';
import { descriptionForKit, Kit, SpecialKits } from '@cmt/kit';
import { descriptionForKit, Kit, getKitDetect, SpecialKits } from '@cmt/kit';
import { majorVersionSemver, minorVersionSemver, parseTargetTriple, TargetTriple } from '@cmt/triple';
import { getHostTargetArchString } from '@cmt/installs/visualStudio';
import { loadSchema } from '@cmt/schema';
import json5 = require('json5');
Expand Down Expand Up @@ -42,12 +43,26 @@ export class PresetsController {
const presetsController = new PresetsController(project, kitsController, isMultiProject);
const expandSourceDir = async (dir: string) => {
const workspaceFolder = project.workspaceFolder.uri.fsPath;
const kit = project.getActiveKit();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part worries me, if we're in the presetsController then don't we not care about kits? Since it's either kits or Presets? Not both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't step back and realize this obvious fact. I just noticed errors and complains in my repro and just went head first into making those go away. I'll rethink a bit and get back with an update. Very good essential point.

const kitDetect = kit ? await getKitDetect(kit) : undefined;
const target: Partial<TargetTriple> | undefined = kitDetect ? parseTargetTriple(kitDetect?.triple ?? '') ?? {} : undefined;
const version = kitDetect?.version ?? '0.0';

const expansionOpts: ExpansionOptions = {
vars: {
workspaceFolder,
workspaceFolderBasename: path.basename(workspaceFolder),
workspaceHash: util.makeHashString(workspaceFolder),
workspaceRoot: workspaceFolder,
buildKit: kit?.name || '__unknownkit__',
buildKitVendor: kitDetect?.vendor ?? '__unknow_vendor__',
buildKitTriple: kitDetect?.triple ?? '__unknow_triple__',
buildKitVersion: version,
buildKitHostOs: process.platform,
buildKitTargetOs: target?.targetOs ?? '__unknow_target_os__',
buildKitTargetArch: target?.targetArch ?? '__unknow_target_arch__',
buildKitVersionMajor: majorVersionSemver(version),
buildKitVersionMinor: minorVersionSemver(version),
workspaceRootFolderName: path.dirname(workspaceFolder),
userHome: paths.userHome,
// Following fields are not supported for sourceDir expansion
Expand Down
9 changes: 7 additions & 2 deletions src/projectController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,10 @@ export class ProjectController implements vscode.Disposable {
}

async getProjectForFolder(folder: string): Promise<CMakeProject | undefined> {
const sourceDir = util.platformNormalizePath(await util.normalizeAndVerifySourceDir(folder, CMakeDriver.sourceDirExpansionOptions(folder)));
const kit = this.activeProject?.activeKit;
const sourceDir = util.platformNormalizePath(await util.normalizeAndVerifySourceDir(folder,
await CMakeDriver.sourceDirExpansionOptions(folder, kit,
(await this.activeProject?.getCMakeDriverInstance())?.generatorName)));
const allCMakeProjects: CMakeProject[] = this.getAllCMakeProjects();
for (const project of allCMakeProjects) {
if (util.platformNormalizePath(project.sourceDir) === sourceDir ||
Expand Down Expand Up @@ -390,7 +393,9 @@ export class ProjectController implements vscode.Disposable {
}
// Normalize the paths.
for (let i = 0; i < sourceDirectories.length; i++) {
sourceDirectories[i] = await util.normalizeAndVerifySourceDir(sourceDirectories[i], CMakeDriver.sourceDirExpansionOptions(folder.uri.fsPath));
sourceDirectories[i] = await util.normalizeAndVerifySourceDir(sourceDirectories[i],
await CMakeDriver.sourceDirExpansionOptions(folder.uri.fsPath, this.activeProject?.activeKit,
(await this.activeProject?.getCMakeDriverInstance())?.generatorName));
}
const projects: CMakeProject[] | undefined = this.getProjectsForWorkspaceFolder(folder);

Expand Down