#!/usr/bin/env bash # Cross-compiles engine/ (the vendored Shockolate snapshot) for Windows # (x86_64) via MinGW, against the dependencies prebuilt into this image at # /opt/prebuilt/win - no network access needed. engine/CMakeLists.txt # already has working WIN32/MINGW branches (the upstream Shockolate # project's own build_win64.sh/appveyor.yml build the same way, natively # on Windows via Git Bash/MinGW; this cross-compiles the same branches # fully offline and reproducibly from Linux instead), so no source # patching is needed, unlike the Quest build's android/engine-patches/. # # Builds from a scratch copy of engine/ (like android/engine-patches/ # does for the Quest build) rather than engine/ itself: its BUNDLED # dependency paths (build_ext/built_sdl etc.) and in-source CMake cache # are relative to/inside the source tree, and would otherwise collide # with the Linux desktop build's own build_ext/CMakeCache.txt (see # build-engine.sh) if both are built from the same checkout, as `make # dist` (dist-linux + dist-win) does. # # Must be run with the repo root as the working directory - either via # ../run-image.sh, or directly when already inside this image (see the # Makefile's `engine-win` target, which picks whichever of these # applies, same as `engine`). # # Output lands in engine/.build-output-win/: systemshock.exe, the DLLs # it needs at runtime, and a default MIDI soundfont - everything the # root Makefile needs to assemble dist-win/. set -euo pipefail REPO_ROOT="$(pwd)" SCRATCH_ENGINE="$REPO_ROOT/build/win-engine" OUT_DIR="$REPO_ROOT/engine/.build-output-win" echo "== Preparing a scratch copy of engine/ for the Windows cross-build ==" rm -rf "$SCRATCH_ENGINE" mkdir -p "$(dirname "$SCRATCH_ENGINE")" # See build-engine.sh for why this detection is needed (e.g. a VirtualBox # vboxsf shared folder refusing to create symlinks or preserve hard-link # relationships) - applied here too since build/ is under the same # bind-mounted repo checkout. CP_FLAGS=(-a) mkdir -p "$(dirname "$SCRATCH_ENGINE")/.symlink-test-dir" if ! ln -s test-target "$(dirname "$SCRATCH_ENGINE")/.symlink-test-dir/test" 2>/dev/null; then echo "(destination filesystem doesn't support symlinks - copying real file content instead)" CP_FLAGS=(-a --dereference --no-preserve=links) fi rm -rf "$(dirname "$SCRATCH_ENGINE")/.symlink-test-dir" cp "${CP_FLAGS[@]}" "$REPO_ROOT/engine" "$SCRATCH_ENGINE" cd "$SCRATCH_ENGINE" # If engine/ has ever been built in-source directly (`make dist`/`make # engine` - see build-engine.sh), that leftover CMakeCache.txt etc. just # got copied along verbatim - and it still points at the real engine/ # path, not this scratch copy, which CMake refuses to configure against # ("directory is different than the directory where CMakeCache.txt was # created"). Same artifact list as .gitignore's "Engine build artifacts" # section. rm -rf build_ext CMakeCache.txt CMakeFiles cmake_install.cmake Makefile \ systemshock src/Libraries/CMakeFiles echo "== Wiring up prebuilt SDL2/SDL2_mixer/GLEW/fluidsynth-lite (Windows/MinGW) from the image ==" rm -rf build_ext mkdir -p build_ext cp "${CP_FLAGS[@]}" /opt/prebuilt/win/sdl2 build_ext/built_sdl cp "${CP_FLAGS[@]}" /opt/prebuilt/win/sdl2_mixer build_ext/built_sdl_mixer cp "${CP_FLAGS[@]}" /opt/prebuilt/win/glew build_ext/built_glew # engine/CMakeLists.txt's BUNDLED FluidSynth mode hardcodes # build_ext/fluidsynth-lite/src as the library search path (matching the # desktop Linux in-source build's own output layout) - same lib/ -> src/ # remapping build-image/prepare-android-project.sh does for the Quest # build's own prebuilt fluidsynth-lite. mkdir -p build_ext/fluidsynth-lite/src build_ext/fluidsynth-lite/include cp "${CP_FLAGS[@]}" /opt/prebuilt/win/fluidsynth-lite/lib/. build_ext/fluidsynth-lite/src/ cp "${CP_FLAGS[@]}" /opt/prebuilt/win/fluidsynth-lite/include/. build_ext/fluidsynth-lite/include/ echo "== Configuring (CMake, MinGW cross-compile, BUNDLED SDL2/SDL2_mixer/FluidSynth) ==" cmake -DCMAKE_TOOLCHAIN_FILE="$MINGW_TOOLCHAIN_FILE" \ -DENABLE_SDL2=BUNDLED -DENABLE_SOUND=BUNDLED -DENABLE_FLUIDSYNTH=BUNDLED . echo "== Compiling ==" make -j"$(nproc)" systemshock echo "== Assembling engine/.build-output-win ==" rm -rf "$OUT_DIR" mkdir -p "$OUT_DIR" cp systemshock.exe "$OUT_DIR/" # Only SDL2.dll/SDL2_mixer.dll themselves - not SDL2_mixer's own bundled # codec DLLs (libvorbis, libmodplug, libopus, ...), matching what # engine/'s own upstream Windows build script (build_win64.sh) ships: # Shockolate only ever calls Mix_LoadWAV_RW/Mix_HookMusic (same as the # Quest build - see build-image/Dockerfile's Android layer comment), # never loading the OGG/MOD/MP3 game data those codecs would be for. cp build_ext/built_sdl/bin/SDL2.dll build_ext/built_sdl_mixer/bin/SDL2_mixer.dll "$OUT_DIR/" cp build_ext/built_glew/lib/glew32.dll "$OUT_DIR/" cp build_ext/fluidsynth-lite/src/*.dll "$OUT_DIR/" # libgcc/libstdc++ are statically linked (see the Dockerfile's # MINGW_TOOLCHAIN_FILE), but fluidsynth-lite/SDL2 still pull in the # MinGW pthread emulation dynamically. cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll "$OUT_DIR/" cp /opt/prebuilt/soundfont/default.sf2 "$OUT_DIR/soundfont.sf2" echo "== Done ==" echo "Binary: $OUT_DIR/systemshock.exe" echo "DLLs: $OUT_DIR/*.dll" echo "Soundfont: $OUT_DIR/soundfont.sf2"