2024-02-03 21:07:53 -05:00
|
|
|
#!/usr/bin/env node
|
|
|
|
import * as path from 'node:path';
|
|
|
|
import * as fs from 'node:fs';
|
2025-01-03 10:20:33 -05:00
|
|
|
import { info, err, run, createDir, getScriptsDir } from './lib/util.mjs';
|
2025-01-03 08:25:09 -05:00
|
|
|
import { parseOptions, Enum, Architectures } from './lib/options.mjs';
|
2024-02-03 21:07:53 -05:00
|
|
|
|
2025-01-03 08:25:09 -05:00
|
|
|
// CMake Options
|
|
|
|
const cmakeArgPrefix = '-D';
|
|
|
|
const cmakeArgSeparator = '=';
|
|
|
|
const cmakeOptions = new Map();
|
|
|
|
function parseCMakeOption(arg) {
|
|
|
|
if (arg === null) {
|
|
|
|
// Usage Text
|
|
|
|
return `${cmakeArgPrefix}var${cmakeArgSeparator}value...`;
|
|
|
|
} else if (arg.startsWith(cmakeArgPrefix)) {
|
2024-02-03 21:07:53 -05:00
|
|
|
// Pass Build Option To CMake
|
2024-12-22 03:34:31 -05:00
|
|
|
let parsedArg = arg.substring(cmakeArgPrefix.length);
|
2025-01-03 08:25:09 -05:00
|
|
|
const parts = parsedArg.split(cmakeArgSeparator);
|
2024-12-22 03:34:31 -05:00
|
|
|
if (parts.length !== 2) {
|
2024-02-03 21:07:53 -05:00
|
|
|
err('Unable To Parse Build Option: ' + arg);
|
|
|
|
}
|
2024-12-22 03:34:31 -05:00
|
|
|
const name = parts[0];
|
|
|
|
const value = parts[1];
|
2024-02-03 21:07:53 -05:00
|
|
|
if (!/^[a-zA-Z_]+$/.test(name) || name.length === 0) {
|
|
|
|
err('Invalid Build Option Name: ' + name);
|
|
|
|
}
|
2025-01-03 08:25:09 -05:00
|
|
|
cmakeOptions.set(name, value);
|
|
|
|
return true;
|
2024-02-03 21:07:53 -05:00
|
|
|
} else {
|
2025-01-03 08:25:09 -05:00
|
|
|
// Unknown Option
|
|
|
|
return false;
|
2024-02-03 21:07:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-01-03 08:25:09 -05:00
|
|
|
// Options
|
2025-01-03 10:20:33 -05:00
|
|
|
const PackageTypes = new Enum([
|
|
|
|
'None',
|
|
|
|
'AppImage',
|
|
|
|
'Flatpak'
|
|
|
|
]);
|
2025-01-03 08:25:09 -05:00
|
|
|
const options = parseOptions([
|
|
|
|
['packageType', PackageTypes],
|
|
|
|
['architecture', Architectures]
|
|
|
|
], [
|
|
|
|
'clean',
|
|
|
|
'install',
|
|
|
|
'debug'
|
|
|
|
], parseCMakeOption);
|
|
|
|
|
|
|
|
// Check Options
|
|
|
|
if (options.packageType === PackageTypes.Flatpak && options.architecture !== Architectures.Host) {
|
|
|
|
err('Flatpak Builds Do Not Support Custom Toolchains');
|
2024-02-03 21:07:53 -05:00
|
|
|
}
|
2025-01-03 08:25:09 -05:00
|
|
|
if (options.packageType === PackageTypes.AppImage && options.install) {
|
|
|
|
err('AppImages Cannot Be Installed');
|
2024-02-04 00:36:58 -05:00
|
|
|
}
|
2024-02-03 21:07:53 -05:00
|
|
|
|
2025-01-03 08:25:09 -05:00
|
|
|
// Folders
|
2025-01-03 10:20:33 -05:00
|
|
|
const __dirname = getScriptsDir();
|
2025-01-03 08:25:09 -05:00
|
|
|
const root = path.join(__dirname, '..');
|
|
|
|
let build = path.join(root, 'build');
|
|
|
|
let out = path.join(root, 'out');
|
|
|
|
|
|
|
|
// Update Build Directory
|
|
|
|
function specializeDir(dir) {
|
|
|
|
// Use Unique Folder For Build Type
|
|
|
|
return path.join(dir, options.packageType.name, options.architecture.name);
|
|
|
|
}
|
|
|
|
build = specializeDir(build);
|
|
|
|
// Update Output Directory
|
|
|
|
const useOutRoot = options.packageType === PackageTypes.AppImage;
|
|
|
|
if (!useOutRoot) {
|
|
|
|
out = specializeDir(out);
|
|
|
|
}
|
|
|
|
// Print Directories
|
|
|
|
function printDir(name, dir) {
|
|
|
|
info(name + ' Directory: ' + dir);
|
|
|
|
}
|
|
|
|
printDir('Build', build);
|
|
|
|
printDir('Output', out);
|
|
|
|
|
|
|
|
// Configure CMake Options
|
|
|
|
function setupPackageTypeOption(type) {
|
|
|
|
cmakeOptions.set(`MCPI_IS_${type.name.toUpperCase()}_BUILD`, options.packageType === type ? 'ON' : 'OFF');
|
|
|
|
}
|
|
|
|
setupPackageTypeOption(PackageTypes.AppImage);
|
|
|
|
setupPackageTypeOption(PackageTypes.Flatpak);
|
|
|
|
const toolchainOption = 'CMAKE_TOOLCHAIN_FILE';
|
|
|
|
if (options.architecture !== Architectures.Host) {
|
|
|
|
cmakeOptions.set(toolchainOption, path.join(root, 'cmake', 'toolchain', options.architecture.name + '-toolchain.cmake'));
|
2024-02-03 21:07:53 -05:00
|
|
|
} else {
|
2025-01-03 08:25:09 -05:00
|
|
|
cmakeOptions.delete(toolchainOption);
|
2024-02-03 21:07:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make Build Directory
|
2025-01-03 08:25:09 -05:00
|
|
|
createDir(build, options.clean);
|
|
|
|
if (!options.install) {
|
|
|
|
createDir(out, !useOutRoot);
|
2024-02-03 21:07:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Run CMake
|
2024-12-22 03:34:31 -05:00
|
|
|
const configure = ['cmake', '-GNinja Multi-Config'];
|
2025-01-03 08:25:09 -05:00
|
|
|
cmakeOptions.forEach((value, key) => {
|
|
|
|
configure.push(cmakeArgPrefix + key + cmakeArgSeparator + value);
|
2024-02-04 01:31:41 -05:00
|
|
|
});
|
2025-01-03 08:25:09 -05:00
|
|
|
configure.push('-S', root, '-B', build);
|
2024-12-22 03:34:31 -05:00
|
|
|
run(configure);
|
2024-02-03 21:07:53 -05:00
|
|
|
|
|
|
|
// Build
|
2025-01-03 08:25:09 -05:00
|
|
|
const configArg = ['--config', options.debug ? 'Debug' : 'Release'];
|
|
|
|
run(['cmake', '--build', build, ...configArg]);
|
2024-02-03 21:07:53 -05:00
|
|
|
|
|
|
|
// Package
|
2025-01-03 08:25:09 -05:00
|
|
|
if (options.packageType !== PackageTypes.AppImage) {
|
|
|
|
if (!options.install) {
|
2024-02-03 21:07:53 -05:00
|
|
|
process.env.DESTDIR = out;
|
|
|
|
}
|
2025-01-03 08:25:09 -05:00
|
|
|
run(['cmake', '--install', build, ...configArg]);
|
2024-02-03 21:07:53 -05:00
|
|
|
} else {
|
2025-01-03 08:25:09 -05:00
|
|
|
run(['cmake', '--build', build, '--target', 'package', ...configArg]);
|
2024-02-04 00:36:58 -05:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
2024-02-03 21:07:53 -05:00
|
|
|
}
|