Skip to content

Commit 3526f50

Browse files
check if the compiler path and debugger path exist. (#9813)
1 parent 2be467e commit 3526f50

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

Extension/src/Debugger/configurationProvider.ts

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -408,9 +408,18 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
408408
// Generating a task is async, therefore we must *await* *all* map(task => config) Promises to resolve.
409409
let configs: CppDebugConfiguration[] = [];
410410
if (buildTasks.length !== 0) {
411-
configs = await Promise.all(buildTasks.map<Promise<CppDebugConfiguration>>(async task => {
411+
configs = (await Promise.all(buildTasks.map<Promise<CppDebugConfiguration | undefined>>(async task => {
412412
const definition: CppBuildTaskDefinition = task.definition as CppBuildTaskDefinition;
413413
const compilerPath: string = definition.command;
414+
// Filter out the tasks that has an invalid compiler path.
415+
const compilerPathExists: boolean = path.isAbsolute(compilerPath) ?
416+
// Absolute path, just check if it exists
417+
await util.checkFileExists(compilerPath) :
418+
// Non-absolute. Check on $PATH
419+
((await util.whichAsync(compilerPath)) !== undefined);
420+
if (!compilerPathExists) {
421+
logger.getOutputChannelLogger().appendLine(localize('compiler.path.not.exists', "Unable to find {0}. {1} task is ignored.", compilerPath, definition.label));
422+
}
414423
const compilerName: string = path.basename(compilerPath);
415424
const newConfig: CppDebugConfiguration = { ...defaultTemplateConfig }; // Copy enumerables and properties
416425
newConfig.existing = false;
@@ -439,20 +448,24 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
439448
const isCl: boolean = compilerName === "cl.exe";
440449
newConfig.cwd = isWindows && !isCl && !process.env.PATH?.includes(path.dirname(compilerPath)) ? path.dirname(compilerPath) : "${fileDirname}";
441450

442-
return new Promise<CppDebugConfiguration>(resolve => {
451+
return new Promise<CppDebugConfiguration | undefined>(async resolve => {
443452
if (platformInfo.platform === "darwin") {
444453
return resolve(newConfig);
445454
} else {
446455
let debuggerName: string;
447456
if (compilerName.startsWith("clang")) {
448457
newConfig.MIMode = "lldb";
449-
debuggerName = "lldb-mi";
450-
// Search for clang-8, clang-10, etc.
451-
if ((compilerName !== "clang-cl.exe") && (compilerName !== "clang-cpp.exe")) {
452-
const suffixIndex: number = compilerName.indexOf("-");
453-
if (suffixIndex !== -1) {
454-
const suffix: string = compilerName.substring(suffixIndex);
455-
debuggerName += suffix;
458+
if (isWindows) {
459+
debuggerName = "lldb";
460+
} else {
461+
debuggerName = "lldb-mi";
462+
// Search for clang-8, clang-10, etc.
463+
if ((compilerName !== "clang-cl.exe") && (compilerName !== "clang-cpp.exe")) {
464+
const suffixIndex: number = compilerName.indexOf("-");
465+
if (suffixIndex !== -1) {
466+
const suffix: string = compilerName.substring(suffixIndex);
467+
debuggerName += suffix;
468+
}
456469
}
457470
}
458471
newConfig.type = DebuggerType.cppdbg;
@@ -468,22 +481,27 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
468481
}
469482
const compilerDirname: string = path.dirname(compilerPath);
470483
const debuggerPath: string = path.join(compilerDirname, debuggerName);
471-
if (isWindows) {
484+
485+
// Check if debuggerPath exists.
486+
if (await util.checkFileExists(debuggerPath)) {
472487
newConfig.miDebuggerPath = debuggerPath;
473-
return resolve(newConfig);
488+
} else if ((await util.whichAsync(debuggerName)) !== undefined) {
489+
// Check if debuggerName exists on $PATH
490+
newConfig.miDebuggerPath = debuggerName;
474491
} else {
475-
fs.stat(debuggerPath, (err, stats: fs.Stats) => {
476-
if (!err && stats && stats.isFile()) {
477-
newConfig.miDebuggerPath = debuggerPath;
478-
} else {
479-
newConfig.miDebuggerPath = path.join("/usr", "bin", debuggerName);
480-
}
481-
return resolve(newConfig);
482-
});
492+
// Try the usr path for non-windows platforms.
493+
const usrDebuggerPath: string = path.join("/usr", "bin", debuggerName);
494+
if (!isWindows && await util.checkFileExists(usrDebuggerPath)) {
495+
newConfig.miDebuggerPath = usrDebuggerPath;
496+
} else {
497+
logger.getOutputChannelLogger().appendLine(localize('debugger.path.not.exists', "Unable to find the {0} debugger. The debug configuration for {1} is ignored.", `\"${debuggerName}\"`, compilerName));
498+
return resolve(undefined);
499+
}
483500
}
501+
return resolve(newConfig);
484502
}
485503
});
486-
}));
504+
}))).filter((item): item is CppDebugConfiguration => !!item);
487505
}
488506
configs.push(defaultTemplateConfig);
489507
const existingConfigs: CppDebugConfiguration[] | undefined = this.getLaunchConfigs(folder, type)?.map(config => {

Extension/src/common.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* ------------------------------------------------------------------------------------------ */
55

66
import * as path from 'path';
7+
import * as which from 'which';
78
import * as fs from 'fs';
89
import * as os from 'os';
910
import * as child_process from 'child_process';
@@ -1411,3 +1412,15 @@ export interface ISshLocalForwardInfo {
14111412
localSocket?: string;
14121413
remoteSocket?: string;
14131414
}
1415+
1416+
export function whichAsync(name: string): Promise<string | undefined> {
1417+
return new Promise<string | undefined>(resolve => {
1418+
which(name, (err, resolved) => {
1419+
if (err) {
1420+
resolve(undefined);
1421+
} else {
1422+
resolve(resolved);
1423+
}
1424+
});
1425+
});
1426+
}

0 commit comments

Comments
 (0)