171 lines
10 KiB
Makefile
171 lines
10 KiB
Makefile
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# Shared variables used by per-target Makefile fragments.
|
|
#
|
|
# Source this only via the per-target make file (make/iigs.mk etc), which
|
|
# sets PLATFORM first; make/tools.mk and the top Makefile include it without.
|
|
|
|
REPO_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
|
|
|
|
# Tool paths (AMIGA_CC, LLVM816_ROOT, LIBXMP_DIR, ...) come from the file
|
|
# install.sh generates; it is the only place they are defined.
|
|
-include $(REPO_DIR)/toolchains/config.mk
|
|
|
|
# $(call requireTool,FILE,INSTALL-TARGET): stop with a clear message when a
|
|
# port's compiler is missing, instead of letting recipes run an empty
|
|
# command. Goals that only clean need no toolchain. The missing path is not
|
|
# printed: with nothing installed it is empty or a bare suffix, and
|
|
# `./install.sh doctor` names exactly what is wrong.
|
|
requireTool = $(if $(filter-out clean%,$(or $(MAKECMDGOALS),all)),$(if $(wildcard $(1)),,$(error $(2) is not installed; run: ./install.sh install $(2))))
|
|
|
|
# Letter case, for the port tags (IIGS) and the program names each port
|
|
# derives from a program's id (Hello on the Amiga, hello on DVX).
|
|
lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$(1)))))))))))))))))))))))))))
|
|
uc = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(1)))))))))))))))))))))))))))
|
|
capFirst = $(patsubst a%,A%,$(patsubst b%,B%,$(patsubst c%,C%,$(patsubst d%,D%,$(patsubst e%,E%,$(patsubst f%,F%,$(patsubst g%,G%,$(patsubst h%,H%,$(patsubst i%,I%,$(patsubst j%,J%,$(patsubst k%,K%,$(patsubst l%,L%,$(patsubst m%,M%,$(patsubst n%,N%,$(patsubst o%,O%,$(patsubst p%,P%,$(patsubst q%,Q%,$(patsubst r%,R%,$(patsubst s%,S%,$(patsubst t%,T%,$(patsubst u%,U%,$(patsubst v%,V%,$(patsubst w%,W%,$(patsubst x%,X%,$(patsubst y%,Y%,$(patsubst z%,Z%,$(1)))))))))))))))))))))))))))
|
|
|
|
# The ports, and which of them can build here: a port is available when its
|
|
# real compiler binary is installed (DVX also needs the DVX SDK). The top
|
|
# Makefile's `make` and a project's `make` build exactly these.
|
|
JOEY_PORTS := iigs amiga atarist ste dos x68000 dvx sdl3 web win32 win16 psp haiku haiku32 beos
|
|
HAVE_IIGS := $(if $(wildcard $(LLVM816_ROOT)/tools/llvm-mos-build/bin/clang),1)
|
|
HAVE_AMIGA := $(if $(wildcard $(AMIGA_CC)),1)
|
|
HAVE_ATARIST := $(if $(wildcard $(ST_CC)),1)
|
|
HAVE_STE := $(HAVE_ATARIST)
|
|
HAVE_DOS := $(if $(wildcard $(DOS_CC)),1)
|
|
HAVE_X68000 := $(if $(wildcard $(X68K_ROOT)/bin/m68k-xelf-gcc),1)
|
|
HAVE_DVX := $(if $(and $(wildcard $(DOS_CC)),$(wildcard $(DVX_SDK)/sdk.mk)),1)
|
|
HAVE_SDL3 := $(if $(wildcard $(SDL3_DIR)/lib/libSDL3.a),1)
|
|
HAVE_WEB := $(if $(and $(wildcard $(EMCC)),$(wildcard $(SDL3_WEB_DIR)/lib/libSDL3.a)),1)
|
|
HAVE_WIN32 := $(if $(wildcard $(WIN32_CC)),1)
|
|
HAVE_WIN16 := $(if $(wildcard $(WIN16_WATCOM)/binl64/owcc),1)
|
|
HAVE_PSP := $(if $(and $(wildcard $(PSP_CC)),$(wildcard $(SDL3_PSP_DIR)/lib/libSDL3.a)),1)
|
|
HAVE_HAIKU := $(if $(wildcard $(HAIKU_CROSS)g++),1)
|
|
HAVE_HAIKU32 := $(if $(wildcard $(HAIKU32_ROOT)/cross/bin/i586-pc-haiku-g++),1)
|
|
HAVE_BEOS := $(if $(and $(HAVE_HAIKU32),$(wildcard $(BEOS_R5_SYSROOT)/system-lib/libbe.so)),1)
|
|
JOEY_PORTS_INSTALLED := $(foreach p,$(JOEY_PORTS),$(if $(HAVE_$(call uc,$(p))),$(p)))
|
|
|
|
# Where things are built. JOEY_BUILD holds what is JoeyLib's -- each port's
|
|
# library and the host tools -- and PROJECT_BUILD the programs: for JoeyLib's
|
|
# own examples both are build/. A project (make/project.mk) sets JOEY_PROJECT
|
|
# to its directory, so its programs land in its own build/ while JoeyLib's
|
|
# library is built once, in JoeyLib's. Point JOEY_BUILD elsewhere to keep a
|
|
# project's build out of the JoeyLib checkout altogether.
|
|
JOEY_BUILD ?= $(REPO_DIR)/build
|
|
PROJECT_DIR := $(or $(JOEY_PROJECT),$(REPO_DIR))
|
|
PROJECT_BUILD ?= $(PROJECT_DIR)/build
|
|
# make/tools.mk runs as a separate make; it builds into the same place.
|
|
export JOEY_BUILD
|
|
|
|
INCLUDE_DIR := $(REPO_DIR)/include
|
|
# Machine-specific code lives in src/<machine>/ (iigs, amiga, atarist, dos,
|
|
# x68000, dvx); code shared across machines of one CPU lives in a processor
|
|
# folder (src/m68k, src/x86); the hosted core and its backends in src/hosted
|
|
# (sdl3, web and psp build the same SDL3 backend, natively, for a browser
|
|
# and for the PSP; win32 and win16 their own).
|
|
SRC_DIR := $(REPO_DIR)/src
|
|
SRC_CORE := $(REPO_DIR)/src/core
|
|
SRC_CG := $(REPO_DIR)/src/codegen
|
|
SRC_68K := $(REPO_DIR)/src/m68k
|
|
SRC_X86 := $(REPO_DIR)/src/x86
|
|
EXAMPLES := $(REPO_DIR)/examples
|
|
|
|
# Host tools (make/tools.mk, and a program's own bake tools) build with the
|
|
# host's cc.
|
|
HOST_CC ?= cc
|
|
HOST_CFLAGS := -std=c99 -Wall -Wextra -Werror -O2
|
|
|
|
# Portable C sources for libjoey -- present on every target.
|
|
CORE_C_SRCS := $(wildcard $(SRC_CORE)/*.c)
|
|
|
|
# Generic portable-C op defaults (the src/generic backend) -- present on every
|
|
# target. spriteEmitStub.c is excluded: it is the no-codegen template and
|
|
# redefines jlSpriteCompile / spriteCompiledDraw, which the real
|
|
# src/codegen/spriteCompile.c already provides.
|
|
GENERIC_C_SRCS := $(filter-out %/spriteEmitStub.c, $(wildcard $(SRC_DIR)/generic/*.c))
|
|
|
|
# Common include flags. Per-port code can include port.h / surfaceInternal.h
|
|
# directly because SRC_CORE is in the include path. EXTRA_CFLAGS is the one
|
|
# command-line hook for extra flags on every port (make EXTRA_CFLAGS=-DX);
|
|
# make/iigs.mk, which does not use COMMON_CFLAGS, honours it too.
|
|
COMMON_CFLAGS := -I$(INCLUDE_DIR) -I$(SRC_CORE) -Wall -Wextra -Werror -O2 $(EXTRA_CFLAGS)
|
|
|
|
ifdef PLATFORM
|
|
# One port's directories: its library (BUILD, LIBDIR) is JoeyLib's, its
|
|
# programs (PROGRAM_BUILD, BINDIR) the project's.
|
|
BUILD := $(JOEY_BUILD)/$(PLATFORM)
|
|
LIBDIR := $(BUILD)/lib
|
|
PROGRAM_BUILD := $(PROJECT_BUILD)/$(PLATFORM)
|
|
BINDIR := $(PROGRAM_BUILD)/bin
|
|
PORT_TAG := $(call uc,$(PLATFORM))
|
|
# Baked assets (sprite and tile banks) carry the target they were baked for.
|
|
# DVX shows the DOS port's stage and runs its x86 code, so it takes the DOS
|
|
# bakes; the hosted ports' stage (SDL3, the web, Win32, Win16, the PSP,
|
|
# Haiku, BeOS) is chunky like the DOS one, so they take them too (the cels of a
|
|
# pre-compiled bank, without their code); the STe build is the ST port, so it
|
|
# takes the ST's (same planes, same compiled sprites); every other port its
|
|
# own.
|
|
ASSET_PLATFORM := $(if $(filter dvx sdl3 web win32 win16 psp haiku haiku32 beos,$(PLATFORM)),dos,$(if $(filter ste,$(PLATFORM)),atarist,$(PLATFORM)))
|
|
# The host sprite pre-compiler for this port's bakes (.spr -> .spc); its rule
|
|
# is make/programs.mk's.
|
|
SPRITEBAKE := $(JOEY_BUILD)/tools/spritebake-$(ASSET_PLATFORM)
|
|
endif
|
|
|
|
# ---- programs -----------------------------------------------------------------
|
|
# What a program's variables mean is listed in make/programs.mk. These are the
|
|
# lookups that file and the program descriptions use; each port sets
|
|
# PROGRAM_EXT, PROGRAM_FOLDERS (programs may ship in a folder of their own),
|
|
# PROGRAM_DATA_APART (DATA is staged apart from the program, for the
|
|
# packager) and PROGRAM_OPTIONAL_APART (optional DATA apart again), and may
|
|
# redefine programNameRule, programDir, programBin and programTarget.
|
|
|
|
# $(call programVar,ID,VAR): the program's VAR on this port -- ID_<PORT>_VAR
|
|
# when that is defined (even empty), else ID_VAR.
|
|
programVar = $(if $(filter undefined,$(origin $(1)_$(PORT_TAG)_$(2))),$($(1)_$(2)),$($(1)_$(PORT_TAG)_$(2)))
|
|
|
|
# $(call programOnPort,ID): ID when it is built for this port (ID_PORTS,
|
|
# every port by default), else nothing.
|
|
programOnPort = $(if $(filter $(PLATFORM),$(or $($(1)_PORTS),$(JOEY_PORTS))),$(1))
|
|
|
|
# $(call programName,ID): its file name without the extension: ID_NAME, else
|
|
# the port's naming rule -- the id itself, unless the port redefines it.
|
|
programName = $(or $(call programVar,$(1),NAME),$(call programNameRule,$(1)))
|
|
programNameRule = $(1)
|
|
|
|
# $(call programDir,ID): the folder it is built into: ID_BINDIR or bin/, and
|
|
# in there a folder of its own when it ships in one (ID_FOLDER) on a port
|
|
# whose programs can.
|
|
programDir = $(or $(call programVar,$(1),BINDIR),$(BINDIR))$(if $(and $(PROGRAM_FOLDERS),$(call programVar,$(1),FOLDER)),/$(call programName,$(1)))
|
|
|
|
# $(call programBin,ID): the program file.
|
|
programBin = $(call programDir,$(1))/$(call programName,$(1))$(PROGRAM_EXT)
|
|
|
|
# $(call programTarget,ID): what the programs goal builds for it.
|
|
programTarget = $(call programBin,$(1))
|
|
|
|
# $(call programDataDir,ID): where its DATA files are staged -- the DATA
|
|
# folder beside it, or on a port that packages programs (the IIgs disks, the
|
|
# DVX SDK) build/<port>/data/<name>/DATA.
|
|
programDataDir = $(if $(PROGRAM_DATA_APART),$(PROGRAM_BUILD)/data/$(call programName,$(1))/DATA,$(call programDir,$(1))/DATA)
|
|
|
|
# $(call programOptionalDir,ID): where its optional DATA files are staged:
|
|
# ones it runs without (a game that JIT-compiles a level's sprites when the
|
|
# level's pre-compiled bank is missing). Only the IIgs disk packer treats
|
|
# them apart -- they go on last, while there is room -- so elsewhere this is
|
|
# the DATA folder itself.
|
|
programOptionalDir = $(if $(PROGRAM_OPTIONAL_APART),$(PROGRAM_BUILD)/data/$(call programName,$(1))/OPTIONAL,$(call programDataDir,$(1)))
|
|
|
|
|
|
# Rules that hand a host tool's build to make/tools.mk depend on FORCE, so
|
|
# tools.mk -- which owns each tool's source list -- is always asked; it does
|
|
# nothing when the tool is current. Without it an existing tool binary looked
|
|
# up to date forever, and edits to its sources never reached it (a bake tool
|
|
# kept running a stale binary after a source it links changed). Defining it
|
|
# must not change any port's default goal (most include this file before
|
|
# their `all`), so the goal in force is saved and put back around it.
|
|
COMMON_DEFAULT_GOAL := $(.DEFAULT_GOAL)
|
|
.PHONY: FORCE
|
|
FORCE:
|
|
.DEFAULT_GOAL := $(COMMON_DEFAULT_GOAL)
|