joeylib2/make/project.mk

97 lines
4.3 KiB
Makefile

# Build programs that live outside JoeyLib, with JoeyLib's toolchains,
# library, asset tools and packaging -- the same rules JoeyLib's own examples
# use. A project's Makefile:
#
# JOEYLIB ?= ../joeylib
# include $(JOEYLIB)/make/project.mk
#
# PROGRAMS := MYGAME
# MYGAME_SRCS := mygame.c world.c
# ...the variables make/programs.mk lists, and the project's own rules for
# its DATA files (bakes), which may use what make/programs.mk names...
#
# include $(JOEYLIB)/make/programs.mk
#
# Paths in it are relative to the project's directory: run make there.
#
# make every port the programs build for whose toolchain
# is installed (ports without one are noted, skipped)
# make <port> one port: iigs amiga atarist dos x68000 dvx
# make <port>-<goal> one of that port's goals: iigs-game-disk GAME=NAME,
# iigs-verify-game-disk, iigs-game-disks
# make JOEY_PORT=<port> <target>
# any target of that port, a file among them
# make clean remove the project's build/ (clean-<port>: one port's)
#
# Outputs land in the project's build/<port>/, laid out like JoeyLib's own:
# programs in bin/ (joey-run --project DIR finds them by name), DATA staged
# beside them, the IIgs data and game disks in bin/ too. JoeyLib's library
# and host tools are built on demand where JoeyLib keeps them (JOEY_BUILD,
# make/common.mk), shared with JoeyLib's own build and every other project;
# make JOEY_BUILD=DIR keeps them out of the JoeyLib checkout. PROJECT_BUILD=DIR
# moves the project's own.
#
# How it works: each port has its own compiler and its own make variables,
# so one make process cannot hold two ports. This level only reads the
# descriptions (for the ports they build for) and runs make on the same
# Makefile again with JOEY_PORT set, once per port; in that run this file
# includes make/<port>.mk -- the port's library rules and its programRules
# template -- and make/programs.mk at the bottom instantiates the template
# for every program.
JOEY_PROJECT := $(abspath $(dir $(firstword $(MAKEFILE_LIST))))
JOEY_MAKE_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
ifeq ($(JOEY_PORT),)
include $(JOEY_MAKE_DIR)common.mk
# Read by make/programs.mk, which then makes no rules: there is no port here.
JOEY_DISPATCH := 1
PROJECT_MAKEFILE := $(abspath $(firstword $(MAKEFILE_LIST)))
# This Makefile again, quietly: $(MAKE) $(PORT_MAKE) JOEY_PORT=<port>.
# ($(MAKE) itself stays in each recipe: that is how make knows the line runs
# make, to share its job slots with it and to run it under -n.)
PORT_MAKE := --no-print-directory -f $(PROJECT_MAKEFILE)
# The ports the programs build for (each one's ID_PORTS, by default every
# port), in JOEY_PORTS order. Expanded in recipes: the descriptions come after.
PROJECT_PORTS = $(filter $(sort $(foreach p,$(PROGRAMS),$(or $($(p)_PORTS),$(JOEY_PORTS)))),$(JOEY_PORTS))
PROJECT_BUILDING = $(filter $(JOEY_PORTS_INSTALLED),$(PROJECT_PORTS))
.DEFAULT_GOAL := all
.PHONY: all clean help $(JOEY_PORTS) $(addprefix clean-,$(JOEY_PORTS))
# One port after another: each is a make of its own, already parallel inside
# under -j, and DVX shares the DOS port's asset bakes.
all:
@$(foreach p,$(filter-out $(PROJECT_BUILDING),$(PROJECT_PORTS)),echo "note: $(p) skipped: its toolchain is not installed (./install.sh doctor)";) true
@$(if $(PROJECT_BUILDING),,echo "No toolchain for any of: $(PROJECT_PORTS). Run: ./install.sh install toolchains" >&2; exit 1)
@set -e; for p in $(PROJECT_BUILDING); do $(MAKE) $(PORT_MAKE) JOEY_PORT=$$p; done
$(JOEY_PORTS):
@$(MAKE) $(PORT_MAKE) JOEY_PORT=$@
# make iigs-game-disk and the like: the goal, run in its port's make.
$(foreach p,$(JOEY_PORTS),$(eval $(p)-%: ; @$$(MAKE) $$(PORT_MAKE) JOEY_PORT=$(p) $$@))
clean:
rm -rf $(PROJECT_BUILD)
$(addprefix clean-,$(JOEY_PORTS)):
rm -rf $(PROJECT_BUILD)/$(patsubst clean-%,%,$@)
help:
@echo "Ports this project builds for: $(PROJECT_PORTS) (installed: $(PROJECT_BUILDING))"
@echo "Targets: all $(JOEY_PORTS) clean clean-<port> help"
@echo " <port>-<goal> (iigs-game-disk GAME=NAME, iigs-verify-game-disk, iigs-game-disks)"
@echo " JOEY_PORT=<port> <target> (any target of one port)"
else
# One port: its library and program rules. The project's descriptions follow,
# then make/programs.mk.
include $(JOEY_MAKE_DIR)$(JOEY_PORT).mk
.DEFAULT_GOAL := all
endif