Add Windows cross-compilation via MinGW, and fix Docker build permission
build / build (push) Successful in 3m5s

issues on vboxsf-mounted checkouts

New `make dist-win`/`package-win` targets (folded into `dist`/`package`
alongside the renamed `dist-linux`/`package-linux`) cross-compile
systemshock.exe via MinGW, using prebuilt SDL2/SDL2_mixer/GLEW/
fluidsynth-lite baked into the build-image - no Windows machine or Wine
needed to build it, confirmed working and playable on a real Windows
machine. dist-win/ ships DLLs flat alongside the exe plus a new
res/run.bat launcher, packaged into a .zip the same way dist/ becomes a
.tar.gz.

Also fixes three build-image bugs hit while testing on a VirtualBox
vboxsf-mounted checkout: build-engine.sh/docker-entrypoint.sh losing
their execute bit (chmod +x on restrictive source perms), the container
user missing access to /workspace's supplementary vboxsf group, and
cp -a failing on symlink/hard-link creation (vboxsf doesn't support
either) - now falls back to dereferencing copies when detected. Also
adds Docker/zip/etc. prerequisites to the README for both the desktop
and Quest builds.
This commit is contained in:
2026-08-11 05:14:13 +02:00
parent 581af95e7b
commit a2fb95e57b
11 changed files with 457 additions and 47 deletions
+71 -14
View File
@@ -92,10 +92,30 @@ below.
## 4. Desktop build
Builds and runs Questshock natively on Linux (your dev machine, or any
Linux box) - useful for local development and testing without a VR
headset at all. For the VR-headset build, see "5. Android / Quest build"
below instead.
Builds and runs Questshock natively on the desktop (your dev machine, or
any Linux/Windows box) - useful for local development and testing
without a VR headset at all. For the VR-headset build, see "5. Android /
Quest build" below instead.
Two platforms: Linux (native) and Windows (x86_64, cross-compiled via
MinGW - see "4.2. Windows cross-build" below for how). `make dist`/`make
package` build **both** by default; use `make dist-linux`/`make
dist-win` (or `package-linux`/`package-win`) to build just one.
**Prerequisites:**
- **Docker** - `build-image.sh`/`run-image.sh` build and run the engine
build-image; no other build tool touches the host directly. The
Windows cross-toolchain (MinGW) is baked into the same build-image, so
building `dist-win` needs nothing extra beyond Docker itself.
- **`innoextract` and `unzip`** - optional, only needed by
`res/assets/extract_assets.sh` (see "3. Game assets" above) to unpack
the GOG installer locally; if either is missing, that script falls
back to running the extraction inside a throwaway Docker container
instead.
- **`zip`** - only needed on the host for `make package`/`package-win`
(the Windows release archive); `make dist`/`dist-win` and
`package-linux` don't need it.
```sh
# 1. Build the engine build-image (once, or after build-image/ changes)
@@ -104,11 +124,12 @@ below instead.
# 2. Get your own copy of the game data (see "3. Game assets" above), then:
res/assets/extract_assets.sh
# 3. Compile the engine and assemble dist/
# 3. Compile the engine and assemble dist/ (Linux) and dist-win/ (Windows)
make dist
# 4. Play
dist/run.sh
dist/run.sh # Linux
dist-win/run.bat # Windows (or systemshock.exe directly)
```
`make dist` always recompiles the engine from the current `engine/`
@@ -117,14 +138,38 @@ source (via `run-image.sh`), so a fresh build-image plus a re-run of
### 4.1. Packaging a distributable build
`make package` builds `dist/shockolate-<version>-linux-<arch>.tar.gz`: the
compiled binary, its runtime libraries, shaders, a default MIDI
soundfont, license information, and `res/GET_ASSETS.txt` in place of the
actual game data (which the tarball never includes). Version comes from
the current git tag (push a `vX.Y.Z` tag to drive a release); without one
it builds an untagged `0.0.0-dev+<sha>` placeholder. `make apk` (see
"5. Android / Quest build" below) is versioned identically, via the same
`build-image/version.sh`.
`make package` builds both `dist/shockolate-<version>-linux-<arch>.tar.gz`
and `dist/shockolate-<version>-windows-x86_64.zip`: the compiled
binary/DLLs, shaders, a default MIDI soundfont, license information, and
`res/GET_ASSETS.txt` in place of the actual game data (which neither
archive ever includes). Version comes from the current git tag (push a
`vX.Y.Z` tag to drive a release); without one it builds an untagged
`0.0.0-dev+<sha>` placeholder. `make apk` (see "5. Android / Quest build"
below) is versioned identically, via the same `build-image/version.sh`.
### 4.2. Windows cross-build
`make dist-win`/`make package-win` cross-compile a native Windows x86_64
build via MinGW (`x86_64-w64-mingw32-gcc`/`g++`, baked into the
build-image alongside the Linux toolchain - see
`build-image/build-engine-win.sh` and the "Windows cross-compile" section
of `build-image/Dockerfile`) - no Windows machine, Wine, or VM involved
in building it. `engine/CMakeLists.txt` already has working `WIN32`/
`MINGW` branches from Shockolate's own upstream Windows build (built
natively via Git Bash/MinGW on a real Windows machine - see
`engine/build_win64.sh`/`engine/appveyor.yml`), so unlike the Quest
build's `android/engine-patches/`, no source patching is needed here -
this cross-compiles those same branches offline and reproducibly, from
Linux, via Docker.
`dist-win/`/the packaged `.zip` ship `systemshock.exe` with its DLLs
(SDL2, SDL2_mixer, GLEW, fluidsynth-lite, plus the MinGW pthread runtime)
sitting flat alongside it, rather than in a `lib/` subdirectory like
`dist/` - Windows' default DLL search order already checks the
executable's own directory first, so no `PATH`/library-path setup is
needed the way `dist/run.sh` needs `LD_LIBRARY_PATH`.
Confirmed working (and playable) on a real Windows machine.
A Gitea Actions workflow (`.gitea/workflows/build.yml`) builds this
package on every push, using the build-image as its container (so no
@@ -133,6 +178,18 @@ resulting tarball to dl.ladkau.de.
## 5. Android / Quest build
**Prerequisites:**
- **Docker** - same build-image as the desktop build (see "4. Desktop
build" above), plus network access at build time for Gradle/AGP's own
dependency resolution (the one target that isn't fully offline).
- **SideQuest or `adb`** (Android Platform Tools) - to sideload the built
APK onto the headset, and to enable/verify USB debugging; see "5.1.
Installing and playing" below.
- Building/debugging natively in Android Studio instead of via `make
apk` needs its own separate toolchain - see "5.2. Building natively in
Android Studio" below.
`make apk` builds `dist/questshock-<version>-android-arm64.apk` - an
immersive OpenXR app (see `android/app/src/main/cpp/xr_session.c`) that
can be sideloaded onto any Android-based VR headset with OpenXR support