Files
jellytau/scripts/build-windows-cross.sh
T
dtourolle 2a3f08f8a4 build: hand containerised build artifacts back to the host user
The compose services bind-mount the repo and build as root, so every artifact
they leave in src-tauri/target belongs to root on the host. It accumulates:
11,124 such files had built up, enough that cargo clean and scripts/clean.sh
failed with EACCES — and a plain cargo build died part-way through, because
build scripts compile for the host and land in target/debug even when
cross-compiling to Android. That is what blocked the device build in this batch.

Restores ownership at the end of each containerised build, reading the intended
owner from the checkout so no uid has to be plumbed through from the host. A
no-op when not running as root, so the native build scripts call it
unconditionally.

Running the containers as the host uid is the tidier fix and stays open — it
needs the cargo/bun cache volumes moved off /root first, which is why this is
not a one-line user: directive.

TRACES: | DR-213
2026-08-20 20:17:36 +02:00

74 lines
3.2 KiB
Bash
Executable File

#!/bin/bash
# Cross-compile JellyTau for Windows from Linux, producing an NSIS installer.
#
# Uses the OFFICIAL Tauri cross-compile path (https://v2.tauri.app/distribute/
# windows-installer/): the MSVC target driven by cargo-xwin, which downloads the
# MSVC CRT/Windows SDK headers and links with lld. This is the target Tauri
# officially supports for Windows (the mingw/GNU target is not), and unlike GNU
# it can bundle the NSIS installer from a Linux host.
#
# Playback on Windows: video renders via WebView2 and audio via the webview
# <audio> backend (WebviewAudioBackend) — see docs/build/build-windows.md.
#
# Requirements (present in the Docker windows-cross target / unified builder):
# - rustup target x86_64-pc-windows-msvc
# - cargo-xwin (cargo install --locked cargo-xwin)
# - lld, llvm (linker + llvm-lib used by cargo-xwin)
# - nsis (makensis) (installer generator)
#
# Usage:
# scripts/build-windows-cross.sh # exe + NSIS installer
# WIN_BUNDLES=none scripts/build-windows-cross.sh # exe only, skip bundling
# OUTPUT_DIR=/app/dist scripts/build-windows-cross.sh
set -euo pipefail
cd "$(dirname "$0")/.."
TARGET="x86_64-pc-windows-msvc"
WIN_BUNDLES="${WIN_BUNDLES:-nsis}"
echo "🪟 Cross-compiling JellyTau for Windows ($TARGET, via cargo-xwin)"
echo "================================================================"
echo "Video plays via WebView2; audio via the webview <audio> backend."
echo "Bundles: $WIN_BUNDLES"
echo ""
bun install --frozen-lockfile 2>/dev/null || bun install
bun run build
# --runner cargo-xwin + the MSVC target is what makes the Tauri CLI treat this as
# a real Windows build and enable the nsis/msi bundlers on a Linux host.
#
# IMPORTANT: do NOT pass `--bundles nsis` here. tauri-cli 2.9.x validates the
# `--bundles` flag against a static clap enum gated by the HOST OS (Linux allows
# only deb/rpm/appimage) *before* it considers --target/--runner, so `--bundles
# nsis` is rejected at arg-parse time. Instead the Windows bundle targets come
# from tauri.conf.json (bundle.targets includes "nsis"), which is not subject to
# that CLI validation — the bundler then picks nsis once it knows the target is
# Windows.
if [[ "$WIN_BUNDLES" == "none" ]]; then
bun run tauri build --runner cargo-xwin --target "$TARGET" --no-bundle
else
bun run tauri build --runner cargo-xwin --target "$TARGET"
fi
BIN_DIR="src-tauri/target/$TARGET/release"
echo ""
echo "✅ Built Windows artifacts:"
find "$BIN_DIR" -maxdepth 1 -name '*.exe' -print
find "$BIN_DIR/bundle" -type f \( -name '*.exe' -o -name '*.msi' \) -print 2>/dev/null || true
if [[ -n "${OUTPUT_DIR:-}" ]]; then
mkdir -p "$OUTPUT_DIR"
find "$BIN_DIR" -maxdepth 1 -name 'jellytau.exe' -exec cp -v {} "$OUTPUT_DIR/" \;
# NSIS setup installers land in bundle/nsis/*-setup.exe; MSI in bundle/msi/*.msi.
find "$BIN_DIR/bundle" -type f \( -name '*-setup.exe' -o -name '*.msi' \) \
-exec cp -v {} "$OUTPUT_DIR/" \; 2>/dev/null || true
echo ""
echo "📦 Copied Windows artifacts to $OUTPUT_DIR"
fi
# Containerised builds run as root against a bind-mounted tree; hand the
# artifacts back to the host user. No-op when not root. See DR-213.
"$(dirname "$0")/restore-ownership.sh"