Files
Kmake/lib/kmake/Exporters/CompileCommandsExporter.js

152 lines
6.8 KiB
JavaScript
Raw Permalink Normal View History

2026-05-26 23:36:42 -07:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompilerCommandsExporter = void 0;
const fs = require("kmake/fsextra");
const path = require("path");
const Platform_1 = require("kmake/Platform");
const log = require("kmake/log");
const os = require("os");
const child_process = require("child_process");
const Exporter_1 = require("kmake/Exporters/Exporter");
class CompilerCommandsExporter extends Exporter_1.Exporter {
constructor(options) {
super(options);
}
async exportSolution(project, _from, to, platform, vrApi, options) {
var _a;
let from = path.resolve(process.cwd(), _from);
this.writeFile(path.resolve(to, 'compile_commands.json'));
let includes = [];
for (let inc of project.getIncludeDirs()) {
includes.push('-I');
includes.push(path.resolve(from, inc));
}
let defines = [];
for (let def of project.getDefines()) {
defines.push('-D');
defines.push(def.value.replace(/\"/g, '\\"'));
}
let objects = {};
let ofiles = {};
for (let fileobject of project.getFiles()) {
let file = fileobject.file;
if (file.endsWith('.cpp') || file.endsWith('.c') || file.endsWith('.cc') || file.endsWith('.s') || file.endsWith('.S')) {
if (fileobject.options && fileobject.options.nocompile) {
continue;
}
let name = file.toLowerCase();
if (name.indexOf('/') >= 0)
name = name.substr(name.lastIndexOf('/') + 1);
name = name.substr(0, name.lastIndexOf('.'));
if (!objects[name]) {
objects[name] = true;
ofiles[file] = name;
}
else {
while (objects[name]) {
name = name + '_';
}
objects[name] = true;
ofiles[file] = name;
}
}
}
let defaultArgs = [];
// TODO: same for MacOS, Windows, etc...
if (platform === Platform_1.Platform.Android) {
defaultArgs.push('--target=aarch64-none-linux-android21');
defaultArgs.push('-DANDROID');
// take a guess at where the ndk could be
function ndkFromSdkRoot() {
var _a;
let sdkEnv = (_a = process.env['ANDROID_HOME']) !== null && _a !== void 0 ? _a : process.env['ANDROID_SDK_ROOT'];
if (!sdkEnv)
return null;
let ndk_dir = path.join(sdkEnv, 'ndk');
if (!fs.existsSync(ndk_dir)) {
return null;
}
let ndks = fs.readdirSync(ndk_dir);
ndks = ndks.filter(item => !item.startsWith("."));
if (ndks.length < 1) {
return null;
}
return path.join(ndk_dir, ndks[0]);
}
let android_ndk = (_a = process.env['ANDROID_NDK']) !== null && _a !== void 0 ? _a : ndkFromSdkRoot();
if (android_ndk) {
let host_tag = '';
switch (os.platform()) {
// known host tags
// TODO: figure out the host tag for aarch64 darwin/linux/windows
case 'linux':
host_tag = 'linux-x86_64';
break;
case 'darwin':
host_tag = 'darwin-x86_64';
break;
case 'win32':
host_tag = 'windows-x86_64';
break;
}
let ndk_toolchain = path.join(android_ndk, `toolchains/llvm/prebuilt/${host_tag}`);
if (host_tag !== '' && fs.existsSync(ndk_toolchain)) {
defaultArgs.push(`--gcc-toolchain=${ndk_toolchain}`);
defaultArgs.push(`--sysroot=${ndk_toolchain}/sysroot`);
}
else {
// fallback to the first found toolchain
let toolchains = fs.readdirSync(path.join(android_ndk, `toolchains/llvm/prebuilt/`));
if (toolchains.length > 0) {
let host_tag = toolchains[0];
let ndk_toolchain = path.join(android_ndk, `toolchains/llvm/prebuilt/${host_tag}`);
defaultArgs.push(`--gcc-toolchain=${ndk_toolchain}`);
defaultArgs.push(`--sysroot=${ndk_toolchain}/sysroot`);
log.info(`Found android ndk toolchain in ${ndk_toolchain}.`);
}
else {
log.error('Platform is set to Android, but android toolchain not found.');
}
}
}
else {
log.error('Platform is set to Android, but android toolchain not found.\nPlease set the ANDROID_NDK environment variable if you need a compile_commands.json for your IDE.');
}
}
else if (platform === Platform_1.Platform.Emscripten) {
const emcc_bin = (process.platform === 'win32') ? 'emcc.bat' : 'emcc';
let emcc = child_process.spawnSync(emcc_bin, ['--cflags']);
// log.info(emcc.status);
if (emcc.status === 0) {
let flags = emcc.output.toString().split(' ');
defaultArgs.push(...flags);
}
else {
log.error('Platform is set to Emscripten, but emcc could not be found. Please add it to your PATH environment variable if you need a compile_commands.json for your IDE.');
}
}
let commands = [];
for (let fileobject of project.getFiles()) {
let file = fileobject.file;
if (file.endsWith('.c') || file.endsWith('.cpp') || file.endsWith('.cc')) {
let args = ['/usr/bin/clang', '-c', '-o', (options.debug ? 'debug' : 'release') + ofiles[file] + '.o'];
if (file.endsWith('.c')) {
args.push('-std=c99');
}
args.push(...defaultArgs);
args.push(path.resolve(from, file));
let command = {
directory: from,
file: path.resolve(from, file),
output: path.resolve(to, ofiles[file] + '.o'),
arguments: args.concat(includes).concat(defines)
};
commands.push(command);
}
}
this.p(JSON.stringify(commands));
this.closeFile();
}
}
exports.CompilerCommandsExporter = CompilerCommandsExporter;
//# sourceMappingURL=CompileCommandsExporter.js.map