Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
15 changes: 13 additions & 2 deletions src/cmakeExecutable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,18 @@ export interface CMakeExecutable {

const cmakeInfo = new Map<string, CMakeExecutable>();

export async function getCMakeExecutableInformation(path: string, config?: ConfigurationReader): Promise<CMakeExecutable> {
/**
* Query a cmake binary for its version and capabilities.
*
* @param path Path to the cmake executable.
* @param config Optional configuration used to provide the child process environment.
* @param cwd Optional working directory to run the probe in. This matters for users
* whose `cmake` is provided by a directory-based version manager (mise, asdf, vfox, ...):
* their shims resolve the tool version by walking up from the current working directory,
* so the probe must run inside the project. When omitted, the child process inherits the
* extension host's `process.cwd()`, which is not guaranteed to be the workspace folder.
*/
export async function getCMakeExecutableInformation(path: string, config?: ConfigurationReader, cwd?: string): Promise<CMakeExecutable> {
const cmake: CMakeExecutable = {
path,
isPresent: false,
Expand All @@ -51,7 +62,7 @@ export async function getCMakeExecutableInformation(path: string, config?: Confi
}

try {
const execOpt: proc.ExecutionOptions = { showOutputOnError: true, environment: config?.environment };
const execOpt: proc.ExecutionOptions = { showOutputOnError: true, environment: config?.environment, cwd: cwd || undefined };
const execVersion = await proc.execute(path, ['--version'], null, execOpt).result;
if (execVersion.retc === 0 && execVersion.stdout) {
console.assert(execVersion.stdout);
Expand Down
2 changes: 1 addition & 1 deletion src/cmakeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1605,7 +1605,7 @@ export class CMakeProject {

async getCMakeExecutable() {
const cmakePath: string = await this.getCMakePathofProject();
const cmakeExe = await getCMakeExecutableInformation(cmakePath);
const cmakeExe = await getCMakeExecutableInformation(cmakePath, undefined, this.folderPath);
if (cmakeExe.version && this.minCMakeVersion && versionLess(cmakeExe.version, this.minCMakeVersion)) {
rollbar.error(localize('cmake.version.not.supported',
'CMake version {0} may not be supported. Minimum version required is {1}.',
Expand Down
6 changes: 6 additions & 0 deletions src/cmakeTaskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,12 @@ export class CustomBuildTaskTerminal extends proc.CommandConsumer implements vsc
if (!this.options) {
this.options = {};
}
// Default the working directory to the project so directory-based version managers
// (mise, asdf, vfox, ...) can resolve the cmake shim; otherwise the child inherits
// the extension host's process.cwd(), which may be outside the workspace.
if (this.options.cwd === undefined) {
this.options.cwd = cmakeDriver.binaryDir || cmakeDriver.sourceDir || this.workspaceFolder?.uri.fsPath;
}
this.preset = await this.resolvePresetName(this.preset, project.useCMakePresets, CommandType.build);
if (this.preset) {
const buildPreset: preset.BuildPreset | undefined = await project?.expandBuildPresetbyName(this.preset);
Expand Down
4 changes: 2 additions & 2 deletions src/debug/cmakeDebugger/debuggerScriptDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function executeScriptWithDebugger(scriptPath: string, scriptArgs:
const cmakeProject = extensionManager?.getActiveProject();
const cmakePath = await cmakeProject?.getCMakePathofProject();
if (cmakeProject && cmakePath) {
const cmakeExe = await getCMakeExecutableInformation(cmakePath);
const cmakeExe = await getCMakeExecutableInformation(cmakePath, undefined, cmakeProject.folderPath);
if (cmakeExe.isDebuggerSupported) {
const concreteArgs = ["-P", scriptPath];
concreteArgs.push(...scriptArgs);
Expand All @@ -49,7 +49,7 @@ export async function executeScriptWithDebugger(scriptPath: string, scriptArgs:
const commandShell = process.platform === 'win32' ? proc.determineShell(cmakeExe.path) : false;
const configShell = cmakeProject.workspaceContext.config.shell;
const shell = (commandShell || undefined) ?? configShell ?? undefined;
const child = proc.execute(cmakeExe.path, concreteArgs, outputConsumer, { environment: env, shell });
const child = proc.execute(cmakeExe.path, concreteArgs, outputConsumer, { environment: env, shell, cwd: cmakeProject.folderPath || undefined });

while (
!outputConsumer.stateMessages.includes(
Expand Down
8 changes: 7 additions & 1 deletion src/drivers/cmakeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,12 @@ export abstract class CMakeDriver implements vscode.Disposable {
const commandShell = process.platform === 'win32' ? proc.determineShell(command) : false;
const shell = options?.shell ?? (commandShell || undefined) ?? this.config.shell ?? undefined;
const exec_options = { ...options, environment, shell };
// Run driver subprocesses inside the project by default so directory-based version
// managers (mise, asdf, vfox, ...) can resolve the tool version. Without a cwd the
// child inherits the extension host's process.cwd(), which may be outside the workspace.
if (exec_options.cwd === undefined) {
exec_options.cwd = this.sourceDir || undefined;
}
return proc.execute(command, args, consumer, exec_options);
}

Expand Down Expand Up @@ -2015,7 +2021,7 @@ export abstract class CMakeDriver implements vscode.Disposable {
}
}
} else {
const exeOpt: proc.ExecutionOptions = { environment: buildcmd.build_env, outputEncoding: outputEnc, useAutoEncoding: isAutoEncoding };
const exeOpt: proc.ExecutionOptions = { environment: buildcmd.build_env, outputEncoding: outputEnc, useAutoEncoding: isAutoEncoding, cwd: this.binaryDir || undefined };
this.cmakeBuildRunner.setBuildProcess(this.executeCommand(buildcmd.command, buildcmd.args, consumer, exeOpt));
}
const result = await this.cmakeBuildRunner.getResult();
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class ExtensionManager implements vscode.Disposable {
cmakePath = await workspaceContext.getCMakePath() || '';
}
// initialize the state of the cmake exe
await getCMakeExecutableInformation(cmakePath, this.workspaceConfig);
await getCMakeExecutableInformation(cmakePath, this.workspaceConfig, vscode.workspace.workspaceFolders?.[0]?.uri.fsPath);

await util.setContextValue("cmake:testExplorerIntegrationEnabled", this.workspaceConfig.testExplorerIntegrationEnabled);
if (this.workspaceConfig.testExplorerIntegrationEnabled) {
Expand Down
5 changes: 4 additions & 1 deletion src/kits/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,10 @@ async function scanDirForClangForMSVCKits(dir: PathWithTrust, vsInstalls: VSInst
log.info(localize("failed.to.scan.for.kits", "Unable to scan for GNU CLI Clang kits: CMake Path is undefined"));
return null;
} else {
const cmake_executable = await getCMakeExecutableInformation(cmakePath);
// Probe from the workspace folder so directory-based version managers (mise, asdf,
// vfox, ...) can resolve the cmake shim; otherwise the child inherits the extension
// host's process.cwd(), which may be outside the workspace and fail to resolve.
const cmake_executable = await getCMakeExecutableInformation(cmakePath, undefined, vscode.workspace.workspaceFolders?.[0]?.uri.fsPath);
if (undefined === cmake_executable.version) {
return null;
} else {
Expand Down
Loading