Files
LithosAnanake/Makefile
T
rajamesandClaude Opus 5.5 1a4b163861 feat(boards): both systems on every board image, chosen at boot -- system=v3 or system=v4
boards/BRINGUP.md A6, FABRIC-3 SXLIII (ruled: one image, switch at boot).
A STARFORTH_V4 kernel carries v3 too; system= in the boot arguments
chooses, else the build's default (V4_DEFAULT: 1 for plain STARFORTH_V4
builds as before, 0 for board images).  make boot_image builds both and
always writes starforth.cfg / cmdline.txt with system=v3 first, and cleans
its ISA's objects first -- that clean was removing build/<arch>/SER5, not
the kernel's objects, until fixed here.

Each ISA: v3 by default (hash unchanged), v4 with system=v4 (538/538).
The SER5 image under OVMF: v3 as built, v4 after a one-word edit on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:11:47 -04:00

167 lines
6.8 KiB
Makefile

# ==============================================================================
# LithosAnanke / StarForth -- top-level Makefile
#
# Thin dispatcher. The real build lives in:
# v3/Makefile -- hosted StarForth v3 (Linux userland VM, POST, DoE)
# kernel/Makefile -- LithosAnanke kernel (UEFI loader, kernel ELF, QEMU)
# boards/<board>/ -- one directory per physical target (board.mk + boot files)
# docs/book/Makefile -- the single LaTeX book (build/docs/*.pdf)
# Every sub-make runs from this directory, so paths are always repo-relative.
#
# TARGET is either a board (SER5 RASPI MILKV ZYNQ7020), a hosted v3 profile
# (standard fast fastest turbo asan ...), or empty:
#
# make [all] every board that has a kernel port, the
# hosted v3 build, and the book
# make [all] TARGET=<board> that board's boot image + its book
# make [all] TARGET=<profile> hosted v3 build with that profile
#
# make boot_image TARGET=<board> only the board's boot image
# make boot_images every board that has a kernel port
# make docs [TARGET=<board>] the book; a board adds its appendix
#
# make clean all of build/ except build/cache/
# make clean TARGET=<board> the board's image + book and its ISA's kernel objects
# make clean TARGET=<profile> build/<arch>/<profile> for every arch
# make clean-docs build/docs/
#
# make kernel ARCH=<arch> [GOAL=g] kernel/Makefile goal (default: all)
# make boards list boards and whether they can be built
# make <other goal> goes to v3/Makefile (make help-hosted)
# ==============================================================================
# Board name (as typed on the command line) -> boards/ directory.
BOARD_DIR_SER5 := ser5
BOARD_DIR_RASPI := raspi
BOARD_DIR_MILKV := milkv
BOARD_DIR_ZYNQ7020 := zynq7020
BOARDS := SER5 RASPI MILKV ZYNQ7020
empty :=
space := $(empty) $(empty)
board_field = $(if $(BOARD_DIR_$(1)),$(shell sed -n 's/^$(2) *:= *//p' boards/$(BOARD_DIR_$(1))/board.mk))
board_arch = $(call board_field,$(1),BOARD_ARCH)
# A board can be built once its ISA's kernel port exists.
board_ready = $(if $(call board_arch,$(1)),$(wildcard kernel/src/arch/$(call board_arch,$(1))/.))
READY_BOARDS := $(foreach b,$(BOARDS),$(if $(call board_ready,$(b)),$(b)))
UNREADY_BOARDS := $(filter-out $(READY_BOARDS),$(BOARDS))
TARGET := $(strip $(TARGET))
BOARD_DIR := $(if $(TARGET),$(BOARD_DIR_$(TARGET)))
SUBMAKE := $(MAKE) --no-print-directory
.DEFAULT_GOAL := all
.PHONY: all boot_image boot_images docs clean clean-docs kernel boards help help-hosted
# ------------------------------------------------------------------------------
# all
# ------------------------------------------------------------------------------
ifeq ($(TARGET),)
all:
@for b in $(READY_BOARDS); do \
$(SUBMAKE) boot_image TARGET=$$b || exit 1; \
done
@$(SUBMAKE) -f v3/Makefile all
@$(SUBMAKE) docs
@echo ""
@echo "Built:"
@for b in $(READY_BOARDS); do \
d=$$(echo $$b | tr A-Z a-z); ls build/boards/$$d/*.img | sed 's/^/ /'; \
done
@echo " build/docs/LithosAnanke.pdf"
@$(foreach b,$(UNREADY_BOARDS),echo "Skipped $(b): needs kernel/src/arch/$(call board_arch,$(b)), which does not exist yet";)
else ifneq ($(BOARD_DIR),)
all:
@$(SUBMAKE) boot_image TARGET=$(TARGET)
@$(SUBMAKE) docs TARGET=$(TARGET)
else
all:
@$(SUBMAKE) -f v3/Makefile all TARGET=$(TARGET)
endif
# ------------------------------------------------------------------------------
# boot images
# ------------------------------------------------------------------------------
boot_image:
@if [ -z "$(BOARD_DIR)" ]; then \
echo "Usage: make boot_image TARGET=<$(subst $(space),|,$(BOARDS))>"; \
[ -z "$(TARGET)" ] || echo "Unknown board TARGET='$(TARGET)'"; \
exit 1; \
fi
@if [ -z "$(call board_ready,$(TARGET))" ]; then \
echo "Error: $(TARGET) needs the $(call board_arch,$(TARGET)) kernel port (kernel/src/arch/$(call board_arch,$(TARGET))), which does not exist yet."; \
echo " $(call board_field,$(TARGET),BOARD_DESC)"; \
exit 1; \
fi
@# Both systems in one image, v3 unless the boot arguments say system=v4
@# (boards/BRINGUP.md A6, ruled 2026-10-14). A clean build every time: the
@# kernel objects are shared with `make qemu`, and make does not see a
@# change of compile flags -- an image could otherwise carry objects built
@# without v4, or without the bring-up console.
@$(SUBMAKE) -f kernel/Makefile ARCH=$(call board_arch,$(TARGET)) TARGET=kernel clean
@$(SUBMAKE) -f kernel/Makefile \
BOARD=$(BOARD_DIR) ARCH=$(call board_arch,$(TARGET)) TARGET=kernel \
STARFORTH_V4=1 V4_DEFAULT=0 boot_image
boot_images:
@for b in $(READY_BOARDS); do \
$(SUBMAKE) boot_image TARGET=$$b || exit 1; \
done
@$(foreach b,$(UNREADY_BOARDS),echo "Skipped $(b): needs kernel/src/arch/$(call board_arch,$(b)), which does not exist yet";)
# ------------------------------------------------------------------------------
# docs
# ------------------------------------------------------------------------------
docs:
@if [ -n "$(TARGET)" ] && [ -z "$(BOARD_DIR)" ]; then \
echo "Error: make docs takes TARGET=<$(subst $(space),|,$(BOARDS))> or no TARGET; '$(TARGET)' is not a board."; \
exit 1; \
fi
@$(SUBMAKE) -f docs/book/Makefile BOARD=$(BOARD_DIR) BOARD_NAME=$(TARGET)
clean-docs:
rm -rf build/docs
# ------------------------------------------------------------------------------
# clean
# ------------------------------------------------------------------------------
ifeq ($(TARGET),)
clean:
@if [ -d build ]; then find build -mindepth 1 -maxdepth 1 ! -name cache -exec rm -rf {} +; fi
rm -f v3/include/version.h
rm -f v3/src/*.gcda v3/src/*.gcno v3/src/word_source/*.gcda v3/src/word_source/*.gcno
@echo "Cleaned build/ (kept build/cache/)"
else ifneq ($(BOARD_DIR),)
clean:
rm -rf build/boards/$(BOARD_DIR) build/$(call board_arch,$(TARGET))/kernel build/docs/$(BOARD_DIR) \
build/docs/LithosAnanke-$(BOARD_DIR).pdf
else
clean:
rm -rf build/*/$(TARGET)
endif
# ------------------------------------------------------------------------------
# misc
# ------------------------------------------------------------------------------
GOAL ?= all
kernel:
@$(SUBMAKE) -f kernel/Makefile TARGET=kernel $(GOAL)
boards:
@$(foreach b,$(BOARDS),printf ' %-9s %-8s %s\n' "$(b)" \
"$(if $(call board_ready,$(b)),ready,no port)" "$(call board_field,$(b),BOARD_DESC)";)
help:
@sed -n '/^# TARGET is/,/^# =====/p' Makefile | sed '$$d; s/^# \{0,1\}//'
help-hosted:
@$(SUBMAKE) -f v3/Makefile help
# Everything else is the hosted v3 build, unchanged. (The empty Makefile
# rule stops the match-anything rule from trying to remake this file.)
Makefile: ;
%:
@$(SUBMAKE) -f v3/Makefile $@