Add Windows ARM64 packaging support
This commit is contained in:
@@ -60,6 +60,8 @@ npm run build # TypeScript + Vite production build
|
|||||||
npm run desktop # Run Electron against the built dist/
|
npm run desktop # Run Electron against the built dist/
|
||||||
npm run dist:dir # Build an unpacked Electron app in release/
|
npm run dist:dir # Build an unpacked Electron app in release/
|
||||||
npm run dist:mac # Build macOS .dmg and .zip packages in release/
|
npm run dist:mac # Build macOS .dmg and .zip packages in release/
|
||||||
|
npm run dist:win # Build Windows installer + zip for the current Windows architecture
|
||||||
|
npm run dist:win:arm64 # Build Windows ARM64 installer + zip in release/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Production-Like Local Run
|
## Production-Like Local Run
|
||||||
@@ -129,10 +131,12 @@ Current packaging commands:
|
|||||||
|
|
||||||
- `npm run dist:dir` creates an unpacked app bundle in `release/`
|
- `npm run dist:dir` creates an unpacked app bundle in `release/`
|
||||||
- `npm run dist:mac` creates macOS `.dmg` and `.zip` artifacts in `release/`
|
- `npm run dist:mac` creates macOS `.dmg` and `.zip` artifacts in `release/`
|
||||||
|
- `npm run dist:win` creates Windows `.exe` and `.zip` artifacts for the current Windows architecture
|
||||||
|
- `npm run dist:win:arm64` creates Windows ARM64 `.exe` and `.zip` artifacts in `release/`
|
||||||
|
|
||||||
The current mac build is unsigned and not notarized, which is fine for local use and testing but not enough for friction-free public distribution through Gatekeeper.
|
The current mac build is unsigned and not notarized, which is fine for local use and testing but not enough for friction-free public distribution through Gatekeeper.
|
||||||
|
|
||||||
Windows and Linux targets are also configured in `package.json`, but they have not been validated in this repository yet.
|
Windows ARM64 packaging has been validated in this repository with Electron Builder on Windows 11 ARM running under Parallels. Linux targets are still configured in `package.json`, but they have not been validated here yet.
|
||||||
|
|
||||||
## Legacy Tauri Script
|
## Legacy Tauri Script
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,14 @@
|
|||||||
"dev:renderer": "vite",
|
"dev:renderer": "vite",
|
||||||
"dev:electron": "wait-on tcp:1420 && cross-env ELECTRON_RENDERER_URL=http://localhost:1420 electron .",
|
"dev:electron": "wait-on tcp:1420 && cross-env ELECTRON_RENDERER_URL=http://localhost:1420 electron .",
|
||||||
"dev:desktop": "concurrently -k \"npm:dev:renderer\" \"npm:dev:electron\"",
|
"dev:desktop": "concurrently -k \"npm:dev:renderer\" \"npm:dev:electron\"",
|
||||||
|
"gen:win-icon": "node scripts/generate-win-icon.mjs",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"desktop": "electron .",
|
"desktop": "electron .",
|
||||||
"dist:dir": "npm run build && electron-builder --dir",
|
"dist:dir": "npm run build && electron-builder --dir",
|
||||||
"dist:mac": "npm run build && electron-builder --mac dmg zip",
|
"dist:mac": "npm run build && electron-builder --mac dmg zip",
|
||||||
"dist:linux": "npm run build && electron-builder --linux AppImage deb",
|
"dist:linux": "npm run build && electron-builder --linux AppImage deb",
|
||||||
|
"dist:win": "npm run gen:win-icon && npm run build && electron-builder --win nsis zip",
|
||||||
|
"dist:win:arm64": "npm run gen:win-icon && npm run build && electron-builder --win nsis zip --arm64",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"tauri": "tauri"
|
"tauri": "tauri"
|
||||||
},
|
},
|
||||||
|
|||||||
46
scripts/generate-win-icon.mjs
Normal file
46
scripts/generate-win-icon.mjs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
const projectRoot = path.resolve(__dirname, "..");
|
||||||
|
|
||||||
|
const sourcePngPath = path.join(projectRoot, "src-tauri", "icons", "128x128@2x.png");
|
||||||
|
const targetIcoPath = path.join(projectRoot, "src-tauri", "icons", "icon.ico");
|
||||||
|
|
||||||
|
const pngBytes = fs.readFileSync(sourcePngPath);
|
||||||
|
|
||||||
|
if (pngBytes.length < 24 || pngBytes.toString("ascii", 1, 4) !== "PNG") {
|
||||||
|
throw new Error(`Expected a PNG file at ${sourcePngPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = pngBytes.readUInt32BE(16);
|
||||||
|
const height = pngBytes.readUInt32BE(20);
|
||||||
|
|
||||||
|
if (width !== 256 || height !== 256) {
|
||||||
|
throw new Error(`Expected a 256x256 PNG, received ${width}x${height}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerSize = 6;
|
||||||
|
const directoryEntrySize = 16;
|
||||||
|
const imageOffset = headerSize + directoryEntrySize;
|
||||||
|
const icoBytes = Buffer.alloc(imageOffset + pngBytes.length);
|
||||||
|
|
||||||
|
icoBytes.writeUInt16LE(0, 0);
|
||||||
|
icoBytes.writeUInt16LE(1, 2);
|
||||||
|
icoBytes.writeUInt16LE(1, 4);
|
||||||
|
|
||||||
|
icoBytes.writeUInt8(0, 6);
|
||||||
|
icoBytes.writeUInt8(0, 7);
|
||||||
|
icoBytes.writeUInt8(0, 8);
|
||||||
|
icoBytes.writeUInt8(0, 9);
|
||||||
|
icoBytes.writeUInt16LE(1, 10);
|
||||||
|
icoBytes.writeUInt16LE(32, 12);
|
||||||
|
icoBytes.writeUInt32LE(pngBytes.length, 14);
|
||||||
|
icoBytes.writeUInt32LE(imageOffset, 18);
|
||||||
|
|
||||||
|
pngBytes.copy(icoBytes, imageOffset);
|
||||||
|
|
||||||
|
fs.writeFileSync(targetIcoPath, icoBytes);
|
||||||
|
console.log(`Generated ${path.relative(projectRoot, targetIcoPath)} from ${path.relative(projectRoot, sourcePngPath)}`);
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 9.1 KiB |
Reference in New Issue
Block a user