Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR 0004: Docker for Cross-Compilation

Status

Accepted

Context

Primary development is on macOS (Apple Silicon), but the target device runs Linux aarch64. macOS cannot cross-compile SDL2 apps directly because macOS SDL2 libraries (.dylib, Mach-O format) are incompatible with the Linux aarch64 cross-compiler (needs .so, ELF format).

Options considered:

ApproachProsCons
DockerSame environment every time, works on any host, reproducibleSlower first build (image creation)
WSL2Native Linux on Windows, can share filesWindows only, setup complexity
Virtual MachineFull Linux environmentHeavy, slow, manual maintenance
Remote Linux serverFast, always-onRequires server, network dependency
Build on deviceNo cross-compilation at allSlow compilation on H700, needs dev tools on device
nix-shellReproducible, declarativeSteep learning curve, nix adoption

Decision

Use Docker as the primary cross-compilation method. Provide build-on-device as fallback.

Consequences

Positive

  • Works on macOS, Linux, and Windows (with Docker Desktop)
  • Container has exact SDL2 version we need (2.26.2)
  • No host dependency contamination
  • Reproducible builds
  • Apple Silicon Macs run aarch64 Linux containers natively (no emulation)

Negative

  • Docker image is ~2.5 GB (Ubuntu 20.04 + SDL2 build + Rust toolchain)
  • First build takes ~2 minutes to create the image
  • Container startup adds ~5 seconds per build
  • Requires Docker Desktop installed

Implementation

scripts/Dockerfile.build creates the image:

FROM ubuntu:20.04

# Install build dependencies
RUN apt-get install -y build-essential libsdl2-dev libsdl2-ttf-dev ...

# Build SDL2 2.26.2 from source (avoids macOS Metal symbol issues)
RUN wget https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.26.2.tar.gz
...

# Build SDL2_ttf 2.20.2 from source
RUN wget https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.20.2.tar.gz
...

# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
RUN rustup target add aarch64-unknown-linux-gnu

scripts/docker-build.sh runs the build:

docker build -t cardagain-build -f scripts/Dockerfile.build .
docker run --rm -v $(pwd):/workspace -w /workspace cardagain-build \
    bash -c 'cargo build --release --target aarch64-unknown-linux-gnu'

Future work

  • Multi-stage Dockerfile to reduce image size
  • Cache Rust dependencies between builds
  • Publish pre-built image to Docker Hub or GHCR