diff options
| -rw-r--r-- | CLAUDE.md | 35 | ||||
| -rw-r--r-- | Makefile | 84 | ||||
| -rw-r--r-- | README.md | 35 | ||||
| -rwxr-xr-x | scripts/build.sh | 40 |
4 files changed, 125 insertions, 69 deletions
@@ -15,27 +15,32 @@ Read `research/` and `requirements/` for the deep dives; this is the map. in `/usr/local`, defined by `Containerfile`). The **binary runs on the host** (needs the host's SDL3 + a display). -```bash -# one-time (and after editing Containerfile): build the dev image -podman build -t forts-clone-dev . - -# configure + compile (from repo root) -podman run --rm -v "$PWD":/src:Z --userns=keep-id localhost/forts-clone-dev:latest \ - bash -c "cd /src && meson setup builddir && meson compile -C builddir" +**Use the `Makefile` — don't type raw `podman` commands.** It wraps the whole +workflow and puts each half in the right place (compile in the container, run on +the host). Run everything from the repo root. -# run ON THE HOST, from the repo root (data/ is resolved relative to CWD) -./builddir/forts-clone +```bash +make image # one-time, and after editing Containerfile +make build # compile in the container (default target; configures on first use) +make run # compile, then run the game on the host +make check # compile + validate the Lua data <- do this before claiming done +make help # every target ``` -- `scripts/build.sh` wraps the container build/compile. +Also available: `make reconfigure` (after editing `meson.build`, since meson +refuses a plain re-setup), `make shell` (interactive container), `make clean`, +`make clean-image`. For a from-scratch rebuild, `make clean && make build`. + - Lua is **statically linked** (Containerfile builds `liblua.a`) so the container-built binary runs on any host regardless of its lua soname. - If you add a dependency: add it to `Containerfile` **at the end** (so cached layers don't rebuild) unless it must come earlier. **Verify without a display:** you can't run the GUI in the container, so validate -by (a) compiling clean, and (b) running Lua data files through a standalone `lua` -to check they parse. Do both after changes. +by (a) compiling clean and (b) parsing the Lua data. `make check` does both. +Note mods must be validated **layered** (base file first) because they +`table.insert` into globals the base defines — `make check-lua` already does +this; running a mod file standalone always fails. --- @@ -180,9 +185,9 @@ consult it before deciding what to build; don't guess from vibes. Don't commit feature work straight to `main`; open a branch, then merge. - **Commit/push only when asked.** End commit messages with the `Co-Authored-By: Claude ...` trailer. -- **Build before you claim done** (compile in the container) and validate any Lua - you touched with a standalone `lua` run. Be honest about what you couldn't - verify (the GUI can't run headless here). +- **Build before you claim done:** run `make check` (compiles in the container + and parses the Lua data). Be honest about what you couldn't verify — the GUI + can't run headless here, so anything visual needs a human to look at it. - **Keep the status docs in sync — same commit as the change.** When you land, extend or remove a feature, update all three in the commit that changes the behaviour, not later: diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df2eb4d --- /dev/null +++ b/Makefile @@ -0,0 +1,84 @@ +# LibreForts build helpers — thin wrappers around the Podman workflow. +# +# Everything COMPILES inside the container (Fedora + every dependency prebuilt +# in /usr/local, see Containerfile). The binary RUNS on the host, which supplies +# SDL3 and a display. `make run` does both halves in the right place. +# +# Recipe lines are indented with TABs; make requires it. + +IMAGE := forts-clone-dev +BUILDDIR := builddir +BIN := $(BUILDDIR)/forts-clone + +# Run a command in the dev image with the repo bind-mounted at /src. +PODMAN_RUN := podman run --rm -v "$(CURDIR)":/src:Z --userns=keep-id \ + localhost/$(IMAGE):latest bash -c + +.DEFAULT_GOAL := build +.PHONY: help image build reconfigure run check check-lua shell clean clean-image + +help: + @echo "LibreForts:" + @echo " make image build the Podman dev image (once, and after" + @echo " editing Containerfile)" + @echo " make build compile in the container (default target)" + @echo " make run compile, then run the game on the host" + @echo " make check compile + validate the Lua data (do this before" + @echo " claiming a change works)" + @echo " make check-lua validate the Lua data only" + @echo " make reconfigure re-run meson setup, after editing meson.build" + @echo " make shell interactive shell in the dev container" + @echo " make clean remove $(BUILDDIR)" + @echo " make clean-image remove the Podman dev image" + +image: + podman build -t $(IMAGE) . + +# Configures builddir on first use, then compiles. Re-running is cheap. +build: + $(PODMAN_RUN) 'cd /src && { [ -f $(BUILDDIR)/build.ninja ] || \ + meson setup $(BUILDDIR); } && meson compile -C $(BUILDDIR)' + +# meson refuses a plain re-setup on a configured dir; this is the escape hatch. +reconfigure: + $(PODMAN_RUN) 'cd /src && meson setup $(BUILDDIR) --reconfigure && \ + meson compile -C $(BUILDDIR)' + +# Runs on the HOST, from the repo root: data/ is resolved relative to CWD. +run: build + ./$(BIN) + +check: build check-lua + +# The GUI cannot run headless here, so parsing the Lua is the other half of +# "it works". Mods are validated LAYERED (base file first), because they +# table.insert into globals the base defines — running one alone always fails. +check-lua: + @command -v lua >/dev/null 2>&1 || \ + { echo "check-lua: no 'lua' on the host, skipping"; exit 0; } + @set -e; \ + for f in data/*.lua; do \ + lua -e "dofile('$$f')"; \ + echo " OK $$f"; \ + done; \ + for f in data/mods/*/*.lua; do \ + [ -e "$$f" ] || continue; \ + base="data/$$(basename "$$f")"; \ + if [ -f "$$base" ]; then \ + lua -e "dofile('$$base'); dofile('$$f')"; \ + echo " OK $$f (layered on $$base)"; \ + else \ + lua -e "dofile('$$f')"; \ + echo " OK $$f"; \ + fi; \ + done + +shell: + podman run --rm -it -v "$(CURDIR)":/src:Z --userns=keep-id \ + localhost/$(IMAGE):latest bash + +clean: + rm -rf $(BUILDDIR) + +clean-image: + -podman rmi localhost/$(IMAGE):latest @@ -13,16 +13,27 @@ and EnTT are planned but not yet wired up. ### Container (reproducible, any distro) +The `Makefile` wraps the Podman workflow. Run it from the repo root: + ```sh -podman build -t forts-clone-dev . -podman run --rm -v "$PWD":/src:Z --userns=keep-id localhost/forts-clone-dev:latest \ - sh -c "cd /src && meson setup builddir && meson compile -C builddir" -./builddir/forts-clone # run from repo root +make image # one-time, and after editing Containerfile +make run # compile in the container, then launch on the host ``` +| Target | What it does | +|---|---| +| `make build` | compile in the container (default; configures on first use) | +| `make run` | compile, then run the game on the host | +| `make check` | compile + validate the Lua data | +| `make reconfigure` | re-run `meson setup` after editing `meson.build` | +| `make shell` | interactive shell in the dev container | +| `make clean` / `make clean-image` | remove `builddir/` / the dev image | + The container builds every dependency into `/usr/local` and links Lua -statically, so the resulting binary runs on any host. You still run it on the -host (it needs the host's SDL3 and a display). +statically, so the resulting binary runs on any host. Compilation happens in the +container, but the game runs on the host, which supplies SDL3 and a display; +`make run` handles both halves. Run from the repo root either way, since `data/` +is resolved relative to the working directory. ### Local (Arch Linux) @@ -30,6 +41,10 @@ host (it needs the host's SDL3 and a display). libraries the code actually uses. bgfx, SoLoud, ENet and EnTT are part of the planned stack but not yet wired up, so they are not required to build. +The `make` targets above all go through Podman, so a native build drives meson +directly. (`make check-lua` is the exception: it runs on the host and works +either way.) + ```sh # repo packages sudo pacman -S --needed meson ninja gcc pkgconf sdl3 lua54 glm box2d @@ -45,14 +60,6 @@ meson compile -C builddir Native builds link Lua dynamically against the system `lua54`, which is fine when you build and run on the same machine. -### Removing the container image - -```sh -podman rmi localhost/forts-clone-dev:latest # drop the dev image -podman image prune -f # drop dangling build layers -rm -rf builddir # meson dir, reconfigure after -``` - ## Assets The repo ships CC0 placeholders only. If you own Forts, real textures load at diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100755 index 6027e75..0000000 --- a/scripts/build.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# Build and run the Forts Clone inside a podman container. -# Usage: ./scripts/build.sh [--shell] - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -IMAGE_NAME="forts-clone-dev" - -cd "$PROJECT_DIR" - -# Build container image (cached) -echo "==> Building container image..." -podman build -t "$IMAGE_NAME" . - -if [ "${1:-}" = "--shell" ]; then - echo "==> Starting shell in container..." - exec podman run -it --rm \ - -v "$PROJECT_DIR":/src:Z \ - --userns=keep-id \ - "$IMAGE_NAME" \ - bash -else - echo "==> Configuring and building..." - podman run -it --rm \ - -v "$PROJECT_DIR":/src:Z \ - --userns=keep-id \ - "$IMAGE_NAME" \ - bash -c " - meson setup builddir \ - --buildtype=debugoptimized \ - -Dwarning_level=3 \ - -Dcpp_std=c++20 \ - --wipe - meson compile -C builddir -j$(nproc) - " - echo - echo "==> Build complete. Run with: ./builddir/forts-clone" -fi |
