docs/windows.md specified it; this is §9 steps 1, 2 and 4 run, and the report in §10. A Debian trixie image with rustup, the MinGW cross compiler, NSIS and Wine; a build.sh in the shape of the Android one; a package.sh that stages the executable and the seven models behind the same LFS-pointer guard every other packager carries, then runs makensis; and the .nsi itself — per-user, no elevation, an uninstaller that leaves the library alone. Measured: the executable links first time once the link flags were right, imports only Windows system DLLs, prints its version under Wine, and the installer installs and uninstalls silently under Wine with the registry key and the models where §5.2 says. What Wine cannot show is the Start Menu shortcut: CreateShortcut is IShellLink and does nothing headless. Four claims in the spec's first draft were wrong and are corrected in place with the reasoning kept: the whole-archive winpthread flag breaks the link and was never needed; build scripts need a host gcc; bookworm's Wine lacks the bcryptprimitives.dll rustc's std imports, so the image is trixie; and NSIS's default stub is 32-bit, so the installer says amd64-unicode and needs no i386 Wine.
Windows cross-build environment
Reproducible container for building the Windows executable and its installer from Linux. The specification is docs/windows.md; this directory is what it turned into, and every departure from the spec's first draft is recorded in the Dockerfile's comments.
Use
# Cross-compile the desktop application
./docker/windows/build.sh cargo build --release --target x86_64-pc-windows-gnu -p darkroom-desktop
# Lint the cfg(windows) branches, which the Linux job never sees
./docker/windows/build.sh cargo clippy --target x86_64-pc-windows-gnu -p darkroom-desktop -- -D warnings
# Build the installer from that binary
./docker/windows/build.sh docker/windows/package.sh
# Smoke-test under Wine (docs/windows.md §6)
./docker/windows/build.sh wine target-windows/x86_64-pc-windows-gnu/release/darkroom-desktop.exe --version
./docker/windows/build.sh wine target-windows/installer/DarkRoom-0.12.0-x86_64-setup.exe /S
# Interactive shell
./docker/windows/build.sh
# After editing the Dockerfile
./docker/windows/build.sh --rebuild
Prefers podman, falls back to docker. The cargo registry, the target directory and the Wine
prefix persist under ~/.cache/darkroom-windows/, so a warm rebuild is minutes and the first
wineboot happens once.
What is verified here, and what is not
Measured on the first build, 2026-09-12:
| Check | Result |
|---|---|
cargo build --target x86_64-pc-windows-gnu -p darkroom-desktop |
Links. 115 MB, PE32+ … (GUI) |
| DLL imports | 26 Windows system DLLs; no libwinpthread-1.dll, libgcc_s, libstdc++ |
wine darkroom-desktop.exe --version |
darkroom-desktop 0.12.0, exit 0, 0.1 s |
makensis |
105 MB DarkRoom-<version>-x86_64-setup.exe, 64-bit stub |
wine setup.exe /S |
Installs exe + 7 models to AppData\Local\Programs\DarkRoom, writes the HKCU uninstall key; the installed exe runs |
wine uninstall.exe /S |
Removes the directory and the key |
| Start Menu shortcut | Not verifiable here. CreateShortcut is IShellLink and does nothing under a headless Wine; the directory beside it is created. Check on Windows. |
None of this proves a Vulkan device opens, a render completes, fonts are found or the secret store round-trips. Those are a Windows machine, once per release — and today the secret store cannot round-trip, because its Windows implementation is still the loud placeholder (docs/windows.md §3.2).
In CI
Not yet wired. The image and the leg are specified in docs/windows.md §7 in the shape of the Android ones, and every step they would run has been exercised by hand above.