in src/preset.ts [851:996]
async function expandConfigurePresetHelper(folder: string,
preset: ConfigurePreset,
workspaceFolder: string,
sourceDir: string,
allowUserPreset: boolean = false) {
if (preset.__expanded) {
return preset;
}
const refs = referencedConfigurePresets.get(folder)!;
if (refs.has(preset.name) && !preset.__expanded) {
// Referenced this preset before, but it still hasn't been expanded. So this is a circular inheritance.
log.error(localize('circular.inherits.in.config.preset', 'Circular inherits in configure preset {0}', preset.name));
return null;
}
refs.add(preset.name);
// Init env and cacheVar to empty if not specified to avoid null checks later
if (!preset.environment) {
preset.environment = EnvironmentUtils.createPreserveNull();
}
if (!preset.cacheVariables) {
preset.cacheVariables = {};
}
// Expand inherits
let inheritedEnv = EnvironmentUtils.createPreserveNull();
if (preset.inherits) {
if (util.isString(preset.inherits)) {
preset.inherits = [preset.inherits];
}
for (const parentName of preset.inherits) {
const parent = await expandConfigurePresetImpl(folder, parentName, workspaceFolder, sourceDir, allowUserPreset);
if (parent) {
// Inherit environment
inheritedEnv = EnvironmentUtils.mergePreserveNull([parent.environment, inheritedEnv]);
// Inherit cache vars
for (const name in parent.cacheVariables) {
if (preset.cacheVariables[name] === undefined) {
preset.cacheVariables[name] = parent.cacheVariables[name];
}
}
// Inherit other fields
let key: keyof ConfigurePreset;
for (key in parent) {
if (isInheritable(key) && preset[key] === undefined) {
// 'as never' to bypass type check
preset[key] = parent[key] as never;
}
}
}
}
}
inheritedEnv = EnvironmentUtils.mergePreserveNull([process.env, inheritedEnv]);
let compilerEnv = EnvironmentUtils.createPreserveNull();
// [Windows Only] If CMAKE_CXX_COMPILER or CMAKE_C_COMPILER is set as cl, clang, clang-cl, clang-cpp and clang++,
// but they are not on PATH, then set the env automatically.
if (process.platform === 'win32') {
const getStringValueFromCacheVar = (variable?: CacheVarType) => {
if (util.isString(variable)) {
return variable;
} else if (variable && typeof variable === 'object') {
return util.isString(variable.value) ? variable.value : null;
}
return null;
};
if (preset.cacheVariables) {
const cxxCompiler = getStringValueFromCacheVar(preset.cacheVariables['CMAKE_CXX_COMPILER'])?.toLowerCase();
const cCompiler = getStringValueFromCacheVar(preset.cacheVariables['CMAKE_C_COMPILER'])?.toLowerCase();
// The env variables for the supported compilers are the same.
const compilerName: string | undefined = util.isSupportedCompiler(cxxCompiler) || util.isSupportedCompiler(cCompiler);
if (compilerName) {
const compilerLocation = await execute('where.exe', [compilerName], null, {
environment: EnvironmentUtils.create(preset.environment),
silent: true,
encoding: 'utf8',
shell: true
}).result;
if (!compilerLocation.stdout) {
// Not on PATH, need to set env
const arch = getArchitecture(preset);
const toolset = getToolset(preset);
// Get version info for all VS instances. Create a map so we don't need to
// iterate through the array every time.
const vsVersions = new Map<string, string>();
for (const vs of await vsInstallations()) {
vsVersions.set(vs.instanceId, vs.installationVersion);
}
let latestVsVersion: string = '';
let latestVsIndex = -1;
for (let i = 0; i < kits.length; i++) {
const kit = kits[i];
if (kit.visualStudio && !kit.compilers) {
const version = vsVersions.get(kit.visualStudio);
if (kit.preferredGenerator && targetArchFromGeneratorPlatform(kit.preferredGenerator.platform) === arch &&
(kit.visualStudioArchitecture === toolset.host || kit.preferredGenerator.toolset === ('host=' + toolset.host))) {
if (toolset.version && version?.startsWith(toolset.version)) {
latestVsVersion = version;
latestVsIndex = i;
break;
}
if (!toolset.version && version && compareVersions(latestVsVersion, version) < 0) {
latestVsVersion = version;
latestVsIndex = i;
}
}
}
}
if (latestVsIndex < 0) {
log.error(localize('specified.cl.not.found',
"Configure preset {0}: Compiler {1} with toolset {2} and architecture {3} was not found, you may need to run the 'CMake: Scan for Compilers' command if this toolset exists on your computer.",
preset.name, `"${compilerName}.exe"`, toolset.version ? `"${toolset.version},${toolset.host}"` : `"${toolset.host}"`, `"${arch}"`));
} else {
compilerEnv = await effectiveKitEnvironment(kits[latestVsIndex]);
// if ninja isn't on path, try to look for it in a VS install
const ninjaLoc = await execute('where.exe', ['ninja'], null, {
environment: EnvironmentUtils.create(preset.environment),
silent: true,
encoding: 'utf8',
shell: true
}).result;
if (!ninjaLoc.stdout) {
const vsCMakePaths = await paths.vsCMakePaths(kits[latestVsIndex].visualStudio);
if (vsCMakePaths.ninja) {
log.warning(localize('ninja.not.set', 'Ninja is not set on PATH, trying to use {0}', vsCMakePaths.ninja));
compilerEnv['PATH'] = `${path.dirname(vsCMakePaths.ninja)};${compilerEnv['PATH']}`;
}
}
}
}
}
}
}
compilerEnv = EnvironmentUtils.mergePreserveNull([inheritedEnv, compilerEnv]);
preset.environment = EnvironmentUtils.mergePreserveNull([compilerEnv, preset.environment]);
preset.__expanded = true;
return preset;
}