build-windows.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/env node
  2. /**
  3. * Build a Windows-only embedded Neutralino executable.
  4. *
  5. * `neu build --embed-resources` embeds every platform binary it finds in bin/.
  6. * With this app's offline libraries, embedding all platforms can exhaust Node's
  7. * heap before the Windows binary is reached, leaving a stale Windows EXE in
  8. * dist/. Temporarily hiding non-Windows binaries makes the CLI embed only the
  9. * target users actually run on Windows.
  10. */
  11. const fs = require("fs");
  12. const path = require("path");
  13. const { spawnSync } = require("child_process");
  14. const APP_DIR = __dirname;
  15. const BIN_DIR = path.join(APP_DIR, "bin");
  16. const CONFIG_FILE = path.join(APP_DIR, "neutralino.config.json");
  17. const WIN_BINARY = "neutralino-win_x64.exe";
  18. const NEU_CLI = "@neutralinojs/neu@11.7.0";
  19. function getArgValue(name) {
  20. const prefix = `${name}=`;
  21. for (let i = 2; i < process.argv.length; i += 1) {
  22. const arg = process.argv[i];
  23. if (arg === name) return process.argv[i + 1] || "";
  24. if (arg.startsWith(prefix)) return arg.slice(prefix.length);
  25. }
  26. return "";
  27. }
  28. function createConfigOverride(distributionPath) {
  29. if (!distributionPath) return CONFIG_FILE;
  30. const config = JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
  31. config.cli = config.cli || {};
  32. config.cli.distributionPath = distributionPath.replace(/\\/g, "/");
  33. const tmpDir = path.join(APP_DIR, ".tmp");
  34. fs.mkdirSync(tmpDir, { recursive: true });
  35. const tempConfigFile = path.join(tmpDir, `neutralino.windows.${process.pid}.config.json`);
  36. fs.writeFileSync(tempConfigFile, `${JSON.stringify(config, null, 2)}\n`, "utf-8");
  37. return tempConfigFile;
  38. }
  39. function hideNonWindowsBinaries(tempDir) {
  40. const hidden = [];
  41. fs.mkdirSync(tempDir, { recursive: true });
  42. for (const entry of fs.readdirSync(BIN_DIR, { withFileTypes: true })) {
  43. if (!entry.isFile()) continue;
  44. if (!entry.name.startsWith("neutralino-")) continue;
  45. if (entry.name === WIN_BINARY) continue;
  46. const from = path.join(BIN_DIR, entry.name);
  47. const to = path.join(tempDir, entry.name);
  48. fs.renameSync(from, to);
  49. hidden.push({ from, to });
  50. }
  51. return hidden;
  52. }
  53. function restoreHiddenBinaries(hidden) {
  54. for (let i = hidden.length - 1; i >= 0; i -= 1) {
  55. const item = hidden[i];
  56. if (fs.existsSync(item.to)) {
  57. fs.renameSync(item.to, item.from);
  58. }
  59. }
  60. }
  61. function main() {
  62. const windowsBinaryPath = path.join(BIN_DIR, WIN_BINARY);
  63. if (!fs.existsSync(windowsBinaryPath)) {
  64. console.error(`Missing ${WIN_BINARY}. Run npm run setup before building.`);
  65. process.exit(1);
  66. }
  67. const distributionPath = getArgValue("--dist");
  68. const tempDir = path.join(BIN_DIR, `.nonwin-disabled-${process.pid}`);
  69. const configFile = createConfigOverride(distributionPath);
  70. const hidden = hideNonWindowsBinaries(tempDir);
  71. let exitCode = 0;
  72. try {
  73. const npx = "npx";
  74. const args = [
  75. "-y",
  76. NEU_CLI,
  77. "build",
  78. "--embed-resources",
  79. "--clean",
  80. "--config-file",
  81. configFile,
  82. ];
  83. const result = spawnSync(npx, args, {
  84. cwd: APP_DIR,
  85. stdio: "inherit",
  86. env: process.env,
  87. shell: process.platform === "win32",
  88. });
  89. if (result.error) {
  90. console.error(result.error.message);
  91. exitCode = 1;
  92. } else {
  93. exitCode = result.status || 0;
  94. }
  95. } finally {
  96. restoreHiddenBinaries(hidden);
  97. fs.rmSync(tempDir, { recursive: true, force: true });
  98. if (configFile !== CONFIG_FILE) {
  99. fs.rmSync(configFile, { force: true });
  100. }
  101. }
  102. process.exit(exitCode);
  103. }
  104. main();