Skip to content

Commit

Permalink
Add vendor hostOs targetOs targetArch versionMajor versionMinor attri…
Browse files Browse the repository at this point in the history
…butes for kit.
  • Loading branch information
lygstate committed Jun 29, 2020
1 parent 804808a commit 983bad9
Show file tree
Hide file tree
Showing 9 changed files with 401 additions and 46 deletions.
6 changes: 6 additions & 0 deletions docs/cmake-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ Some options support the replacement of special values in their string value by
|`${workspaceRootFolderName}`| The name of the leaf directory in the workspace directory path.|
|`${buildType}`|The current CMake build type. For example: `Debug`, `Release`, `MinSizeRel`|
|`${buildKit}`| The current CMake kit name. For example: `GCC 7.3.0`|
|`${buildKitVendor}`| The current CMake kit vendor. Possible values: `gnu|msvc|llvm` and so on, all lowercase|
|`${buildKitHostOs}`| The current CMake kit host OS. Possible values: `win32|osx|linux` and so on, all lowercase|
|`${buildKitTargetOs}`| The current CMake kit target OS. Possible values: `win32|osx|linux` and so on, all lowercase|
|`${buildKitTargetArch}`| The current CMake kit target architecture. Possible values `x86,x64,arm,aarch64` and so on, all lowercase|
|`${buildKitVersionMajor}`| The current CMake kit major version. For example: `7`|
|`${buildKitVersionMinor}`| The current CMake kit minor version. For example: `3`|
|`${generator}`| The name of the CMake generator. For example: `Ninja`|
|`${projectName}`|**DEPRECATED**. Expands to the constant string `"ProjectName"` CMake does not consider there to be just one project name to use. The concept of a single project does not work in CMake. Use `${workspaceRootFolderName}`, instead.|
|`${userHome}`| The full path to the current user's home directory. |
Expand Down
24 changes: 24 additions & 0 deletions schemas/kits-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@
"type": "string",
"description": "Name of this kit"
},
"vendor": {
"type": "string",
"description": "The vendor of this kit"
},
"hostOs": {
"type": "string",
"description": "The host OS of this kit"
},
"targetOs": {
"type": "string",
"description": "The target OS of this kit"
},
"targetArch": {
"type": "string",
"description": "The target architecture of this kit"
},
"versionMajor": {
"type": "string",
"description": "The major version of this kit"
},
"versionMinor": {
"type": "string",
"description": "The minor version of this kit"
},
"keep": {
"type": "boolean",
"description": "If `true`, this kit will be kept even if it appears out-of-date."
Expand Down
6 changes: 6 additions & 0 deletions src/drivers/driver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ export abstract class CMakeDriver implements vscode.Disposable {
generator: this.generatorName || 'null',
userHome: paths.userHome,
buildKit: this._kit ? this._kit.name : '__unknownkit__',
buildKitVendor: this?._kit?.vendor ?? '__unknow_vendor__',
buildKitHostOs: this?._kit?.hostOs ?? '__unknow_host_os__',
buildKitTargetOs: this?._kit?.targetOs ?? '__unknow_target_os__',
buildKitTargetArch: this?._kit?.targetArch ?? '__unknow_target_arch__',
buildKitVersionMajor: this?._kit?.versionMajor ?? '__unknow_version_major__',
buildKitVersionMinor: this?._kit?.versionMinor ?? '__unknow_version_minor__',
// DEPRECATED EXPANSION: Remove this in the future:
projectName: 'ProjectName',
};
Expand Down
6 changes: 6 additions & 0 deletions src/expand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export interface RequiredExpansionContextVars {
workspaceFolder: string;
buildType: string;
buildKit: string;
buildKitVendor: string;
buildKitHostOs: string;
buildKitTargetOs: string;
buildKitTargetArch: string;
buildKitVersionMajor: string;
buildKitVersionMinor: string;
workspaceRootFolderName: string;
workspaceFolderBasename: string;
generator: string;
Expand Down
174 changes: 128 additions & 46 deletions src/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {fs} from './pr';
import * as proc from './proc';
import {loadSchema} from './schema';
import {compare, dropNulls, objectPairs, Ordering} from './util';
import { findTargetTriple, parseTargetTriple, TargetTriple } from './triple';
import * as nls from 'vscode-nls';

nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
Expand Down Expand Up @@ -62,6 +63,36 @@ export interface Kit {
*/
name: string;

/**
* The vendor of the kit
*/
vendor?: string;

/**
* The host OS of the kit
*/
hostOs?: string;

/**
* The target OS of the kit
*/
targetOs?: string;

/**
* The target architecture of the kit
*/
targetArch?: string;

/**
* The major version of the kit
*/
versionMajor?: string;

/**
* The minor version of the kit
*/
versionMinor?: string;

/**
* The preferred CMake generator for this kit
*/
Expand Down Expand Up @@ -116,14 +147,15 @@ export interface Kit {
interface ClangVersion {
fullVersion: string;
version: string;
target?: string;
target: TargetTriple;
threadModel?: string;
installedDir?: string;
}

async function getClangVersion(binPath: string): Promise<ClangVersion|null> {
log.debug(localize('testing.clang.binary', 'Testing Clang binary: {0}', binPath));
const exec = await proc.execute(binPath, ['-v']).result;
const execOption: proc.ExecutionOptions = { environment: {LC_ALL : 'C' } };
const exec = await proc.execute(binPath, ['-v'], null, execOption).result;
if (exec.retc !== 0) {
log.debug(localize('bad.clang.binary', 'Bad Clang binary ("-v" returns non-zero): {0}', binPath));
return null;
Expand All @@ -132,23 +164,22 @@ async function getClangVersion(binPath: string): Promise<ClangVersion|null> {
const version_re = /^(?:Apple LLVM|Apple clang|clang) version ([^\s-]+)[\s-]/;
let version: string = "";
let fullVersion: string = "";
let target: TargetTriple | undefined;
for (const line of lines) {
const version_match = version_re.exec(line);
if (version_match !== null) {
version = version_match[1];
fullVersion = line;
break;
}
const target_triple_match = findTargetTriple(line);
if (target_triple_match !== null) {
target = parseTargetTriple(target_triple_match);
}
}
if (!version) {
if (!version || !target) {
log.debug(localize('bad.clang.binary.output', 'Bad Clang binary {0} -v output: {1}', binPath, exec.stderr));
return null;
}
const target_mat = /Target:\s+(.*)/.exec(exec.stderr);
let target: string|undefined;
if (target_mat) {
target = target_mat[1];
}
const thread_model_mat = /Thread model:\s+(.*)/.exec(exec.stderr);
let threadModel: string|undefined;
if (thread_model_mat) {
Expand All @@ -168,6 +199,24 @@ async function getClangVersion(binPath: string): Promise<ClangVersion|null> {
};
}

function majorVersionSemver(semver: string) : string {
const major_version_re = /^(\d+)./;
const major_version_match = major_version_re.exec(semver);
if (Array.isArray(major_version_match)) {
return major_version_match[1] ?? '';
}
return '';
}

function minorVersionSemver(semver: string) : string {
const minor_version_re = /^(\d+).(\d+)/;
const minor_version_match = minor_version_re.exec(semver);
if (Array.isArray(minor_version_match)) {
return minor_version_match[2] ?? '';
}
return '';
}

/**
* Convert a binary (by path) to a CompilerKit. This checks if the named binary
* is a GCC or Clang compiler and gets its version. If it is not a compiler,
Expand All @@ -186,7 +235,8 @@ export async function kitIfCompiler(bin: string, pr?: ProgressReporter): Promise
log.debug(localize('testing.gcc.binary', 'Testing GCC binary: {0}', bin));
if (pr)
pr.report({message: localize('getting.gcc.version', 'Getting GCC version for {0}', bin)});
const exec = await proc.execute(bin, ['-v']).result;
const execOption: proc.ExecutionOptions = { environment: {LC_ALL : 'C' } };
const exec = await proc.execute(bin, ['-v'], null, execOption).result;
if (exec.retc !== 0) {
log.debug(localize('bad.gcc.binary', 'Bad GCC binary ("-v" returns non-zero): {0}', bin));
return null;
Expand All @@ -195,39 +245,43 @@ export async function kitIfCompiler(bin: string, pr?: ProgressReporter): Promise
const compiler_version_output = exec.stderr.trim().split('\n');
const version_re = /^gcc version (.*?) .*/;
let version: string = "";
let target: TargetTriple | undefined;

for (const line of compiler_version_output) {
const version_match = version_re.exec(line);
if (version_match !== null) {
version = version_match[1];
break;
}
const target_triple_match = findTargetTriple(line);
if (target_triple_match !== null) {
target = parseTargetTriple(target_triple_match);
}
}
if (!version) {
if (!version || !target) {
log.debug(localize('bad.gcc.binary.output', 'Bad GCC binary {0} -v output: {1}', bin, exec.stderr));
return null;
}
const gxx_fname = fname.replace(/gcc/, 'g++');
const gxx_bin = path.join(path.dirname(bin), gxx_fname);
const target_triple_re = /((\w+-)+)gcc.*/;
const target_triple_match = target_triple_re.exec(fname);
let description = '';
if (target_triple_match !== null) {
description += `for ${target_triple_match[1].slice(0, -1)} `;
}
const name = `GCC ${description}${version}`;
const name = `GCC for ${target.triple} ${version}`;
log.debug(localize('detected.gcc.compiler', 'Detected GCC compiler: {0}', bin));
let gccKit: Kit = {
name,
compilers: {
C: bin,
}
};

const gccCompilers: {[lang: string]: string} = { C: bin };
if (await fs.exists(gxx_bin)) {
gccKit = {name, compilers: {C: bin, CXX: gxx_bin}};
gccCompilers.CXX = gxx_bin;
}
const gccKit: Kit = {
name,
vendor: `gnu-${target.vendor}`,
hostOs: process.platform,
targetOs: target.targetOs,
targetArch: target.targetArch,
versionMajor: majorVersionSemver(version),
versionMinor: minorVersionSemver(version),
compilers: gccCompilers
};

const isWin32 = process.platform === 'win32';

if (isWin32 && bin.toLowerCase().includes('mingw')) {
const binParentPath = path.dirname(bin);
const mingwMakePath = path.join(binParentPath, 'mingw32-make.exe');
Expand Down Expand Up @@ -274,7 +328,7 @@ export async function kitIfCompiler(bin: string, pr?: ProgressReporter): Promise
if (version === null) {
return null;
}
if (version.target && version.target.includes('msvc')) {
if (version.target && version.target.triple.includes('msvc')) {
// DO NOT include Clang's that target MSVC but don't present the MSVC
// command-line interface. CMake does not support them properly.
return null;
Expand All @@ -283,22 +337,20 @@ export async function kitIfCompiler(bin: string, pr?: ProgressReporter): Promise
const clangxx_bin = path.join(path.dirname(bin), clangxx_fname);
const name = `Clang ${version.version}`;
log.debug(localize('detected.clang.compiler', 'Detected Clang compiler: {0}', bin));
const clangCompilers: {[lang: string]: string} = { C: bin };
if (await fs.exists(clangxx_bin)) {
return {
name,
compilers: {
C: bin,
CXX: clangxx_bin,
},
};
} else {
return {
name,
compilers: {
C: bin,
},
};
clangCompilers.CXX = clangxx_bin;
}
return {
name,
vendor: `clang-${version.target.vendor}}`,
hostOs: process.platform,
targetOs: version.target.targetOs,
targetArch: version.target.targetArch,
versionMajor: majorVersionSemver(version.version),
versionMinor: minorVersionSemver(version.version),
compilers: clangCompilers,
};
} else {
return null;
}
Expand Down Expand Up @@ -739,6 +791,12 @@ async function tryCreateNewVCEnvironment(inst: VSInstallation, hostArch: string,

const kit: Kit = {
name,
vendor: 'msvc',
hostOs: process.platform,
targetOs: process.platform,
targetArch,
versionMajor: majorVersionSemver(inst.installationVersion),
versionMinor: minorVersionSemver(inst.installationVersion),
visualStudio: kitVSName(inst),
visualStudioArchitecture: hostArch
};
Expand Down Expand Up @@ -805,9 +863,15 @@ async function scanDirForClangCLKits(dir: string, vsInstalls: VSInstallation[]):
}
return vsInstalls.map((vs): Kit => {
const installName = vsDisplayName(vs);
const vs_arch = (version.target && version.target.includes('i686-pc')) ? 'x86' : 'amd64';
const vs_arch = version.target.targetArch === 'x86_64' ? 'amd64' : 'x86' ;
return {
name: localize('clang.for.msvc', 'Clang {0} for MSVC with {1} ({2})', version.version, installName, vs_arch),
vendor: 'clang_msvc' + majorVersionSemver(vs.installationVersion),
hostOs: process.platform,
targetOs: version.target.targetOs,
targetArch: version.target.targetArch,
versionMajor: majorVersionSemver(version.version),
versionMinor: minorVersionSemver(version.version),
visualStudio: kitVSName(vs),
visualStudioArchitecture: vs_arch,
compilers: {
Expand Down Expand Up @@ -881,11 +945,29 @@ export async function effectiveKitEnvironment(kit: Kit, opts?: expand.ExpansionO
}
}
const env = new Map(util.chain(host_env, kit_env));
if (env.has("CMT_MINGW_PATH")) {
const isWin32 = process.platform === 'win32';
if (isWin32)
{
const path_list: string[] = [];
if (kit.vendor?.startsWith('gnu-')) {
const cCompiler = kit.compilers?.C;
if (cCompiler) {
path_list.push(path.dirname(cCompiler));
}
}
const cmt_mingw_path = env.get("CMT_MINGW_PATH");
if (cmt_mingw_path) {
path_list.push(cmt_mingw_path);
}
let path_key : string | undefined = undefined;
if (env.has("PATH")) {
env.set("PATH", env.get("PATH")!.concat(`;${env.get("CMT_MINGW_PATH")}`));
path_key = "PATH";
} else if (env.has("Path")) {
env.set("Path", env.get("Path")!.concat(`;${env.get("CMT_MINGW_PATH")}`));
path_key = "Path";
}
if (path_key) {
path_list.unshift(env.get(path_key) ?? '');
env.set(path_key, path_list.join(';'));
}
}
return env;
Expand Down
6 changes: 6 additions & 0 deletions src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ class Paths {
workspaceFolder: wsc.folder.uri.fsPath,
userHome: this.userHome,
buildKit: '',
buildKitVendor: '',
buildKitHostOs: '',
buildKitTargetOs: '',
buildKitTargetArch: '',
buildKitVersionMajor: '',
buildKitVersionMinor: '',
buildType: '',
generator: '',
workspaceRootFolderName: path.basename(wsc.folder.uri.fsPath),
Expand Down
Loading

0 comments on commit 983bad9

Please sign in to comment.