in Extension/src/LanguageServer/cppBuildTaskProvider.ts [58:160]
public async getTasks(appendSourceToName: boolean): Promise<CppBuildTask[]> {
const editor: TextEditor | undefined = window.activeTextEditor;
const emptyTasks: CppBuildTask[] = [];
if (!editor) {
return emptyTasks;
}
const fileExt: string = path.extname(editor.document.fileName);
if (!fileExt) {
return emptyTasks;
}
// Don't offer tasks for header files.
const fileExtLower: string = fileExt.toLowerCase();
const isHeader: boolean = !fileExt || [".cuh", ".hpp", ".hh", ".hxx", ".h++", ".hp", ".h", ".ii", ".inl", ".idl", ""].some(ext => fileExtLower === ext);
if (isHeader) {
return emptyTasks;
}
// Don't offer tasks if the active file's extension is not a recognized C/C++ extension.
let fileIsCpp: boolean;
let fileIsC: boolean;
if (fileExt === ".C") { // ".C" file extensions are both C and C++.
fileIsCpp = true;
fileIsC = true;
} else {
fileIsCpp = [".cu", ".cpp", ".cc", ".cxx", ".c++", ".cp", ".ino", ".ipp", ".tcc"].some(ext => fileExtLower === ext);
fileIsC = fileExtLower === ".c";
}
if (!(fileIsCpp || fileIsC)) {
return emptyTasks;
}
// Get compiler paths.
const isWindows: boolean = os.platform() === 'win32';
let activeClient: Client;
try {
activeClient = ext.getActiveClient();
} catch (errJS) {
const e: Error = errJS as Error;
if (!e || e.message !== ext.intelliSenseDisabledError) {
console.error("Unknown error calling getActiveClient().");
}
return emptyTasks; // Language service features may be disabled.
}
// Get user compiler path.
const userCompilerPathAndArgs: util.CompilerPathAndArgs | undefined = await activeClient.getCurrentCompilerPathAndArgs();
let userCompilerPath: string | undefined;
if (userCompilerPathAndArgs) {
userCompilerPath = userCompilerPathAndArgs.compilerPath;
if (userCompilerPath && userCompilerPathAndArgs.compilerName) {
userCompilerPath = userCompilerPath.trim();
if (isWindows && userCompilerPath.startsWith("/")) { // TODO: Add WSL compiler support.
userCompilerPath = undefined;
} else {
userCompilerPath = userCompilerPath.replace(/\\\\/g, "\\");
}
}
}
const isCompilerValid: boolean = userCompilerPath ? await util.checkFileExists(userCompilerPath) : false;
const userCompilerIsCl: boolean = isCompilerValid && !!userCompilerPathAndArgs && userCompilerPathAndArgs.compilerName === "cl.exe";
// Get known compiler paths. Do not include the known compiler path that is the same as user compiler path.
// Filter them based on the file type to get a reduced list appropriate for the active file.
// Only allow one instance of cl.exe to be included, as the user must launch VS Code using a VS command
// prompt in order to build with cl.exe, so only one can apply.
const knownCompilerPathsSet: Set<string> = new Set();
let knownCompilers: configs.KnownCompiler[] | undefined = await activeClient.getKnownCompilers();
if (knownCompilers) {
const compiler_condition: (info: configs.KnownCompiler) => boolean = info => ((fileIsCpp && !info.isC) || (fileIsC && info.isC)) &&
(!isCompilerValid || (!!userCompilerPathAndArgs &&
(path.basename(info.path) !== userCompilerPathAndArgs.compilerName))) &&
(!isWindows || !info.path.startsWith("/")); // TODO: Add WSL compiler support.
const cl_to_add: configs.KnownCompiler | undefined = userCompilerIsCl ? undefined : knownCompilers.find(info =>
((path.basename(info.path) === "cl.exe") && compiler_condition(info)));
knownCompilers = knownCompilers.filter(info =>
((info === cl_to_add) || (path.basename(info.path) !== "cl.exe" && compiler_condition(info))));
knownCompilers.map<void>(info => {
knownCompilerPathsSet.add(info.path);
});
}
const knownCompilerPaths: string[] | undefined = knownCompilerPathsSet.size ?
Array.from(knownCompilerPathsSet) : undefined;
if (!knownCompilerPaths && !userCompilerPath) {
// Don't prompt a message yet until we can make a data-based decision.
telemetry.logLanguageServerEvent('noCompilerFound');
return emptyTasks;
}
// Create a build task per compiler path
let result: CppBuildTask[] = [];
// Tasks for known compiler paths
if (knownCompilerPaths) {
result = knownCompilerPaths.map<Task>(compilerPath => this.getTask(compilerPath, appendSourceToName, undefined));
}
// Task for valid user compiler path setting
if (isCompilerValid && userCompilerPath) {
result.push(this.getTask(userCompilerPath, appendSourceToName, userCompilerPathAndArgs?.additionalArgs));
}
return result;
}