aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil A. Overbeck <emil.a.overbeck@gmail.com>2026-07-19 03:46:27 +0200
committerEmil A. Overbeck <emil.a.overbeck@gmail.com>2026-07-19 03:46:27 +0200
commitff85499d5567c36ce63e2d7903d5f872fd9aef1d (patch)
treeb15b1cab27e5bb5a2bb8d797905e47d08bcca889
parent37b5f7c8bd0b4c0e297614577edb7b634c13d700 (diff)
downloadforts_clone-ff85499d5567c36ce63e2d7903d5f872fd9aef1d.tar.gz
forts_clone-ff85499d5567c36ce63e2d7903d5f872fd9aef1d.zip
Makefile
-rw-r--r--CLAUDE.md35
-rw-r--r--Makefile84
-rw-r--r--README.md35
-rwxr-xr-xscripts/build.sh40
4 files changed, 125 insertions, 69 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index 23aec69..4234a9b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -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
diff --git a/README.md b/README.md
index 9d43332..911e32e 100644
--- a/README.md
+++ b/README.md
@@ -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