# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # 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 one port: any of JOEY_PORTS (make/common.mk) # make - one of that port's goals: iigs-game-disk GAME=NAME, # iigs-verify-game-disk, iigs-game-disks # make JOEY_PORT= # any target of that port, a file among them # make clean remove the project's build/ (clean-: one port's) # # Outputs land in the project's build//, 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/.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=. # ($(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- help" @echo " - (iigs-game-disk GAME=NAME, iigs-verify-game-disk, iigs-game-disks)" @echo " JOEY_PORT= (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