Files
Sprinter-SDCC/app.mk
T

167 lines
8.8 KiB
Makefile
Raw Permalink 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 — used both by libc feature tests under tests/ and by real
# applications under examples/.
#
# Usage in a per-program Makefile:
#
# PROJ_ROOT := $(abspath $(CURDIR)/../..)
# 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
# mame/v306/IMG/mc.img — useful for trying a single program
# without rebuilding every example. Top-level `make floppy`
# (in the repo root) still packs all examples.
# run floppy + launch MAME
PYTHON ?= python3
SPRINTER_CC := $(PROJ_ROOT)/bin/sprinter-cc
MKEXE := $(PROJ_ROOT)/toolchain/mkexe/mkexe
LIB := $(PROJ_ROOT)/lib/sprinter.lib
MAME_DIR := $(PROJ_ROOT)/mame/v306
FLOPPY_IMG := $(MAME_DIR)/IMG/mc.img
# ?= — приложение со своим каталогом выхода (applications/SprPoP) держит
# образ у себя и связывает его с MAME символьной ссылкой.
HDD_IMG ?= $(MAME_DIR)/IMG/test_hdd.chd
MAKE_DISK := $(MAME_DIR)/make_disk.py
MAKE_HDD ?= $(PROJ_ROOT)/toolchain/make_hdd.sh
RUN_MAME := $(MAME_DIR)/run_mame.sh
# Optional knobs — see top of file.
MEMORY ?= tiny
# SRC_DIR / BUILD_DIR — раскладка приложения, которое НЕ держит исходники и
# выхлоп в одной папке с Makefile (applications/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` packs ONLY this program (+ optional EXTRA_DATA files) into
# the MAME floppy image, replacing whatever was there. Handy for trying a
# single program without rebuilding everything.
floppy: $(EXE)
python3 $(MAKE_DISK) $(FLOPPY_IMG) $(EXE) $(EXTRA_DATA)
@echo
@echo "Floppy ready: $(FLOPPY_IMG) (with $(EXAMPLE).exe$(if $(EXTRA_DATA), + $(EXTRA_DATA))) "
@echo "Run: cd $(MAME_DIR) && ./run_mame.sh"
run: floppy
cd $(MAME_DIR) && ./run_mame.sh
# `make hdd` packs this program (+ optional EXTRA_DATA files) into the MAME
# HDD image mounted as disk D: (-hard2 test_hdd.chd). Гораздо быстрее FDD —
# используется MCP-мостом к MAME (run_bridge.sh). После пересборки образа
# MAME ОБЯЗАН полный рестарт (chdman -f = новый inode; см. memory).
hdd: $(EXE)
$(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_bridge.sh) — образ пересобран."
.PHONY: all clean floppy run hdd