v0.5.0: Windows/ARM64 and Linux/ARM64 cross targets, .deb/.msi packaging

- Cross toolchains: llvm-mingw-aarch64 (Windows ARM64; SDL3 staged from MSYS2's
  clangarm64 repo since SDL ships no MinGW ARM64 dev package) and
  clang-aarch64-linux-gnu (Linux ARM64; arm64 libc++/SDL3 via dpkg multiarch).
- Distro images: Dockerfile.linux-arm64, Dockerfile.win-arm64, Dockerfile.debian
  and Dockerfile.debian-arm64 (Debian 13 with upstream CMake, whose 3.31 gate
  cannot enable import std).
- Packaging via CPack: .deb for Ubuntu 26.04 and Debian 13 on amd64 and arm64
  (dependencies derived by dpkg-shlibdeps), portable .zip/.tar.gz, and a
  Windows .msi built with wixl (msitools) straight from the Linux cross image.
  wixl 0.106 lacks arm64, so Windows/ARM64 ships the portable zip only.
- CMake: parameterize the SDL3 MinGW triple, add install() + CPack config.
- CI: build/package jobs for both arm64 targets and both Debian packages;
  existing Linux/Windows jobs now also emit the .deb / .zip + .msi.
- scripts/: build-linux-arm64, build-windows-arm64, build-debian,
  build-debian-arm64.
This commit is contained in:
EnderTheCoder
2026-09-28 20:38:40 +08:00
parent 3caf18409b
commit d0ae4c76ba
18 changed files with 842 additions and 14 deletions
+173 -3
View File
@@ -89,10 +89,11 @@ build_linux:
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- retry docker pull $IMAGE:$CI_COMMIT_SHORT_SHA-linux
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux cmake -S . -B build/linux -G Ninja -DCMAKE_BUILD_TYPE=Release
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux cmake -S . -B build/linux -G Ninja -DCMAKE_BUILD_TYPE=Release -DOPENRA3_DISTRO_TAG=ubuntu26.04
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux cmake --build build/linux -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux ctest --test-dir build/linux --output-on-failure
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux bash -c "mkdir -p artifacts/linux && cp build/linux/bin/openra3 artifacts/linux/"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux bash -c "cd build/linux && cpack -G DEB"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux bash -c "mkdir -p artifacts/linux && cp build/linux/bin/openra3 build/linux/*.deb artifacts/linux/"
artifacts:
name: "$CI_PROJECT_NAME-linux-$CI_COMMIT_SHORT_SHA"
paths:
@@ -116,9 +117,178 @@ build_windows:
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-x86_64.cmake
-DCMAKE_BUILD_TYPE=Release
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows cmake --build build/windows -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows bash -c "mkdir -p artifacts/windows && cp build/windows/bin/openra3.exe build/windows/bin/SDL3.dll artifacts/windows/"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows cmake --build build/windows --target openra3_msi
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows bash -c "cd build/windows && cpack -G ZIP"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows bash -c "mkdir -p artifacts/windows && cp build/windows/bin/openra3.exe build/windows/bin/SDL3.dll build/windows/bin/*.msi build/windows/*.zip artifacts/windows/"
artifacts:
name: "$CI_PROJECT_NAME-windows-$CI_COMMIT_SHORT_SHA"
paths:
- artifacts/windows/
expire_in: 7 days
# --- arm64 + Debian toolchain images -----------------------------------------
linux_arm64_image:
stage: image
image: docker:latest
services: *dind
tags:
- docker
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- |
retry docker build \
--cache-from type=registry,ref=$IMAGE:cache-linux-arm64,insecure=true \
--cache-to type=registry,ref=$IMAGE:cache-linux-arm64,mode=max,insecure=true \
--build-arg APT_MIRROR=$APT_MIRROR \
--target dev \
-t $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64 \
-f Dockerfile.linux-arm64 .
- retry docker push $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64
windows_arm64_image:
stage: image
image: docker:latest
services: *dind
tags:
- docker
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- |
retry docker build \
--cache-from type=registry,ref=$IMAGE:cache-windows-arm64,insecure=true \
--cache-to type=registry,ref=$IMAGE:cache-windows-arm64,mode=max,insecure=true \
--build-arg APT_MIRROR=$APT_MIRROR \
--target dev \
-t $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64 \
-f Dockerfile.win-arm64 .
- retry docker push $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64
debian_image:
stage: image
image: docker:latest
services: *dind
tags:
- docker
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- |
retry docker build \
--cache-from type=registry,ref=$IMAGE:cache-debian,insecure=true \
--cache-to type=registry,ref=$IMAGE:cache-debian,mode=max,insecure=true \
--build-arg APT_MIRROR=$APT_MIRROR \
--target dev \
-t $IMAGE:$CI_COMMIT_SHORT_SHA-debian \
-f Dockerfile.debian .
- retry docker push $IMAGE:$CI_COMMIT_SHORT_SHA-debian
debian_arm64_image:
stage: image
image: docker:latest
services: *dind
tags:
- docker
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- |
retry docker build \
--cache-from type=registry,ref=$IMAGE:cache-debian-arm64,insecure=true \
--cache-to type=registry,ref=$IMAGE:cache-debian-arm64,mode=max,insecure=true \
--build-arg APT_MIRROR=$APT_MIRROR \
--target dev \
-t $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64 \
-f Dockerfile.debian-arm64 .
- retry docker push $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64
# --- build each target (binary + packages) -----------------------------------
build_linux_arm64:
stage: build
image: docker:latest
services: *dind
tags:
- docker
needs:
- linux_arm64_image
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- retry docker pull $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64 cmake -S . -B build/linux-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -DOPENRA3_DISTRO_TAG=ubuntu26.04
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64 cmake --build build/linux-arm64 -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64 bash -c "cd build/linux-arm64 && cpack -G DEB"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-linux-arm64 bash -c "mkdir -p artifacts/linux-arm64 && cp build/linux-arm64/bin/openra3 build/linux-arm64/*.deb artifacts/linux-arm64/"
artifacts:
name: "$CI_PROJECT_NAME-linux-arm64-$CI_COMMIT_SHORT_SHA"
paths:
- artifacts/linux-arm64/
expire_in: 7 days
build_windows_arm64:
stage: build
image: docker:latest
services: *dind
tags:
- docker
needs:
- windows_arm64_image
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- retry docker pull $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64 cmake -S . -B build/windows-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-aarch64.cmake -DCMAKE_BUILD_TYPE=Release
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64 cmake --build build/windows-arm64 -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64 bash -c "cd build/windows-arm64 && cpack -G ZIP"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-windows-arm64 bash -c "mkdir -p artifacts/windows-arm64 && cp build/windows-arm64/bin/openra3.exe build/windows-arm64/bin/SDL3.dll build/windows-arm64/*.zip artifacts/windows-arm64/"
artifacts:
name: "$CI_PROJECT_NAME-windows-arm64-$CI_COMMIT_SHORT_SHA"
paths:
- artifacts/windows-arm64/
expire_in: 7 days
build_debian:
stage: build
image: docker:latest
services: *dind
tags:
- docker
needs:
- debian_image
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- retry docker pull $IMAGE:$CI_COMMIT_SHORT_SHA-debian
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian cmake -S . -B build/debian -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json -DOPENRA3_DISTRO_TAG=debian13
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian cmake --build build/debian -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian ctest --test-dir build/debian --output-on-failure
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian bash -c "cd build/debian && cpack -G DEB"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian bash -c "mkdir -p artifacts/debian && cp build/debian/bin/openra3 build/debian/*.deb artifacts/debian/"
artifacts:
name: "$CI_PROJECT_NAME-debian-$CI_COMMIT_SHORT_SHA"
paths:
- artifacts/debian/
expire_in: 7 days
build_debian_arm64:
stage: build
image: docker:latest
services: *dind
tags:
- docker
needs:
- debian_arm64_image
before_script: *retry
script:
- retry sh -c 'echo "$HARBOR_PASSWORD" | docker login "$HARBOR_HOST" -u "$HARBOR_USERNAME" --password-stdin'
- retry docker pull $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64 cmake -S . -B build/debian-arm64 -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -DOPENRA3_AARCH64_CC=clang-19 -DOPENRA3_AARCH64_CXX=clang++-19 -DOPENRA3_AARCH64_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json -DOPENRA3_DISTRO_TAG=debian13
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64 cmake --build build/debian-arm64 -j
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64 bash -c "cd build/debian-arm64 && cpack -G DEB"
- docker run --rm -v "$(pwd):/work" -w /work $IMAGE:$CI_COMMIT_SHORT_SHA-debian-arm64 bash -c "mkdir -p artifacts/debian-arm64 && cp build/debian-arm64/bin/openra3 build/debian-arm64/*.deb artifacts/debian-arm64/"
artifacts:
name: "$CI_PROJECT_NAME-debian-arm64-$CI_COMMIT_SHORT_SHA"
paths:
- artifacts/debian-arm64/
expire_in: 7 days
+75 -4
View File
@@ -25,7 +25,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)
project(OpenRA3 VERSION 0.4.0 LANGUAGES C CXX)
project(OpenRA3 VERSION 0.5.0 LANGUAGES C CXX)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
@@ -52,9 +52,12 @@ endfunction()
# --- SDL3: pkg-config on Linux, or an explicit MinGW root for Windows --------
add_library(openra3_sdl3 INTERFACE)
set(OPENRA3_HAS_SDL3 OFF)
# The triple-named subdirectory inside a MinGW SDL3 development package
# (`<root>/<triple>/{include,lib,bin}`); x86_64 unless a toolchain overrides it.
set(OPENRA3_SDL3_MINGW_TRIPLE "x86_64-w64-mingw32" CACHE STRING "SDL3 MinGW triple subdirectory")
if(OPENRA3_SDL3_ROOT)
target_include_directories(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/include")
target_link_libraries(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/lib/libSDL3.dll.a")
target_include_directories(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/${OPENRA3_SDL3_MINGW_TRIPLE}/include")
target_link_libraries(openra3_sdl3 INTERFACE "${OPENRA3_SDL3_ROOT}/${OPENRA3_SDL3_MINGW_TRIPLE}/lib/libSDL3.dll.a")
set(OPENRA3_HAS_SDL3 ON)
else()
find_package(PkgConfig QUIET)
@@ -293,10 +296,78 @@ openra3_target_defaults(openra3)
if(WIN32 AND OPENRA3_SDL3_ROOT)
add_custom_command(TARGET openra3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${OPENRA3_SDL3_ROOT}/x86_64-w64-mingw32/bin/SDL3.dll"
"${OPENRA3_SDL3_ROOT}/${OPENRA3_SDL3_MINGW_TRIPLE}/bin/SDL3.dll"
"$<TARGET_FILE_DIR:openra3>")
endif()
# --- packaging (.deb / .msi / portable archives) -----------------------------
# CPack produces the release artifacts in one shot:
# Linux -> DEB (dependencies derived from the binary with dpkg-shlibdeps)
# plus a portable .tar.gz
# Windows -> a Windows Installer .msi (built with wixl from msitools when the
# WiX tools are absent, so the Linux cross image can make it) plus a
# portable .zip with the exe and SDL3.dll
# OPENRA3_DISTRO_TAG (e.g. ubuntu26.04) is appended to the Linux file name so the
# per-distro images do not collide.
install(TARGETS openra3 RUNTIME DESTINATION bin)
if(WIN32 AND OPENRA3_SDL3_ROOT)
install(FILES "${OPENRA3_SDL3_ROOT}/${OPENRA3_SDL3_MINGW_TRIPLE}/bin/SDL3.dll" DESTINATION bin)
endif()
set(OPENRA3_DISTRO_TAG "" CACHE STRING "Distro tag appended to package file names (e.g. ubuntu26.04)")
set(CPACK_PACKAGE_NAME "openra3")
set(CPACK_PACKAGE_VENDOR "OpenRA3")
set(CPACK_PACKAGE_CONTACT "OpenRA3 <noreply@openra3.invalid>")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenRA3 - a from-scratch reimplementation of Red Alert 3")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://git.ender.cool/EnderTheCoder/openra3")
set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
set(CPACK_PACKAGE_EXECUTABLES "openra3" "OpenRA3")
set(CPACK_STRIP_FILES ON)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
endif()
if(WIN32)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(OPENRA3_WIN_ARCH "arm64")
else()
set(OPENRA3_WIN_ARCH "x86_64")
endif()
set(CPACK_PACKAGE_FILE_NAME "openra3-${PROJECT_VERSION}-windows-${OPENRA3_WIN_ARCH}")
# Portable .zip (exe + SDL3.dll).
set(CPACK_GENERATOR "ZIP")
# A Windows Installer (.msi) straight from the Linux cross build via wixl
# (msitools). wixl 0.106 has no arm64 support, so the MSI is offered for
# x86_64 and ARM64 ships the portable zip.
find_program(OPENRA3_WIXL wixl)
if(OPENRA3_WIXL AND NOT CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/packaging/openra3.wxs.in"
"${CMAKE_CURRENT_BINARY_DIR}/openra3.wxs" @ONLY)
add_custom_target(openra3_msi
COMMAND "${OPENRA3_WIXL}" --arch x64
-D "exe=$<TARGET_FILE:openra3>"
-D "dll=${OPENRA3_SDL3_ROOT}/${OPENRA3_SDL3_MINGW_TRIPLE}/bin/SDL3.dll"
-o "$<TARGET_FILE_DIR:openra3>/${CPACK_PACKAGE_FILE_NAME}.msi"
"${CMAKE_CURRENT_BINARY_DIR}/openra3.wxs"
DEPENDS openra3
COMMENT "Building Windows Installer (${CPACK_PACKAGE_FILE_NAME}.msi) with wixl"
VERBATIM)
endif()
else()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64")
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "arm64")
else()
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64")
endif()
set(CPACK_PACKAGE_FILE_NAME "openra3_${PROJECT_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}${OPENRA3_DISTRO_TAG}")
set(CPACK_GENERATOR "TGZ;DEB")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
endif()
include(CPack)
# --- extracted assets ---------------------------------------------------------
# At build time, extract the retail assets into <exe_dir>/assets so the
# executable is self-contained (no --game-dir at run time). This drives the
+5 -2
View File
@@ -29,6 +29,8 @@ RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
clang-21 \
clang-tools-21 \
cmake \
dpkg-dev \
file \
gdb \
git \
libc++-21-dev \
@@ -45,9 +47,10 @@ ENV CXX=clang++-21
WORKDIR /work
COPY . .
RUN cmake -S . -B build/linux -G Ninja -DCMAKE_BUILD_TYPE=Release \
RUN cmake -S . -B build/linux -G Ninja -DCMAKE_BUILD_TYPE=Release -DOPENRA3_DISTRO_TAG=ubuntu26.04 \
&& cmake --build build/linux -j \
&& ctest --test-dir build/linux --output-on-failure
&& ctest --test-dir build/linux --output-on-failure \
&& (cd build/linux && cpack -G DEB)
# deploy target: runtime dependencies + final binary, minimal and fast.
FROM ubuntu:26.04 AS deploy
+87
View File
@@ -0,0 +1,87 @@
# syntax=docker/dockerfile:1
# Debian build environment (latest stable, Debian 13 "trixie") producing a .deb
# alongside the binary. Separate from Dockerfile (Ubuntu 26.04) because the
# distro and its libc++/SDL3 versions differ, and a .deb's dependencies must be
# generated against the distro it targets.
#
# Toolchain: clang-19 + libc++-19 (for `import std;`). Debian 13 ships CMake
# 3.31, whose experimental `import std` gate value the project does not target,
# so an upstream CMake is installed from the Kitware tarball.
FROM debian:stable AS dev
ENV DEBIAN_FRONTEND=noninteractive
ARG APT_MIRROR=""
RUN if [ -n "$APT_MIRROR" ]; then \
sed -i -e "s|http://deb.debian.org/debian|${APT_MIRROR}|g" \
-e "s|http://security.debian.org/debian-security|${APT_MIRROR}|g" \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true; \
fi
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
for attempt in 1 2 3 4 5; do \
apt-get -o Acquire::Retries=5 update && break; \
echo "apt-get update failed (attempt $attempt), retrying"; \
sleep 5; \
done \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
ca-certificates \
clang-19 \
clang-tools-19 \
curl \
dpkg-dev \
file \
libc++-19-dev \
libc++abi-19-dev \
libsdl3-dev \
libunwind-19-dev \
lld-19 \
ninja-build \
pkg-config \
python3 \
&& rm -rf /var/lib/apt/lists/*
# Upstream CMake, because Debian 13's 3.31 experimental gate does not enable the
# `import std;` support the project relies on.
ARG CMAKE_VERSION=4.2.3
RUN mkdir -p /opt/cmake \
&& curl -fL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz" \
| tar -xz -C /opt/cmake --strip-components=1
ENV PATH="/opt/cmake/bin:${PATH}"
ENV CC=clang-19
ENV CXX=clang++-19
WORKDIR /work
COPY . .
RUN cmake -S . -B build/debian -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json \
-DOPENRA3_DISTRO_TAG=debian13 \
&& cmake --build build/debian -j \
&& ctest --test-dir build/debian --output-on-failure \
&& (cd build/debian && cpack -G DEB)
# deploy target: runtime dependencies + final binary, minimal and fast.
FROM debian:stable AS deploy
ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
apt-get -o Acquire::Retries=5 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
libc++1-19 \
libc++abi1-19 \
libsdl3-0 \
libvulkan1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=dev /work/build/debian/bin/openra3 /app/openra3
ENTRYPOINT ["/app/openra3"]
+86
View File
@@ -0,0 +1,86 @@
# syntax=docker/dockerfile:1
# Debian build environment for Linux on ARM64 (aarch64-linux-gnu), producing an
# arm64 .deb. Cross-compiled from amd64 with Debian's clang-19 + libc++-19 and
# the arm64 packages installed via dpkg multiarch.
FROM debian:stable AS dev
ENV DEBIAN_FRONTEND=noninteractive
ARG APT_MIRROR=""
RUN if [ -n "$APT_MIRROR" ]; then \
sed -i -e "s|http://deb.debian.org/debian|${APT_MIRROR}|g" \
-e "s|http://security.debian.org/debian-security|${APT_MIRROR}|g" \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true; \
fi
RUN dpkg --add-architecture arm64
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
for attempt in 1 2 3 4 5; do \
apt-get -o Acquire::Retries=5 update && break; \
echo "apt-get update failed (attempt $attempt), retrying"; \
sleep 5; \
done \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
ca-certificates \
clang-19 \
clang-tools-19 \
curl \
dpkg-dev \
file \
gcc-aarch64-linux-gnu \
libc++-19-dev:arm64 \
libc++abi-19-dev:arm64 \
libsdl3-dev:arm64 \
libunwind-19-dev:arm64 \
lld-19 \
ninja-build \
pkg-config \
python3 \
&& rm -rf /var/lib/apt/lists/*
ARG CMAKE_VERSION=4.2.3
RUN mkdir -p /opt/cmake \
&& curl -fL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-linux-x86_64.tar.gz" \
| tar -xz -C /opt/cmake --strip-components=1
ENV PATH="/opt/cmake/bin:${PATH}"
ENV CC=clang-19
ENV CXX=clang++-19
# Point pkg-config at the arm64 packages so SDL3 resolves to the aarch64 build.
ENV PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig
WORKDIR /work
COPY . .
RUN cmake -S . -B build/debian-arm64 -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DOPENRA3_AARCH64_CC=clang-19 \
-DOPENRA3_AARCH64_CXX=clang++-19 \
-DOPENRA3_AARCH64_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json \
-DOPENRA3_DISTRO_TAG=debian13 \
&& cmake --build build/debian-arm64 -j \
&& (cd build/debian-arm64 && cpack -G DEB)
FROM --platform=linux/arm64 debian:stable AS deploy
ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
apt-get -o Acquire::Retries=5 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
libc++1-19 \
libc++abi1-19 \
libsdl3-0 \
libvulkan1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=dev /work/build/debian-arm64/bin/openra3 /app/openra3
ENTRYPOINT ["/app/openra3"]
+84
View File
@@ -0,0 +1,84 @@
# syntax=docker/dockerfile:1
# Linux on ARM64 cross-build environment (aarch64-linux-gnu), isolated from the
# x86_64 Linux image and the Windows images.
#
# Toolchain: clang-21 + libc++ with the arm64 libc++ (for `import std;`), the
# arm64 glibc from `gcc-aarch64-linux-gnu`, arm64 SDL3 from `libsdl3-dev:arm64`,
# and lld as the linker. The arm64 packages are installed with dpkg multiarch
# (`arm64` added to the sources); the native clang/cmake build tools stay amd64.
FROM ubuntu:26.04 AS dev
ENV DEBIAN_FRONTEND=noninteractive
ARG APT_MIRROR=""
RUN if [ -n "$APT_MIRROR" ]; then \
sed -i -e "s|http://archive.ubuntu.com/ubuntu|${APT_MIRROR}|g" \
-e "s|http://security.ubuntu.com/ubuntu|${APT_MIRROR}|g" \
-e "s|http://ports.ubuntu.com/ubuntu-ports|${APT_MIRROR}|g" \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true; \
fi
# Enable the arm64 architecture on top of the emulated amd64 userland.
RUN dpkg --add-architecture arm64
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
for attempt in 1 2 3 4 5; do \
apt-get -o Acquire::Retries=5 update && break; \
echo "apt-get update failed (attempt $attempt), retrying"; \
sleep 5; \
done \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
ca-certificates \
clang-21 \
cmake \
dpkg-dev \
file \
gcc-aarch64-linux-gnu \
libc++-21-dev:arm64 \
libc++abi-21-dev:arm64 \
libsdl3-dev:arm64 \
libunwind-21-dev:arm64 \
lld-21 \
ninja-build \
pkg-config \
python3 \
&& rm -rf /var/lib/apt/lists/*
ENV CC=clang-21
ENV CXX=clang++-21
# Point pkg-config at the arm64 packages so SDL3 resolves to the aarch64 build.
ENV PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig
WORKDIR /work
COPY . .
RUN cmake -S . -B build/linux-arm64 -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DOPENRA3_DISTRO_TAG=ubuntu26.04 \
&& cmake --build build/linux-arm64 -j \
&& (cd build/linux-arm64 && cpack -G DEB)
# deploy target: runtime dependencies + final binary, minimal and fast. This is
# an arm64 image; build it on (or with emulation for) an arm64 host.
FROM --platform=linux/arm64 ubuntu:26.04 AS deploy
ENV DEBIAN_FRONTEND=noninteractive
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
apt-get -o Acquire::Retries=5 update \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
libc++1 \
libc++abi1 \
libsdl3-0 \
libvulkan1 \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=dev /work/build/linux-arm64/bin/openra3 /app/openra3
ENTRYPOINT ["/app/openra3"]
+4 -1
View File
@@ -31,6 +31,7 @@ RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
curl \
ninja-build \
python3 \
wixl \
xz-utils \
&& rm -rf /var/lib/apt/lists/*
@@ -54,7 +55,9 @@ COPY . .
RUN cmake -S . -B build/windows -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-x86_64.cmake \
-DCMAKE_BUILD_TYPE=Release \
&& cmake --build build/windows -j
&& cmake --build build/windows -j \
&& cmake --build build/windows --target openra3_msi \
&& (cd build/windows && cpack -G ZIP)
# package target: the .exe plus the SDL3 runtime DLL.
FROM ubuntu:26.04 AS package
+77
View File
@@ -0,0 +1,77 @@
# syntax=docker/dockerfile:1
# Windows on ARM64 cross-build environment (aarch64-w64-mingw32), isolated from
# the x86_64 Windows image and the Linux images.
#
# Toolchain: the same multi-target llvm-mingw as Dockerfile.win (clang + libc++ +
# the libc++ `std` module, MSVCRT runtime), targeting aarch64. The official SDL
# release ships no MinGW ARM64 dev package, so SDL3 comes from MSYS2's clangarm64
# repository, staged into the `<triple>/{include,lib,bin}` layout the toolchain
# expects.
FROM ubuntu:26.04 AS dev
ENV DEBIAN_FRONTEND=noninteractive
ARG APT_MIRROR=""
RUN if [ -n "$APT_MIRROR" ]; then \
sed -i -e "s|http://archive.ubuntu.com/ubuntu|${APT_MIRROR}|g" \
-e "s|http://security.ubuntu.com/ubuntu|${APT_MIRROR}|g" \
-e "s|http://ports.ubuntu.com/ubuntu-ports|${APT_MIRROR}|g" \
/etc/apt/sources.list /etc/apt/sources.list.d/*.sources 2>/dev/null || true; \
fi
RUN --mount=type=cache,target=/var/lib/apt,sharing=locked \
--mount=type=cache,target=/var/cache/apt,sharing=locked \
for attempt in 1 2 3 4 5; do \
apt-get -o Acquire::Retries=5 update && break; \
echo "apt-get update failed (attempt $attempt), retrying"; \
sleep 5; \
done \
&& apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
ca-certificates \
cmake \
curl \
ninja-build \
python3 \
xz-utils \
zstd \
&& rm -rf /var/lib/apt/lists/*
# Pinned toolchain + SDL3 versions (override with --build-arg to bump).
ARG LLVM_MINGW_VERSION=20260908
ARG LLVM_MINGW_FLAVOR=msvcrt
# SDL3 for aarch64-w64-mingw32 from MSYS2's clangarm64 repo (name includes the
# MSYS2 package release, hence the `-1`).
ARG MSYS2_SDL3_PKG=mingw-w64-clang-aarch64-sdl3-3.4.16-1-any.pkg.tar.zst
RUN mkdir -p /opt/llvm-mingw \
&& curl -fL "https://github.com/mstorsjo/llvm-mingw/releases/download/${LLVM_MINGW_VERSION}/llvm-mingw-${LLVM_MINGW_VERSION}-${LLVM_MINGW_FLAVOR}-ubuntu-22.04-x86_64.tar.xz" \
| tar -xJ -C /opt/llvm-mingw --strip-components=1
RUN mkdir -p /opt/sdl3-aarch64/aarch64-w64-mingw32/include /opt/sdl3-aarch64/aarch64-w64-mingw32/lib /opt/sdl3-aarch64/aarch64-w64-mingw32/bin \
&& curl -fL "https://repo.msys2.org/mingw/clangarm64/${MSYS2_SDL3_PKG}" -o /tmp/sdl3.pkg.tar.zst \
&& mkdir -p /tmp/sdl3 && tar --zstd -xf /tmp/sdl3.pkg.tar.zst -C /tmp/sdl3 \
&& cp -r /tmp/sdl3/clangarm64/include/SDL3 /opt/sdl3-aarch64/aarch64-w64-mingw32/include/ \
&& cp /tmp/sdl3/clangarm64/lib/libSDL3.dll.a /opt/sdl3-aarch64/aarch64-w64-mingw32/lib/ \
&& cp /tmp/sdl3/clangarm64/bin/SDL3.dll /opt/sdl3-aarch64/aarch64-w64-mingw32/bin/ \
&& rm -rf /tmp/sdl3 /tmp/sdl3.pkg.tar.zst
ENV OPENRA3_LLVM_MINGW_ROOT=/opt/llvm-mingw
ENV OPENRA3_SDL3_ROOT=/opt/sdl3-aarch64
WORKDIR /work
COPY . .
RUN cmake -S . -B build/windows-arm64 -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-aarch64.cmake \
-DCMAKE_BUILD_TYPE=Release \
&& cmake --build build/windows-arm64 -j \
&& (cd build/windows-arm64 && cpack -G ZIP)
# package target: the .exe plus the SDL3 runtime DLL.
FROM ubuntu:26.04 AS package
WORKDIR /app
COPY --from=dev /work/build/windows-arm64/bin/openra3.exe /app/
COPY --from=dev /work/build/windows-arm64/bin/SDL3.dll /app/
+38 -3
View File
@@ -18,7 +18,7 @@ Ghidra.
## Status
OpenRA3 is at **v0.4.0**. The engine compiles and runs headless, and a **minimal
OpenRA3 is at **v0.5.0**. The engine compiles and runs headless, and a **minimal
skirmish** is playable: it reads a real multiplayer map out of your install,
recovers the player start waypoints, and simulates two sides building a base,
extracting ore and fighting until one side is wiped out. The balance is the
@@ -122,13 +122,29 @@ their compilers and standard libraries never interfere.
The host needs no toolchain: each target builds inside its own image.
```bash
# Linux -> build/linux/bin/openra3
# Linux (amd64) -> build/linux/bin/openra3 + .deb
scripts/build-linux.sh
# Windows -> build/windows/bin/openra3.exe (+ SDL3.dll)
# Linux/arm64 -> build/linux-arm64/bin/openra3 + .deb (cross)
scripts/build-linux-arm64.sh
# Debian (amd64) -> build/debian/bin/openra3 + .deb
scripts/build-debian.sh
# Debian (arm64) -> build/debian-arm64/bin/openra3 + .deb (cross)
scripts/build-debian-arm64.sh
# Windows (x86_64) -> build/windows/bin/openra3.exe + SDL3.dll, .zip, .msi
scripts/build-windows.sh
# Windows (arm64) -> build/windows-arm64/bin/openra3.exe + SDL3.dll, .zip (cross)
scripts/build-windows-arm64.sh
```
Every target is cross-built from x86_64 Linux in its own image: llvm-mingw for
the Windows targets, clang + libc++ with dpkg multiarch for the arm64 targets,
and Debian/Ubuntu-specific images for the `.deb` packages.
Or drive Docker directly:
```bash
@@ -160,6 +176,25 @@ openra3.exe render --game-dir "C:\Red Alert 3" --vulkan
Vulkan is provided by **vendored volk + headers** (`third_party/`), resolved at
runtime, so neither image needs a Vulkan SDK.
## Packages
CPack produces the release artifacts; the Docker images and CI run it for every
target.
| Target | Portable | Installer |
| --- | --- | --- |
| Linux amd64 (Ubuntu 26.04) | `.tar.gz` | `openra3_<v>_amd64ubuntu26.04.deb` |
| Linux arm64 (Ubuntu 26.04) | `.tar.gz` | `openra3_<v>_arm64ubuntu26.04.deb` |
| Linux amd64 (Debian 13) | `.tar.gz` | `openra3_<v>_amd64debian13.deb` |
| Linux arm64 (Debian 13) | `.tar.gz` | `openra3_<v>_arm64debian13.deb` |
| Windows x86_64 | `openra3-<v>-windows-x86_64.zip` | `openra3-<v>-windows-x86_64.msi` |
| Windows arm64 | `openra3-<v>-windows-arm64.zip` | (WiX-only; see below) |
The `.deb` dependencies are derived from the binary with `dpkg-shlibdeps`. The
`.msi` is built with **wixl** (msitools) straight from the Linux cross image;
wixl 0.106 has no arm64 support, so Windows/ARM64 ships the portable `.zip`
(the MSI toolchain for ARM64 would be WiX v4 via the .NET SDK).
## Logging
Every run writes `openra3.log` next to the executable through the vendored
+1 -1
View File
@@ -1 +1 @@
0.4.0
0.5.0
+39
View File
@@ -0,0 +1,39 @@
<?xml version='1.0' encoding='utf-8'?>
<!--
Windows Installer source for OpenRA3, driven by wixl (msitools) so the Linux
cross-build image can produce the .msi. `exe` and `dll` are passed with
wixl -D; the version is substituted at configure time.
-->
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Id='*'
Name='OpenRA3'
Language='1033'
Version='@PROJECT_VERSION@'
Manufacturer='OpenRA3'
UpgradeCode='6C6B1F4E-0B9A-4C2E-9E2A-2E4D7B5C1A31'>
<Package Id='*' InstallerVersion='500' Compressed='yes' InstallScope='perMachine'/>
<Media Id='1' Cabinet='openra3.cab' EmbedCab='yes'/>
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFiles64Folder'>
<Directory Id='INSTALLFOLDER' Name='OpenRA3'>
<Component Id='MainExecutable' Guid='1F2E3D4C-5B6A-4798-8C1D-2E3F4A5B6C7D'>
<File Id='OpenRA3Exe' Name='openra3.exe' Source='$(var.exe)' KeyPath='yes'>
<Shortcut Id='StartMenuShortcut' Directory='ProgramMenuFolder' Name='OpenRA3'
WorkingDirectory='INSTALLFOLDER' Advertise='no'/>
</File>
</Component>
<Component Id='SdlRuntime' Guid='2A3B4C5D-6E7F-4809-9D2E-3F4A5B6C7D8E'>
<File Id='Sdl3Dll' Name='SDL3.dll' Source='$(var.dll)' KeyPath='yes'/>
</Component>
</Directory>
</Directory>
<Directory Id='ProgramMenuFolder'/>
</Directory>
<Feature Id='Main' Title='OpenRA3' Level='1'>
<ComponentRef Id='MainExecutable'/>
<ComponentRef Id='SdlRuntime'/>
</Feature>
</Product>
</Wix>
@@ -0,0 +1,53 @@
# Cross-compile for Linux on ARM64 (aarch64-linux-gnu) from x86_64.
#
# clang-21 + libc++ (for `import std;`) with the arm64 libc++ and SDL3 taken
# from Ubuntu's arm64 packages (installed with dpkg multiarch), and the arm64
# glibc headers/libs from `gcc-aarch64-linux-gnu`. lld links the result; the C
# multiarch include directory is added explicitly because clang does not always
# infer Debian's `bits/` layout from the target triple alone.
# The `import std` gate must be set before the compiler is probed; a toolchain
# file is processed earlier than the project's own top-level settings.
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(OPENRA3_AARCH64_TRIPLE "aarch64-linux-gnu")
# Multiarch paths the arm64 packages install into.
set(OPENRA3_AARCH64_INCLUDE "/usr/include/${OPENRA3_AARCH64_TRIPLE}")
set(OPENRA3_AARCH64_LIB "/usr/lib/${OPENRA3_AARCH64_TRIPLE}")
# Compiler + libc++ module description are cache vars so a distro with a
# differently-versioned clang (e.g. Debian's clang-19) can override on the
# command line.
set(OPENRA3_AARCH64_CC "clang-21" CACHE STRING "aarch64 C compiler")
set(OPENRA3_AARCH64_CXX "clang++-21" CACHE STRING "aarch64 C++ compiler")
set(OPENRA3_AARCH64_STDLIB_MODULES_JSON "/usr/lib/llvm-21/lib/libc++.modules.json" CACHE FILEPATH
"libc++ std module description for the aarch64 target")
set(CMAKE_C_COMPILER ${OPENRA3_AARCH64_CC})
set(CMAKE_CXX_COMPILER ${OPENRA3_AARCH64_CXX})
set(CMAKE_C_COMPILER_TARGET ${OPENRA3_AARCH64_TRIPLE})
set(CMAKE_CXX_COMPILER_TARGET ${OPENRA3_AARCH64_TRIPLE})
# CMake's standard-library detection does not pass COMPILER_TARGET, so without
# this it probes the host standard library.
set(CMAKE_C_COMPILER_ARG1 "--target=${OPENRA3_AARCH64_TRIPLE}")
set(CMAKE_CXX_COMPILER_ARG1 "--target=${OPENRA3_AARCH64_TRIPLE}")
# libc++ standard-library module description for the aarch64 target. On a
# multiarch image only the arm64 libc++ is installed, so the standard path
# already resolves to the aarch64 module description.
set(CMAKE_CXX_STDLIB_MODULES_JSON "${OPENRA3_AARCH64_STDLIB_MODULES_JSON}")
# Strip with the cross binutils, so CPack can strip the arm64 binary.
set(CMAKE_STRIP aarch64-linux-gnu-strip)
set(CMAKE_C_FLAGS_INIT "-isystem ${OPENRA3_AARCH64_INCLUDE}")
set(CMAKE_CXX_FLAGS_INIT "-stdlib=libc++ -isystem ${OPENRA3_AARCH64_INCLUDE}")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-stdlib=libc++ -fuse-ld=lld -L${OPENRA3_AARCH64_LIB}")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-stdlib=libc++ -fuse-ld=lld -L${OPENRA3_AARCH64_LIB}")
# Run arm64 test binaries through qemu when it is installed, so `ctest` works
# during the image build; harmless when the tests are only cross-compiled.
set(CMAKE_CROSSCOMPILING_EMULATOR qemu-aarch64-static)
+50
View File
@@ -0,0 +1,50 @@
# Cross-compile for Windows on ARM64 (aarch64-w64-mingw32) with llvm-mingw:
# clang + libc++ + the libc++ `std` module, targeting the MSVCRT MinGW runtime.
# The same llvm-mingw release is multi-target, so only the target triple, the
# SDL3 SDK and the sysroot paths differ from the x86_64 toolchain.
# The `import std` gate must be set before the compiler is probed; a toolchain
# file is processed earlier than the project's own top-level settings.
set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444")
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(OPENRA3_LLVM_MINGW_ROOT "/opt/llvm-mingw" CACHE PATH "llvm-mingw installation root")
if(NOT EXISTS "${OPENRA3_LLVM_MINGW_ROOT}/bin/clang++")
message(FATAL_ERROR "llvm-mingw not found at ${OPENRA3_LLVM_MINGW_ROOT} (expected bin/clang++)")
endif()
# llvm-mingw's per-target prefix/sysroot for the ARM64 target.
set(OPENRA3_MINGW_TRIPLE "aarch64-w64-mingw32")
set(CMAKE_C_COMPILER "${OPENRA3_LLVM_MINGW_ROOT}/bin/clang")
set(CMAKE_CXX_COMPILER "${OPENRA3_LLVM_MINGW_ROOT}/bin/clang++")
set(CMAKE_C_COMPILER_TARGET ${OPENRA3_MINGW_TRIPLE})
set(CMAKE_CXX_COMPILER_TARGET ${OPENRA3_MINGW_TRIPLE})
# CMake's standard-library detection does not pass COMPILER_TARGET, so without
# this it probes the host standard library. Putting the target in ARG1 makes
# the probe see libc++ (the MinGW target's library).
set(CMAKE_C_COMPILER_ARG1 "--target=${OPENRA3_MINGW_TRIPLE}")
set(CMAKE_CXX_COMPILER_ARG1 "--target=${OPENRA3_MINGW_TRIPLE}")
# libc++ standard-library module description for the MinGW target. Must be set
# before the compiler is probed so CMake can build `import std;`.
set(CMAKE_CXX_STDLIB_MODULES_JSON "${OPENRA3_LLVM_MINGW_ROOT}/${OPENRA3_MINGW_TRIPLE}/lib/libc++.modules.json")
# Select libc++ explicitly so CMake's `import std` detection recognises the
# standard library (llvm-mingw defaults to it, but CMake keys off -stdlib=).
set(CMAKE_CXX_FLAGS_INIT "-stdlib=libc++")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-stdlib=libc++")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-stdlib=libc++")
# SDL3 for aarch64-w64-mingw32. The official SDL release ships no MinGW ARM64
# dev package, so the image stages one from MSYS2's clangarm64 repo under this
# root in the same `<triple>/{include,lib,bin}` layout.
set(OPENRA3_SDL3_ROOT "/opt/sdl3-aarch64" CACHE PATH "SDL3 aarch64 MinGW development package root")
set(OPENRA3_SDL3_MINGW_TRIPLE "${OPENRA3_MINGW_TRIPLE}" CACHE STRING "SDL3 MinGW triple subdirectory")
set(CMAKE_FIND_ROOT_PATH "${OPENRA3_LLVM_MINGW_ROOT}/${OPENRA3_MINGW_TRIPLE}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+2
View File
@@ -36,6 +36,8 @@ set(CMAKE_SHARED_LINKER_FLAGS_INIT "-stdlib=libc++")
# Official SDL3 MinGW development package (headers + import library + DLL).
set(OPENRA3_SDL3_ROOT "/opt/sdl3-mingw" CACHE PATH "SDL3 MinGW development package root")
# The triple-named subdirectory inside the SDL3 MinGW package.
set(OPENRA3_SDL3_MINGW_TRIPLE "x86_64-w64-mingw32" CACHE STRING "SDL3 MinGW triple subdirectory")
set(CMAKE_FIND_ROOT_PATH "${OPENRA3_LLVM_MINGW_ROOT}/x86_64-w64-mingw32")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# Build the Debian (latest stable) Linux/ARM64 target (.deb + binary).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IMAGE="${OPENRA3_DEBIAN_ARM64_IMAGE:-openra3-debian-arm64:local}"
BUILD_DIR="${1:-build/debian-arm64}"
docker build --target dev -f "$ROOT/Dockerfile.debian-arm64" -t "$IMAGE" "$ROOT"
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake -S . -B "$BUILD_DIR" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DOPENRA3_AARCH64_CC=clang-19 -DOPENRA3_AARCH64_CXX=clang++-19 \
-DOPENRA3_AARCH64_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json \
-DOPENRA3_DISTRO_TAG=debian13
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake --build "$BUILD_DIR" -j
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" bash -c "cd $BUILD_DIR && cpack -G DEB"
echo "Debian arm64: $ROOT/$BUILD_DIR/bin/openra3 (+ .deb)"
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Build the Debian (latest stable) target (.deb + binary) with the isolated image.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IMAGE="${OPENRA3_DEBIAN_IMAGE:-openra3-debian:local}"
BUILD_DIR="${1:-build/debian}"
docker build --target dev -f "$ROOT/Dockerfile.debian" -t "$IMAGE" "$ROOT"
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake -S . -B "$BUILD_DIR" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-19/lib/libc++.modules.json \
-DOPENRA3_DISTRO_TAG=debian13
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake --build "$BUILD_DIR" -j
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" bash -c "cd $BUILD_DIR && cpack -G DEB"
echo "Debian: $ROOT/$BUILD_DIR/bin/openra3 (+ .deb)"
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Build the Linux/ARM64 target (.deb + binary) with the isolated cross image.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IMAGE="${OPENRA3_LINUX_ARM64_IMAGE:-openra3-linux-arm64:local}"
BUILD_DIR="${1:-build/linux-arm64}"
docker build --target dev -f "$ROOT/Dockerfile.linux-arm64" -t "$IMAGE" "$ROOT"
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake -S . -B "$BUILD_DIR" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/clang-aarch64-linux-gnu.cmake \
-DCMAKE_BUILD_TYPE=Release -DOPENRA3_DISTRO_TAG=ubuntu26.04
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake --build "$BUILD_DIR" -j
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" bash -c "cd $BUILD_DIR && cpack -G DEB"
echo "Linux arm64: $ROOT/$BUILD_DIR/bin/openra3 (+ .deb)"
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Build the Windows/ARM64 target (portable .zip) with the isolated cross image.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
IMAGE="${OPENRA3_WINDOWS_ARM64_IMAGE:-openra3-windows-arm64:local}"
BUILD_DIR="${1:-build/windows-arm64}"
docker build --target dev -f "$ROOT/Dockerfile.win-arm64" -t "$IMAGE" "$ROOT"
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake -S . -B "$BUILD_DIR" -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-aarch64.cmake \
-DCMAKE_BUILD_TYPE=Release
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" cmake --build "$BUILD_DIR" -j
docker run --rm -v "$ROOT:/work" -w /work "$IMAGE" bash -c "cd $BUILD_DIR && cpack -G ZIP"
echo "Windows arm64: $ROOT/$BUILD_DIR/bin/openra3.exe (+ .zip)"