Files
dtourolle d8f26fb5cd Ship the manual with the Arch package, the Windows installer and the APK
The rendered manual was in the repository and nowhere else, so an
installed application still had nothing to open.

Each packager now carries docs/manual/index.html and its pictures, to
where the application will look for them: /usr/share/darkroom/manual on
Arch, manual\ beside darkroom.exe on Windows (where the models already
are, and where dr_plat::system_data_dirs points), and assets/manual in
the APK, stored rather than deflated since a GIF or PNG is already
compressed. The manual is about 27 MB, which the APK and the installer
both grow by; the pictures are 1600x1100 screenshots and short GIFs,
and against an APK that already carries 170 MB of inference runtime and
70 MB of models they are not worth re-encoding for.

The pictures are LFS objects, so each packager refuses a pointer where a
picture should be, as it already does for the models: shipped, a pointer
is a manual of broken images that nothing reports. The Android and
Windows CI legs therefore fetch docs/manual/media, which they excluded
while nothing they built read it, and the installer smoke test checks
that the page and every picture were installed.
2026-09-24 22:33:41 -04:00
..

Windows cross-build environment

Reproducible container for building the Windows executable and its installer from Linux. The specification is docs/dev/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/dev/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 + 10 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.

Also checked by running the application itself under Wine: its log lands in AppData\Local\darkroom\state, and nothing is written outside AppData (FR-PLAT-WIN-1).

None of this proves a Vulkan device opens, a render completes, fonts are found, the secret store round-trips or the browser opens for sign-in. Those are a Windows machine, once per release.

In CI

.gitea/workflows/windows-image.yml builds this image and pushes it to gitea.tourolle.paris/dtourolle/darkroom-windows, exactly as the Android image is handled — tagged by the tree hash of docker/windows/, rebuilt when and only when a file here changes. The windows job in build-and-test.yml then runs, inside it, the same commands listed above plus cargo clippy --target x86_64-pc-windows-gnu -- -D warnings, and uploads the installer as an artefact.