Replace the single Ubuntu-based container build with a dedicated Dockerfile, build script, and launcher for each target platform. Infrastructure: - Add .dockerignore to minimize Docker build context - Add container/builder-linux.Dockerfile (Ubuntu 24.04, GCC, native build) - Add container/builder-macos.Dockerfile (multi-stage: SDK fetcher + osxcross/Clang 18) - Add container/builder-windows.Dockerfile (LLVM-MinGW 20240619, vcpkg) - Add container/macos/sdk-fetcher.py (auto-fetch macOS SDK from Apple catalog) - Add container/macos/osxcross-toolchain.cmake (auto-detecting CMake toolchain) - Add container/macos/triplets/arm64-osx-cross.cmake - Add container/macos/triplets/x64-osx-cross.cmake - Remove container/builder-ubuntu.Dockerfile (replaced by per-platform Dockerfiles) - Remove container/build-in-container.sh and container/build-wowee.sh (replaced) Build scripts (run inside containers): - Add container/build-linux.sh (tar copy, FidelityFX clone, cmake/ninja) - Add container/build-macos.sh (arch detection, vcpkg triplet, cross-compile) - Add container/build-windows.sh (Vulkan import lib via dlltool, cross-compile) Launcher scripts (run on host): - Add container/run-linux.sh, run-macos.sh, run-windows.sh (bash) - Add container/run-linux.ps1, run-macos.ps1, run-windows.ps1 (PowerShell) Documentation: - Add container/README.md (quick start, options, file structure, troubleshooting) - Add container/FLOW.md (comprehensive build flow for each platform) CMake changes: - Add macOS cross-compile support (VulkanHeaders, -undefined dynamic_lookup) - Add LLVM-MinGW/Windows cross-compile support - Detect osxcross toolchain and vcpkg triplets Other: - Update vcpkg.json with ffmpeg feature flags - Update resources/wowee.rc version string
12 KiB
Container Build Flow
Comprehensive documentation of the Docker-based build pipeline for each target platform.
Architecture Overview
Each platform follows the same two-phase pattern:
- Image Build (one-time, cached by Docker) — installs compilers, toolchains, and pre-builds vcpkg dependencies.
- Container Run (each build) — copies source into the container, runs CMake configure + build, outputs artifacts to the host.
Host Docker
─────────────────────────────────────────────────────────────
run-{platform}.sh/.ps1
│
├─ docker build builder-{platform}.Dockerfile
│ (cached after first run) ├─ install compilers
│ ├─ install vcpkg + packages
│ └─ COPY build-{platform}.sh
│
└─ docker run build-{platform}.sh (entrypoint)
├─ bind /src (readonly) ├─ tar copy source → /wowee-build-src
└─ bind /out (writable) ├─ git clone FidelityFX SDKs
├─ cmake -S . -B /out
├─ cmake --build /out
└─ artifacts appear in /out
Linux Build Flow
Image: wowee-builder-linux
Dockerfile: builder-linux.Dockerfile
Toolchain: GCC + Ninja (native amd64)
Base: Ubuntu 24.04
Docker Image Build Steps
| Step | What | Why |
|---|---|---|
| 1 | apt-get install cmake, ninja-build, build-essential, pkg-config, git, python3 |
Core build tools |
| 2 | apt-get install glslang-tools, spirv-tools |
Vulkan shader compilation |
| 3 | apt-get install libsdl2-dev, libglew-dev, libglm-dev, libssl-dev, zlib1g-dev |
Runtime dependencies (system packages) |
| 4 | apt-get install libavformat-dev, libavcodec-dev, libswscale-dev, libavutil-dev |
FFmpeg libraries |
| 5 | apt-get install libvulkan-dev, vulkan-tools |
Vulkan SDK |
| 6 | apt-get install libstorm-dev, libunicorn-dev |
MPQ archive + CPU emulation |
| 7 | COPY build-linux.sh → /build-platform.sh |
Container entrypoint |
Container Run Steps (build-linux.sh)
1. tar copy /src → /wowee-build-src (excludes build/, .git/, large Data/ dirs)
2. git clone FidelityFX-FSR2 (if missing)
3. git clone FidelityFX-SDK (if missing)
4. cmake configure:
-G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_C_COMPILER=gcc
-DCMAKE_CXX_COMPILER=g++
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON
5. cmake --build (parallel)
6. Create Data symlink: build/linux/bin/Data → ../../../Data
Output
build/linux/bin/wowee— ELF 64-bit x86-64 executablebuild/linux/bin/Data— symlink to project Data/ directory
macOS Build Flow
Image: wowee-builder-macos
Dockerfile: builder-macos.Dockerfile (multi-stage)
Toolchain: osxcross (Clang 18 + Apple ld64)
Base: Ubuntu 24.04
Targets: arm64-apple-darwin24.5 (default), x86_64-apple-darwin24.5
Docker Image Build — Stage 1: SDK Fetcher
The macOS SDK is fetched automatically from Apple's public software update catalog. No manual download required.
| Step | What | Why |
|---|---|---|
| 1 | FROM ubuntu:24.04 AS sdk-fetcher |
Lightweight stage for SDK download |
| 2 | apt-get install ca-certificates, python3, cpio, tar, gzip, xz-utils |
SDK extraction tools |
| 3 | COPY macos/sdk-fetcher.py → /opt/sdk-fetcher.py |
Python script that scrapes Apple's SUCATALOG |
| 4 | python3 /opt/sdk-fetcher.py /opt/sdk |
Downloads, extracts, and packages MacOSX15.5.sdk.tar.gz |
SDK Fetcher internals (macos/sdk-fetcher.py):
- Queries Apple SUCATALOG URLs for the latest macOS package
- Downloads the
CLTools_macOSNMOS_SDK.pkgpackage - Extracts the XAR archive (using
bsdtaror pure-Python fallback) - Decompresses the PBZX payload stream
- Extracts via
cpioto get the SDK directory - Packages as
MacOSX<version>.sdk.tar.gz
Docker Image Build — Stage 2: Builder
| Step | What | Why |
|---|---|---|
| 1 | FROM ubuntu:24.04 AS builder |
Full build environment |
| 2 | apt-get install cmake, ninja-build, git, python3, curl, wget, xz-utils, zip, unzip, tar, make, patch, libssl-dev, zlib1g-dev, pkg-config, libbz2-dev, libxml2-dev, uuid-dev |
Build tools + osxcross build deps |
| 3 | Install Clang 18 from LLVM apt repo (llvm-toolchain-jammy-18) |
Cross-compiler backend |
| 4 | Symlink clang-18 → clang, clang++-18 → clang++, etc. | osxcross expects unversioned names |
| 5 | git clone osxcross → /opt/osxcross |
Apple cross-compile toolchain wrapper |
| 6 | COPY --from=sdk-fetcher /opt/sdk/ → /opt/osxcross/tarballs/ |
SDK from stage 1 |
| 7 | UNATTENDED=1 ./build.sh |
Builds osxcross (LLVM wrappers + cctools + ld64) |
| 8 | Create unprefixed symlinks (install_name_tool, otool, lipo, codesign) | vcpkg/CMake need these without arch prefix |
| 9 | COPY macos/osxcross-toolchain.cmake → /opt/osxcross-toolchain.cmake |
Auto-detecting CMake toolchain |
| 10 | COPY macos/triplets/ → /opt/vcpkg-triplets/ |
vcpkg cross-compile triplet definitions |
| 11 | apt-get install file, nasm |
Mach-O detection + ffmpeg x86 asm |
| 12 | Bootstrap vcpkg → /opt/vcpkg |
Package manager |
| 13 | vcpkg install sdl2, openssl, glew, glm, zlib, ffmpeg --triplet arm64-osx-cross |
arm64 dependencies |
| 14 | vcpkg install same packages --triplet x64-osx-cross |
x86_64 dependencies |
| 15 | apt-get install libvulkan-dev, glslang-tools |
Vulkan headers (for compilation, not runtime) |
| 16 | COPY build-macos.sh → /build-platform.sh |
Container entrypoint |
Custom Toolchain Files
macos/osxcross-toolchain.cmake — Auto-detecting CMake toolchain:
- Detects SDK path via
file(GLOB)in/opt/osxcross/target/SDK/MacOSX*.sdk - Detects darwin version from compiler binary names (e.g.,
arm64-apple-darwin24.5-clang) - Picks architecture from
CMAKE_OSX_ARCHITECTURES - Sets
CMAKE_C_COMPILER,CMAKE_CXX_COMPILER,CMAKE_AR,CMAKE_RANLIB,CMAKE_STRIP
macos/triplets/arm64-osx-cross.cmake:
set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Darwin)
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE /opt/osxcross-toolchain.cmake)
Container Run Steps (build-macos.sh)
1. Determine arch from MACOS_ARCH env (default: arm64)
2. Pick vcpkg triplet: arm64-osx-cross or x64-osx-cross
3. Auto-detect darwin target from osxcross binaries
4. tar copy /src → /wowee-build-src
5. git clone FidelityFX-FSR2 + FidelityFX-SDK (if missing)
6. cmake configure:
-G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_SYSTEM_NAME=Darwin
-DCMAKE_OSX_ARCHITECTURES=${ARCH}
-DCMAKE_C_COMPILER=osxcross clang
-DCMAKE_CXX_COMPILER=osxcross clang++
-DCMAKE_TOOLCHAIN_FILE=vcpkg.cmake
-DVCPKG_TARGET_TRIPLET=arm64-osx-cross
-DVCPKG_OVERLAY_TRIPLETS=/opt/vcpkg-triplets
7. cmake --build (parallel)
CMakeLists.txt Integration
The main CMakeLists.txt has a macOS cross-compile branch that:
- Finds Vulkan headers via vcpkg (
VulkanHeaderspackage) instead of the Vulkan SDK - Adds
-undefined dynamic_lookuplinker flag for Vulkan loader symbols (resolved at runtime via MoltenVK)
Output
build/macos/bin/wowee— Mach-O 64-bit arm64 (or x86_64) executable (~40 MB)
Windows Build Flow
Image: wowee-builder-windows
Dockerfile: builder-windows.Dockerfile
Toolchain: LLVM-MinGW (Clang + LLD) targeting x86_64-w64-mingw32-ucrt
Base: Ubuntu 24.04
Docker Image Build Steps
| Step | What | Why |
|---|---|---|
| 1 | apt-get install ca-certificates, build-essential, cmake, ninja-build, git, python3, curl, zip, unzip, tar, xz-utils, pkg-config, nasm, libssl-dev, zlib1g-dev |
Build tools |
| 2 | Download + extract LLVM-MinGW (v20240619 ucrt) → /opt/llvm-mingw |
Clang/LLD cross-compiler for Windows |
| 3 | Add /opt/llvm-mingw/bin to PATH |
Makes x86_64-w64-mingw32-clang etc. available |
| 4 | Bootstrap vcpkg → /opt/vcpkg |
Package manager |
| 5 | vcpkg install sdl2, openssl, glew, glm, zlib, ffmpeg --triplet x64-mingw-static |
Static Windows dependencies |
| 6 | apt-get install libvulkan-dev, glslang-tools |
Vulkan headers + shader tools |
| 7 | Create no-op powershell.exe stub |
vcpkg MinGW post-build hook needs it |
| 8 | COPY build-windows.sh → /build-platform.sh |
Container entrypoint |
Container Run Steps (build-windows.sh)
1. Set up no-op powershell.exe (if not already present)
2. tar copy /src → /wowee-build-src
3. git clone FidelityFX-FSR2 + FidelityFX-SDK (if missing)
4. Generate Vulkan import library:
a. Extract vk* symbols from vulkan_core.h
b. Create vulkan-1.def file
c. Run dlltool to create libvulkan-1.a
5. Lock PKG_CONFIG_LIBDIR to vcpkg packages only
6. cmake configure:
-G Ninja
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_SYSTEM_NAME=Windows
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-clang
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-clang++
-DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres
-DCMAKE_EXE_LINKER_FLAGS=-fuse-ld=lld
-DCMAKE_TOOLCHAIN_FILE=vcpkg.cmake
-DVCPKG_TARGET_TRIPLET=x64-mingw-static
-DVCPKG_APPLOCAL_DEPS=OFF
7. cmake --build (parallel)
Vulkan Import Library Generation
Windows applications link against vulkan-1.dll (the Khronos Vulkan loader). Since the LLVM-MinGW toolchain doesn't ship a Vulkan import library, the build script generates one:
- Parses
vulkan_core.hforVKAPI_CALL vk*function names - Creates a
.deffile mapping symbols tovulkan-1.dll - Uses
dlltoolto producelibvulkan-1.a(PE import library)
This allows the linker to resolve Vulkan symbols at build time, while deferring actual loading to the runtime DLL.
Output
build/windows/bin/wowee.exe— PE32+ x86-64 executable (~135 MB)
Shared Patterns
Source Tree Copy
All three platforms use the same tar-based copy with exclusions:
tar -C /src \
--exclude='./build' --exclude='./logs' --exclude='./cache' \
--exclude='./container' --exclude='./.git' \
--exclude='./Data/character' --exclude='./Data/creature' \
--exclude='./Data/db' --exclude='./Data/environment' \
--exclude='./Data/interface' --exclude='./Data/item' \
--exclude='./Data/misc' --exclude='./Data/sound' \
--exclude='./Data/spell' --exclude='./Data/terrain' \
--exclude='./Data/world' \
-cf - . | tar -C /wowee-build-src -xf -
Kept: Data/opcodes/, Data/expansions/ (small, needed at build time for configuration).
Excluded: Large game asset directories (character, creature, environment, etc.) not needed for compilation.
FidelityFX SDK Fetch
All platforms clone the same two repos at build time:
- FidelityFX-FSR2 — FSR 2.0 upscaling
- FidelityFX-SDK — FSR 3.0 frame generation (repo URL/ref configurable via env vars)
.dockerignore
The .dockerignore at the project root minimizes the Docker build context by excluding:
build/,cache/,logs/,.git/- Large external dirs (
extern/FidelityFX-*) - IDE files, documentation, host-only scripts
- SDK tarballs (
*.tar.xz,*.tar.gz, etc.)
Timing Estimates
These are approximate times on a 4-core machine with 16 GB RAM:
| Phase | Linux | macOS | Windows |
|---|---|---|---|
| Docker image build (first time) | ~5 min | ~25 min | ~15 min |
| Docker image build (cached) | seconds | seconds | seconds |
| Source copy + SDK fetch | ~10 sec | ~10 sec | ~10 sec |
| CMake configure | ~20 sec | ~30 sec | ~30 sec |
| Compilation | ~8 min | ~8 min | ~8 min |
| Total (first build) | ~14 min | ~34 min | ~24 min |
| Total (subsequent) | ~9 min | ~9 min | ~9 min |
macOS image is slowest because osxcross builds a subset of LLVM + cctools, and vcpkg packages are compiled for two architectures (arm64 + x64).