v0.2.0: clang + import std; isolated Windows cross-build (llvm-mingw + SDL3)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
# OpenRA3
|
||||
|
||||
A from-scratch, portable re-implementation of **Command & Conquer: Red Alert 3**
|
||||
in **C++26** using **C++ modules**, built with **GCC 16**.
|
||||
in **C++26** using **C++ modules** and `import std;`, built with **Clang** for
|
||||
both **Linux** and **Windows**.
|
||||
|
||||
Red Alert 3 runs SAGE 2.0. EA never released that engine's C++ source, but it
|
||||
did open-source the closely related SAGE 1.0 engine as
|
||||
@@ -17,11 +18,13 @@ Ghidra.
|
||||
|
||||
## Status
|
||||
|
||||
OpenRA3 is at **v0.0.1**. The engine compiles and runs headless, and a **minimal
|
||||
OpenRA3 is at **v0.2.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 earning credits,
|
||||
training units and fighting until one base falls. The map and match state can be
|
||||
**rendered** to a window (SDL3) or to an image.
|
||||
**rendered** to a window (SDL3) or to an image. The whole tree builds for
|
||||
**Linux** (clang + libc++) and cross-compiles to **Windows** (`openra3.exe` +
|
||||
`SDL3.dll`) with llvm-mingw — both using C++26 modules and `import std;`.
|
||||
|
||||
```text
|
||||
$ openra3 skirmish --game-dir "/game" --map map_mp_2_feasel4
|
||||
@@ -73,19 +76,48 @@ built-in test map so the project still builds and runs in CI.
|
||||
| `tests/ra3_tests.cpp` | smoke tests (run via `ctest`) |
|
||||
| `tools/` | reference fetch + Ghidra-driven reconstruction helpers |
|
||||
| `docs/` | architecture, reverse-engineering notes, roadmap |
|
||||
| `Dockerfile` | `dev` (toolchain) and `deploy` (runtime) targets |
|
||||
| `.gitlab-ci.yml` | build → test → package pipeline |
|
||||
| `Dockerfile` | Linux build image (`dev` toolchain + `deploy` runtime) |
|
||||
| `Dockerfile.win` | isolated Windows cross-build image (llvm-mingw + SDL3 MinGW) |
|
||||
| `cmake/toolchains/` | `llvm-mingw-x86_64.cmake` cross toolchain |
|
||||
| `scripts/` | `build-linux.sh` / `build-windows.sh` one-shot builders |
|
||||
| `.gitlab-ci.yml` | build both targets → test → package pipeline |
|
||||
|
||||
## Why Clang + `import std;`
|
||||
|
||||
The engine never `#include`s the standard library: every module does
|
||||
`import std;`. CMake's support for that (`CXX_MODULE_STD`) works today with
|
||||
Clang + libc++. Linux uses the distro clang (LLVM 21); Windows cross-compiles
|
||||
with [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) (clang 23 + libc++ +
|
||||
the libc++ `std` module). The two toolchains live in **separate images** so
|
||||
their compilers and standard libraries never interfere.
|
||||
|
||||
## Build
|
||||
|
||||
The host needs no toolchain: build inside the container.
|
||||
The host needs no toolchain: each target builds inside its own image.
|
||||
|
||||
```bash
|
||||
docker build --target dev -t openra3-dev:local .
|
||||
# Linux -> build/linux/bin/openra3
|
||||
scripts/build-linux.sh
|
||||
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-dev:local cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-dev:local cmake --build build -j
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-dev:local ctest --test-dir build --output-on-failure
|
||||
# Windows -> build/windows/bin/openra3.exe (+ SDL3.dll)
|
||||
scripts/build-windows.sh
|
||||
```
|
||||
|
||||
Or drive Docker directly:
|
||||
|
||||
```bash
|
||||
docker build --target dev -t openra3-linux:local .
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-linux:local \
|
||||
cmake -S . -B build/linux -G Ninja -DCMAKE_BUILD_TYPE=Release
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-linux:local cmake --build build/linux -j
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-linux:local ctest --test-dir build/linux --output-on-failure
|
||||
|
||||
docker build -f Dockerfile.win --target dev -t openra3-windows:local .
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-windows:local \
|
||||
cmake -S . -B build/windows -G Ninja \
|
||||
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/llvm-mingw-x86_64.cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
docker run --rm -v "$PWD:/work" -w /work openra3-windows:local cmake --build build/windows -j
|
||||
```
|
||||
|
||||
Behind a slow or blocked mirror, pass `--build-arg APT_MIRROR=<url>`.
|
||||
@@ -94,14 +126,17 @@ Behind a slow or blocked mirror, pass `--build-arg APT_MIRROR=<url>`.
|
||||
|
||||
```bash
|
||||
# list the maps in your install
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-dev:local \
|
||||
./build/bin/openra3 maps --game-dir /game
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-linux:local \
|
||||
/work/build/linux/bin/openra3 maps --game-dir /game
|
||||
|
||||
# play a headless skirmish on a real map
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-dev:local \
|
||||
./build/bin/openra3 skirmish --game-dir /game --map map_mp_2_feasel4 --seed 7
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" openra3-linux:local \
|
||||
/work/build/linux/bin/openra3 skirmish --game-dir /game --map map_mp_2_feasel4 --seed 7
|
||||
```
|
||||
|
||||
The Windows build is a native `openra3.exe` — copy it next to `SDL3.dll` and run
|
||||
it from `cmd`/PowerShell, e.g. `openra3.exe skirmish --game-dir "C:\Red Alert 3"`.
|
||||
|
||||
`--frames N` caps the simulation length (default 15 minutes of game time at
|
||||
30 Hz). The result is deterministic for a given map and seed.
|
||||
|
||||
@@ -113,10 +148,13 @@ The renderer draws the map's own overview art, a world grid and the match state
|
||||
**Offscreen image** (works anywhere, no display needed):
|
||||
|
||||
```bash
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" -v "$PWD/out:/out" openra3-dev:local \
|
||||
/work/build/bin/openra3 render --game-dir /game --map map_mp_2_feasel4 --out /out/map.bmp
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" -v "$PWD/out:/out" openra3-linux:local \
|
||||
/work/build/linux/bin/openra3 render --game-dir /game --map map_mp_2_feasel4 --out /out/map.bmp
|
||||
```
|
||||
|
||||
On Windows the same command runs natively: `openra3.exe render --game-dir
|
||||
"C:\Red Alert 3" --map map_mp_2_feasel4` opens an SDL3 window.
|
||||
|
||||
**Interactive window** (SDL3; drag to pan, wheel to zoom, Esc to quit). In a
|
||||
container you need an X server on the host — on Windows run
|
||||
[VcXsrv](https://sourceforge.net/projects/vcxsrv/) and launch it with "Disable
|
||||
@@ -124,7 +162,7 @@ access control", then:
|
||||
|
||||
```bash
|
||||
docker run --rm -v "/path/to/Red Alert 3:/game:ro" -e DISPLAY=host.docker.internal:0.0 \
|
||||
openra3-dev:local /work/build/bin/openra3 render --game-dir /game --map map_mp_2_feasel4
|
||||
openra3-linux:local /work/build/linux/bin/openra3 render --game-dir /game --map map_mp_2_feasel4
|
||||
```
|
||||
|
||||
If no display is available the viewer falls back to writing `openra3_view.bmp`.
|
||||
|
||||
Reference in New Issue
Block a user