mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2026-06-11 03:49:23 +00:00
196 lines
5.5 KiB
JavaScript
196 lines
5.5 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Build/package Qortal Hub with a platform-native frozen Reticulum binary.
|
|
*
|
|
* Why this wrapper exists:
|
|
* - `rnsd` must be frozen on the same OS/arch as the packaged app.
|
|
* - Cross-packaging a Windows/macOS app from Linux would otherwise embed the wrong
|
|
* Reticulum binary and break end-user startup.
|
|
*
|
|
* Use the matching host OS for each target, or use the GitHub Actions matrix workflow.
|
|
*/
|
|
import { spawnSync } from 'child_process';
|
|
|
|
const mode = process.argv[2];
|
|
|
|
const configs = {
|
|
pack: {
|
|
description: 'current host unpacked app',
|
|
allowed: [{ platform: 'linux' }, { platform: 'darwin' }, { platform: 'win32' }],
|
|
builderArgs: ['build', '--dir', '-c', './electron-builder.config.json'],
|
|
},
|
|
local: {
|
|
description: 'current host packaged app',
|
|
allowed: [{ platform: 'linux' }, { platform: 'darwin' }, { platform: 'win32' }],
|
|
builderArgs: ['build', '-c', './electron-builder.config.json', '--publish=never'],
|
|
},
|
|
lin: {
|
|
description: 'Linux x64 package',
|
|
allowed: [{ platform: 'linux', arch: 'x64' }],
|
|
builderArgs: ['build', '-c', './electron-builder.config.lin.json', '--publish=never', '-l'],
|
|
},
|
|
arm: {
|
|
description: 'Linux arm64 package',
|
|
allowed: [{ platform: 'linux', arch: 'arm64' }],
|
|
builderArgs: [
|
|
'build',
|
|
'-c',
|
|
'./electron-builder.config.arm.json',
|
|
'--publish=never',
|
|
'--linux',
|
|
'--arm64',
|
|
],
|
|
},
|
|
win: {
|
|
description: 'Windows package',
|
|
allowed: [{ platform: 'win32' }],
|
|
builderArgs: ['build', '-c', './electron-builder.config.win.json', '--publish=never', '-w'],
|
|
},
|
|
mac: {
|
|
description: 'macOS package',
|
|
allowed: [{ platform: 'darwin' }],
|
|
builderArgs: [
|
|
'build',
|
|
'-c',
|
|
'./electron-builder.config.mac.json',
|
|
'--publish=never',
|
|
'--mac',
|
|
'dmg',
|
|
'pkg',
|
|
'zip',
|
|
],
|
|
},
|
|
'mac-universal': {
|
|
description: 'macOS universal package',
|
|
allowed: [{ platform: 'darwin' }],
|
|
universal: true,
|
|
builderArgs: [
|
|
'build',
|
|
'-c',
|
|
'./electron-builder.config.mac.json',
|
|
'--publish=never',
|
|
'--mac',
|
|
'dmg',
|
|
'pkg',
|
|
'zip',
|
|
'--universal',
|
|
],
|
|
},
|
|
'mac-universal-unsigned': {
|
|
description: 'unsigned macOS universal package',
|
|
allowed: [{ platform: 'darwin' }],
|
|
universal: true,
|
|
builderEnv: {
|
|
CSC_IDENTITY_AUTO_DISCOVERY: 'false',
|
|
},
|
|
builderArgs: [
|
|
'build',
|
|
'-c',
|
|
'./electron-builder.config.mac-unsigned.json',
|
|
'--publish=never',
|
|
'--mac',
|
|
'dmg',
|
|
'pkg',
|
|
'zip',
|
|
'--universal',
|
|
],
|
|
},
|
|
};
|
|
|
|
function fail(message) {
|
|
console.error(message);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (!mode || mode === 'all') {
|
|
fail(
|
|
[
|
|
'Cross-platform packaging is no longer safe through a single local command,',
|
|
'because Reticulum must be bundled as a native binary per OS/arch.',
|
|
'',
|
|
'Use one of:',
|
|
' npm run electron:make-lin # on Linux x64',
|
|
' npm run electron:make-arm # on Linux arm64',
|
|
' npm run electron:make-win # on Windows',
|
|
' npm run electron:make-mac # on macOS',
|
|
' npm run electron:make-mac-universal # on macOS, universal app',
|
|
' npm run electron:make-mac-universal-unsigned # on macOS, unsigned universal app',
|
|
'',
|
|
'Or use the GitHub Actions workflow to build the supported OS matrix.',
|
|
].join('\n')
|
|
);
|
|
}
|
|
|
|
const cfg = configs[mode];
|
|
if (!cfg) {
|
|
fail(`Unknown packaging mode: ${mode}`);
|
|
}
|
|
|
|
const supportedHere = cfg.allowed.some(
|
|
(rule) =>
|
|
process.platform === rule.platform &&
|
|
(rule.arch == null || process.arch === rule.arch)
|
|
);
|
|
|
|
if (!supportedHere) {
|
|
const here = `${process.platform}-${process.arch}`;
|
|
const expected = cfg.allowed
|
|
.map((rule) => `${rule.platform}${rule.arch ? `-${rule.arch}` : ''}`)
|
|
.join(' or ');
|
|
fail(
|
|
`Cannot build ${cfg.description} from ${here}. Build it on ${expected}, so the bundled Reticulum binary matches the packaged app.`
|
|
);
|
|
}
|
|
|
|
function run(cmd, args) {
|
|
// Windows: npm.cmd / electron-builder.cmd are cmd shims; spawn without a shell can
|
|
// fail with EINVAL. Running through the default shell matches how npm invokes scripts.
|
|
const res = spawnSync(cmd, args, {
|
|
stdio: 'inherit',
|
|
env: process.env,
|
|
windowsHide: true,
|
|
...(process.platform === 'win32' ? { shell: true } : {}),
|
|
});
|
|
if (res.error) {
|
|
console.error(`Failed to run ${cmd}:`, res.error.message);
|
|
process.exit(1);
|
|
}
|
|
if (res.status !== 0) {
|
|
process.exit(res.status ?? 1);
|
|
}
|
|
}
|
|
|
|
function runWithEnv(cmd, args, envExtra) {
|
|
const res = spawnSync(cmd, args, {
|
|
stdio: 'inherit',
|
|
env: { ...process.env, ...envExtra },
|
|
windowsHide: true,
|
|
...(process.platform === 'win32' ? { shell: true } : {}),
|
|
});
|
|
if (res.error) {
|
|
console.error(`Failed to run ${cmd}:`, res.error.message);
|
|
process.exit(1);
|
|
}
|
|
if (res.status !== 0) {
|
|
process.exit(res.status ?? 1);
|
|
}
|
|
}
|
|
|
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
|
|
run(npmCmd, ['run', 'build']);
|
|
if (cfg.universal) {
|
|
runWithEnv(npmCmd, ['run', 'bundle:reticulum'], {
|
|
QORTAL_RETICULUM_OUTPUT_DIR: 'resources/reticulum/darwin-arm64',
|
|
});
|
|
runWithEnv(npmCmd, ['run', 'bundle:reticulum'], {
|
|
QORTAL_RETICULUM_BUILD_ARCH: 'x64',
|
|
QORTAL_RETICULUM_OUTPUT_DIR: 'resources/reticulum/darwin-x64',
|
|
});
|
|
} else {
|
|
run(npmCmd, ['run', 'bundle:reticulum']);
|
|
}
|
|
|
|
const electronBuilderCmd = process.platform === 'win32' ? 'electron-builder.cmd' : 'electron-builder';
|
|
runWithEnv(electronBuilderCmd, cfg.builderArgs, cfg.builderEnv ?? {});
|