feat: add Docker build for Windows NSIS installer via Wine

- contrib/windows/Dockerfile: cross-compile using Wine + xvfb;
  installs Python 3.11 for Windows, builds cli.exe with PyInstaller,
  packages Electron app as NSIS installer
- contrib/windows/build.sh: convenience script to run the Docker build
- frontend/electron/main.cjs: resolve cli.exe on win32, cli on other platforms
- frontend/package.json: add win/nsis target; change extraResources to
  bundle resources/ dir so each platform picks its own binary
This commit is contained in:
2026-03-10 09:24:35 +01:00
parent 2c89a4cfd3
commit 301b7ef0ae
4 changed files with 71 additions and 2 deletions

View File

@@ -0,0 +1,47 @@
FROM node:22.14.0-bookworm
ENV WINEPREFIX=/root/.wine
ENV WINEDEBUG=-all
# System dependencies + Wine + Xvfb
RUN dpkg --add-architecture i386 && \
apt-get update && apt-get install -y --no-install-recommends \
wine wine64 \
python3 python3-pip python3-venv libpython3.11 \
binutils wget xvfb ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
# Copy repo
COPY . .
# Python venv (Linux, for local tools only)
RUN python3 -m venv venv && \
venv/bin/pip install --no-cache-dir -r requirements.txt
# Bootstrap Wine prefix
RUN wineboot --init 2>/dev/null || true
# Install Python for Windows under Wine (silent, no GUI)
RUN wget -q "https://www.python.org/ftp/python/3.11.9/python-3.11.9-amd64.exe" -O /tmp/py.exe && \
xvfb-run wine /tmp/py.exe /quiet InstallAllUsers=1 PrependPath=1 TargetDir="C:\\Python311" && \
rm /tmp/py.exe
# Install Python deps + PyInstaller under Wine Python
RUN xvfb-run wine "C:\\Python311\\python.exe" -m pip install --no-cache-dir -r requirements.txt pyinstaller
# Compile Python CLI into Windows binary
RUN xvfb-run wine "C:\\Python311\\python.exe" -m PyInstaller \
--onefile --name cli src/cli.py && \
mkdir -p frontend/resources && \
cp dist/cli.exe frontend/resources/cli.exe
# JS dependencies + electron-builder
RUN cd frontend && npm ci && npm install --no-save electron-builder
# Build Windows NSIS installer
RUN cd frontend && npx vite build && npx electron-builder --win nsis --publish never
# Export installer
CMD cp frontend/release/*.exe /out/

18
contrib/windows/build.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT=$(cd "$(dirname "$0")/../.." && pwd)
OUT_DIR="$REPO_ROOT/release"
mkdir -p "$OUT_DIR"
docker build -t wallet-gen-builder-win \
-f "$REPO_ROOT/contrib/windows/Dockerfile" \
"$REPO_ROOT"
docker run --rm \
-v "$OUT_DIR:/out" \
wallet-gen-builder-win
echo "Installer saved to: $OUT_DIR"
ls "$OUT_DIR"/*.exe

View File

@@ -51,7 +51,8 @@ function resolveWalletFile(kind, filename) {
// ── Resolve CLI command (dev: python + cli.py, prod: bundled binary) ──────────
function getCliCommand() {
if (!isDev) {
const bundled = path.join(process.resourcesPath, 'cli')
const cliName = process.platform === 'win32' ? 'cli.exe' : 'cli'
const bundled = path.join(process.resourcesPath, cliName)
if (fs.existsSync(bundled)) return { exec: bundled, baseArgs: [] }
}
const repoRoot = path.join(__dirname, '..', '..')

View File

@@ -17,7 +17,7 @@
"icon": "public/icons/icon.png",
"files": ["dist/**", "electron/**"],
"extraResources": [
{ "from": "resources/cli", "to": "cli" }
{ "from": "resources", "to": "." }
],
"directories": {
"output": "release"
@@ -25,6 +25,9 @@
"linux": {
"target": "AppImage",
"category": "Finance"
},
"win": {
"target": "nsis"
}
},
"dependencies": {