217 lines
5.8 KiB
JavaScript
Executable File
217 lines
5.8 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
import * as path from 'node:path';
|
|
import * as url from 'node:url';
|
|
import * as fs from 'node:fs';
|
|
import * as child_process from 'node:child_process';
|
|
|
|
// Logging
|
|
const EXIT_FAILURE = 1;
|
|
function fail(message) {
|
|
console.error(message);
|
|
process.exit(EXIT_FAILURE);
|
|
}
|
|
function err(message) {
|
|
fail('ERROR: ' + message);
|
|
}
|
|
function info(message) {
|
|
console.log('INFO: ' + message);
|
|
}
|
|
|
|
// Enums
|
|
function Enum(values) {
|
|
for (const value of values) {
|
|
this[value] = {
|
|
prettyName: value,
|
|
name: value.toLowerCase()
|
|
};
|
|
}
|
|
}
|
|
Enum.prototype.get = function (name) {
|
|
for (const value in this) {
|
|
if (value.toLowerCase() === name.toLowerCase()) {
|
|
return this[value];
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
function wrap(obj) {
|
|
return new Proxy(obj, {
|
|
get(target, property) {
|
|
if (property in target) {
|
|
return target[property];
|
|
} else {
|
|
err('Undefined Value: ' + property);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
const PackageTypes = wrap(new Enum([
|
|
'None',
|
|
'AppImage',
|
|
'Flatpak'
|
|
]));
|
|
const Architectures = wrap(new Enum([
|
|
'AMD64',
|
|
'ARM64',
|
|
'ARMHF',
|
|
'Host'
|
|
]));
|
|
const Configurations = wrap(new Enum([
|
|
'Release',
|
|
'Debug'
|
|
]));
|
|
|
|
// Folders
|
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
const root = path.join(__dirname, '..');
|
|
let build = path.join(root, 'build');
|
|
let out = path.join(root, 'out');
|
|
|
|
// Positional Arguments
|
|
let argIndex = 2; // Skip First Two Arguments
|
|
function parseArg(arg, from, type) {
|
|
// Check Argument
|
|
if (arg === undefined) {
|
|
err('Expecting ' + type);
|
|
}
|
|
// Read Argument
|
|
const value = from.get(arg);
|
|
if (value === null) {
|
|
err(`Invalid ${type}: ${arg}`);
|
|
}
|
|
// Return
|
|
return value;
|
|
}
|
|
function readArg(...args) {
|
|
return parseArg(process.argv[argIndex++], ...args);
|
|
}
|
|
// Type Of Packaging
|
|
const packageType = readArg(PackageTypes, 'Package Type');
|
|
// Build Architecture
|
|
const architecture = readArg(Architectures, 'Architecture');
|
|
// Flatpak Builds Work Best Without Custom Toolchains
|
|
if (packageType === PackageTypes.Flatpak && architecture !== Architectures.Host) {
|
|
err('Flatpak Builds Do Not Support Custom Toolchains');
|
|
}
|
|
|
|
// CMake Build Options
|
|
const options = new Map();
|
|
|
|
// Other Arguments
|
|
let clean = false;
|
|
let install = false;
|
|
let config = Configurations.Release;
|
|
for (; argIndex < process.argv.length; argIndex++) {
|
|
const arg = process.argv[argIndex];
|
|
const cmakeArgPrefix = '-D';
|
|
if (arg.startsWith(cmakeArgPrefix)) {
|
|
// Pass Build Option To CMake
|
|
let parsedArg = arg.substring(cmakeArgPrefix.length);
|
|
const parts = parsedArg.split('=');
|
|
if (parts.length !== 2) {
|
|
err('Unable To Parse Build Option: ' + arg);
|
|
}
|
|
const name = parts[0];
|
|
const value = parts[1];
|
|
if (!/^[a-zA-Z_]+$/.test(name) || name.length === 0) {
|
|
err('Invalid Build Option Name: ' + name);
|
|
}
|
|
options.set(name, value);
|
|
} else if (arg === '--clean') {
|
|
// Remove Existing Build Directory
|
|
clean = true;
|
|
} else if (arg === '--install') {
|
|
// Install To System Instead Of Output Directory
|
|
if (packageType === PackageTypes.AppImage) {
|
|
err('AppImages Cannot Be Installed');
|
|
}
|
|
install = true;
|
|
} else if (arg === '--config') {
|
|
// Set Configuration
|
|
config = parseArg(process.argv[++argIndex], Configurations, 'Configuration');
|
|
} else {
|
|
// Invalid
|
|
err('Invalid Argument: ' + arg);
|
|
}
|
|
}
|
|
|
|
// Update Folders
|
|
function updateDir(dir) {
|
|
if (packageType !== PackageTypes.None) {
|
|
dir = path.join(dir, packageType.name);
|
|
}
|
|
return path.join(dir, architecture.name);
|
|
}
|
|
build = updateDir(build);
|
|
let cleanOut = false;
|
|
// AppImages Are Placed Directly In ./out
|
|
if (packageType !== PackageTypes.AppImage) {
|
|
cleanOut = true;
|
|
out = updateDir(out);
|
|
}
|
|
|
|
// Configure Build Options
|
|
function toCmakeBool(val) {
|
|
return val ? 'ON' : 'OFF';
|
|
}
|
|
options.set('MCPI_IS_APPIMAGE_BUILD', toCmakeBool(packageType === PackageTypes.AppImage));
|
|
options.set('MCPI_IS_FLATPAK_BUILD', toCmakeBool(packageType === PackageTypes.Flatpak));
|
|
if (architecture !== Architectures.Host) {
|
|
options.set('CMAKE_TOOLCHAIN_FILE', path.join(root, 'cmake', 'toolchain', architecture.name + '-toolchain.cmake'));
|
|
} else {
|
|
options.delete('CMAKE_TOOLCHAIN_FILE');
|
|
}
|
|
|
|
// Make Build Directory
|
|
function createDir(dir, clean) {
|
|
if (clean) {
|
|
fs.rmSync(dir, {recursive: true, force: true});
|
|
}
|
|
fs.mkdirSync(dir, {recursive: true});
|
|
}
|
|
createDir(build, clean);
|
|
if (!install) {
|
|
createDir(out, cleanOut);
|
|
}
|
|
|
|
// Run CMake
|
|
function run(command) {
|
|
try {
|
|
info('Running: ' + command.join(' '));
|
|
child_process.execFileSync(command[0], command.slice(1), {cwd: build, stdio: 'inherit'});
|
|
} catch (e) {
|
|
err(e);
|
|
}
|
|
}
|
|
const configure = ['cmake', '-GNinja Multi-Config'];
|
|
options.forEach((value, key, map) => {
|
|
configure.push(`-D${key}=${value}`);
|
|
});
|
|
configure.push(root);
|
|
run(configure);
|
|
|
|
// Build
|
|
const configArg = ['--config', config.prettyName];
|
|
run(['cmake', '--build', '.', ...configArg/*, '-v'/*, '--', '-n', '-j1', '-j1'*/]);
|
|
|
|
// Package
|
|
if (packageType !== PackageTypes.AppImage) {
|
|
if (!install) {
|
|
process.env.DESTDIR = out;
|
|
}
|
|
run(['cmake', '--install', '.', ...configArg]);
|
|
} else {
|
|
run(['cmake', '--build', '.', '--target', 'package', ...configArg]);
|
|
// Copy Generated Files
|
|
const files = fs.readdirSync(build);
|
|
for (const file of files) {
|
|
if (file.includes('.AppImage')) {
|
|
info('Copying: ' + file);
|
|
const src = path.join(build, file);
|
|
const dst = path.join(out, file);
|
|
fs.copyFileSync(src, dst);
|
|
}
|
|
}
|
|
}
|