Files
Sprinter-SDCC/app.mk
T
2026-09-16 10:01:43 +03:00

192 lines
9.8 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# app.mk — shared Makefile fragment for any standalone Sprinter ESTEX
# program. Приложение может лежать вне репозитория тулкита.
#
# Usage in a per-program Makefile:
#
# SPRINTER_ROOT := /путь/к/C-Compiler
# EXAMPLE := my_program # base name (matches my_program.c)
#
# # Optional overrides (any combination):
# # MEMORY := small # tiny | small | big | huge | manual
# # STACK_SIZE := 2048 # bytes reserved for the stack
# # EXTRA_SRCS := helper.c util.c # additional .c files in this dir
# # EXTRA_FLAGS := --crt0=minimal # passed through to sprinter-cc
# # SRC_DEBUG := 1 # карта C/asm и проверенный debug-пакет
# # SRC_DEBUG_FILES := helper.c # либо карта только выбранных TU
# # EXTRA_DATA := test.txt # extra files to add to `make floppy`
# # HDD_DEST_DIR := games/myapp # общий каталог файлов в `make hdd`
#
# include $(PROJ_ROOT)/app.mk
#
# Pipeline (all driven by sprinter-cc):
# crt0 + EXAMPLE.c + EXTRA_SRCS --sdcc--> .ihx
# .ihx --mkexe--> EXAMPLE.exe
# linking against lib/sprinter.lib for libc.
#
# Targets provided:
# all build $(EXAMPLE).exe (default)
# clean remove build artefacts
# floppy build the example and pack it (alone, plus EXTRA_DATA) into
# build/media/$(EXAMPLE).img внутри приложения.
# run floppy + launch MAME
ifeq ($(strip $(PROJ_ROOT)$(SPRINTER_ROOT)),)
$(error Задайте SPRINTER_ROOT — путь к установленному Sprinter-CC)
endif
ifeq ($(strip $(PROJ_ROOT)),)
PROJ_ROOT := $(SPRINTER_ROOT)
endif
ifeq ($(strip $(SPRINTER_ROOT)),)
SPRINTER_ROOT := $(PROJ_ROOT)
endif
# SPRINTER_PYTHON в sprinter-cc — один исполняемый файл, а не shell-команда.
# pyenv which выбирает local .python-version текущего приложения.
PYTHON ?= $(shell pyenv which python)
ifeq ($(strip $(PYTHON)),)
$(error pyenv Python не найден; задайте PYTHON=/путь/к/python3.12)
endif
SPRINTER_CC := $(PROJ_ROOT)/bin/sprinter-cc
MKEXE := $(PROJ_ROOT)/toolchain/mkexe/mkexe
LIB := $(PROJ_ROOT)/lib/sprinter.lib
ifeq ($(wildcard $(SPRINTER_CC)),)
$(error SPRINTER_ROOT=$(SPRINTER_ROOT): bin/sprinter-cc не найден)
endif
MAME_HOME ?=
MAME_BIN ?= $(if $(strip $(MAME_HOME)),$(MAME_HOME)/mame.arm,)
MAME_ROMPATH ?= $(if $(strip $(MAME_HOME)),$(MAME_HOME)/roms,)
MAME_DSS_IMAGE ?= $(if $(strip $(MAME_HOME)),$(MAME_HOME)/IMG/dss171u.img,)
MAME_SYSTEM_HDD_IMAGE ?= $(if $(strip $(MAME_HOME)),$(MAME_HOME)/IMG/sp_hdd_sys.chd,)
MAME_BIOS ?= v3.06
FLOPPY_IMG ?= $(CURDIR)/build/media/$(EXAMPLE).img
HDD_IMG ?= $(CURDIR)/build/hdd/$(EXAMPLE).chd
MAKE_DISK := $(PROJ_ROOT)/toolchain/make_disk.py
MAKE_HDD ?= $(PROJ_ROOT)/toolchain/make_hdd.sh
RUN_MAME := $(PROJ_ROOT)/toolchain/run_sprinter_mame.py
CHDMAN_BIN ?= chdman
MAME_PROFILE_ARGS = --mame-home "$(MAME_HOME)" --mame-bin "$(MAME_BIN)" \
--mame-rompath "$(MAME_ROMPATH)" \
--mame-dss-image "$(MAME_DSS_IMAGE)" \
--mame-system-hdd-image "$(MAME_SYSTEM_HDD_IMAGE)" \
--mame-bios "$(MAME_BIOS)"
# Optional knobs — see top of file.
MEMORY ?= tiny
# SRC_DIR / BUILD_DIR — раскладка приложения, которое НЕ держит исходники и
# выхлоп в одной папке с Makefile (например, SprPoP: src/ и build/). По
# умолчанию обе пусты, то есть всё как было: ./$(EXAMPLE).c → ./$(EXAMPLE).exe.
# Пустое значение обрабатывается отдельной веткой намеренно: "./prog.exe" и
# "prog.exe" — разные имена целей, и склеивать префикс безусловно нельзя.
SRC_DIR ?=
BUILD_DIR ?=
ifeq ($(strip $(SRC_DIR)),)
MAIN_SRC := $(EXAMPLE).c
else
MAIN_SRC := $(SRC_DIR)/$(EXAMPLE).c
endif
ifeq ($(strip $(BUILD_DIR)),)
EXE := $(EXAMPLE).exe
else
EXE := $(BUILD_DIR)/$(EXAMPLE).exe
endif
SOURCES := $(MAIN_SRC) $(EXTRA_SRCS)
# Аргументы упаковщика HDD. Обычно это exe и EXTRA_DATA; приложение со
# своей раскладкой каталогов может переопределить переменную до include.
HDD_PACK_ARGS ?= $(EXE) $(EXTRA_DATA)
# Общий каталог назначения внутри HDD. Пустое значение сохраняет прежнюю
# укладку в корень; вложенные КАТАЛОГ:файл считаются относительно него.
HDD_DEST_DIR ?=
CC_FLAGS := --memory $(MEMORY)
ifneq ($(STACK_SIZE),)
CC_FLAGS += --stack-size $(STACK_SIZE)
endif
CC_FLAGS += $(EXTRA_FLAGS)
ifeq ($(SRC_DEBUG),1)
CC_FLAGS += --src-debug
endif
ifneq ($(strip $(SRC_DEBUG_FILES)),)
CC_FLAGS += $(foreach src,$(SRC_DEBUG_FILES),--src-debug-file $(src))
endif
all: $(EXE)
# runtime/*.s (crt0-семейство, bank.s, heap.s) собираются per-build
# внутри sprinter-cc — без этой зависимости их правка не перелинкует
# уже собранный exe (кусало: фикс bank.s не подхватился).
RUNTIME_DEPS := $(wildcard $(PROJ_ROOT)/runtime/*.s)
# ПРОВЕРКА БАНКОВЫХ ВЫЗОВОВ — сразу после линковки, пока артефакты свежие.
# Ловит прямой `call` в чужой банк: он собирается МОЛЧА и стреляет диким
# переходом в пустой хвост банка (разбор — в шапке скрипта). Запускается
# только если банки вообще есть, то есть по наличию каталога сборки с
# bankN_*.asm; обычным небанковым программам ничего не стоит.
BANK_CHECK := $(PROJ_ROOT)/toolchain/check_bank_calls.py
# ПРОВЕРКА ISR-СТАБА W0-СТРАНИЦ — там же, по свежей карте. Ловит стаб
# _gfx_w0_isr, оставшийся в W1: программа, кладущая свои страницы в W0
# (атласы спрайтов, gfx_w0_map), получает недетерминированные зависания,
# когда прерывание приходит во время вызова DSS и W1 перемаплен. Только
# предупреждение: страницы в W0 кладут не все. Разбор — в шапке скрипта.
W0ISR_CHECK := $(PROJ_ROOT)/toolchain/check_w0_isr.py
# Команда/зависимости карты участвуют в пересборке, включая смену режима.
SDBG_CONFIG := $(dir $(EXE)).resource-stamps/$(EXAMPLE)-config.json
SDBG_MANIFEST := $(dir $(EXE)).sprinter-cc-$(EXAMPLE)/manifest.json
.PHONY: sdbg-config-force
SDBG_CONFIG_ARGS = $(SDBG_CONFIG) $(SPRINTER_CC) $(CC_FLAGS) $(SOURCES) $(SDBG_MANIFEST)
# Проверка содержимого обязательна: mtime make может иметь точность в секунду.
# Сохранение fingerprint только после успешной сборки позволяет повторить сбой.
$(EXE): $(SOURCES) $(MKEXE) $(LIB) $(RUNTIME_DEPS) sdbg-config-force $(SPRINTER_CC) $(wildcard $(PROJ_ROOT)/toolchain/sdbg/*.py) $(wildcard $(PROJ_ROOT)/toolchain/sdbg_*.py)
@state=$$($(PYTHON) $(PROJ_ROOT)/toolchain/sdbg_config.py check $(SDBG_CONFIG_ARGS)) || exit $$?; \
if [ "$$state" = changed ] || [ -n "$(filter-out sdbg-config-force,$?)" ]; then \
mkdir -p $(dir $@); \
SPRINTER_PYTHON="$(PYTHON)" $(SPRINTER_CC) $(CC_FLAGS) -o $@ $(SOURCES) || exit $$?; \
d=$(dir $@).sprinter-cc-$(EXAMPLE); \
if ls $$d/bank*_*.asm >/dev/null 2>&1; then $(PYTHON) $(BANK_CHECK) $$d || exit $$?; fi; \
if ls $$d/*.map >/dev/null 2>&1; then $(PYTHON) $(W0ISR_CHECK) $$d || exit $$?; fi; \
$(PYTHON) $(PROJ_ROOT)/toolchain/sdbg_config.py save $(SDBG_CONFIG_ARGS); \
fi
$(MKEXE):
$(MAKE) -C $(PROJ_ROOT)/toolchain/mkexe
# $(LIB) = lib/sprinter.lib (libc). Графика (bgi256.lib) собирает
# libbgi/Makefile; гоним и его — иначе standalone `make` в тесте с
# --gfx 256 не найдёт bgi256.lib при линковке. Оба инкрементальные,
# на повторном запуске ничего не пересобирают.
$(LIB):
$(MAKE) -C $(PROJ_ROOT)/libc
$(MAKE) -C $(PROJ_ROOT)/libbgi
clean:
rm -rf $(if $(strip $(BUILD_DIR)),$(BUILD_DIR),.sprinter-cc-* $(EXE))
# `make floppy` создаёт носитель только этого приложения, без записи в MAME.
floppy: $(EXE)
$(PYTHON) $(MAKE_DISK) "$(FLOPPY_IMG)" $(EXE) $(EXTRA_DATA)
@echo
@echo "Floppy ready: $(FLOPPY_IMG) (with $(EXAMPLE).exe$(if $(EXTRA_DATA), + $(EXTRA_DATA))) "
@echo "Run: make run MAME_HOME=/путь/к/MAME/runtime"
run: floppy
$(PYTHON) $(RUN_MAME) $(MAME_PROFILE_ARGS) --floppy "$(FLOPPY_IMG)"
# `make hdd` кладёт носитель в build/ приложения. Для нового inode после
# пересборки образа запущенный MAME должен быть перезапущен.
hdd: $(EXE)
mkdir -p "$(dir $(HDD_IMG))"
CHDMAN_BIN="$(CHDMAN_BIN)" $(MAKE_HDD) $(if $(strip $(HDD_DEST_DIR)),--dest "$(HDD_DEST_DIR)") "$(HDD_IMG)" $(HDD_PACK_ARGS)
@echo
@echo "HDD (D:) ready: $(HDD_IMG) (with $(EXAMPLE).exe$(if $(EXTRA_DATA), + $(EXTRA_DATA)))"
@echo "ВНИМАНИЕ: перезапусти MAME — образ пересобран."
run-hdd: hdd
$(PYTHON) $(RUN_MAME) $(MAME_PROFILE_ARGS) --hdd "$(HDD_IMG)"
.PHONY: all clean floppy run hdd run-hdd