Files
RTLPlayground/Makefile
T
d00f 1d158d21d1 build: show the compiler and the toolchain in the version banner
The boot banner and the version command print the SDCC release and
revision from the compiler's own macros, and the name of the in-tree
toolchain the Makefile built, which is the checksum of sdcc/ and so
changes with every patch in it. A build with CC given on the command
line says "system" instead, since that compiler need not carry the
patches. A plain release and the same release with the patches report
the same revision, so the toolchain line is what tells them apart.

Costs 66 bytes of BANK2.
2026-10-25 16:04:49 +01:00

266 lines
8.7 KiB
Makefile

VERSION=0.1.0
IMAGESIZE = 524288
DEFAULT_CONFIG_LOCATION = 454656
CONFIG_LOCATION = 458752
HTML_LOCATION = 262144
SDCC_TOOLCHAIN = sdcc-$(shell cat sdcc/* | cksum | cut -d' ' -f1)
SDCC_PREFIX = toolchain/$(SDCC_TOOLCHAIN)
ifeq ($(origin CC),default)
SDCC = $(SDCC_PREFIX)/bin/sdcc
CC = $(SDCC)
ASM = $(SDCC_PREFIX)/bin/sdas8051
else
SDCC_TOOLCHAIN = system
endif
CC_FLAGS = -mmcs51 -I. -Imachine -Ihttpd -Iuip
ASM ?= sdas8051
AFLAGS= -plosgff
SUBDIRS := tools
SUBDIRSCLEAN=$(addsuffix clean,$(SUBDIRS))
# $MACHINE selects machine/$(MACHINE).c as the board definition and is passed
# on as -DMACHINE_NAME, which machine.h uses to include machine/$(MACHINE).h.
# Board selection itself needs no MACHINE_* symbol for #if chains, so the
# definition is all the compiler has to know.
ifneq ($(MACHINE),)
CC_FLAGS += -DMACHINE_NAME=$(MACHINE)
endif
# Health instrumentation and the "health" console command: HEALTH=1 gmake ...
ifneq ($(HEALTH),)
CC_FLAGS += -DHEALTH
endif
ifeq ($(CI),1)
CC_FLAGS += --Werror
endif
# The board definition being built: one file per MACHINE_* symbol in machine.h.
MACHINE_SRC = machine/$(MACHINE).c
MACHINE_INIT_DEFAULT := machine/default_machine_init.c
MACHINE_INIT_SRC := $(wildcard machine/$(MACHINE)_init.c)
ifeq ($(MACHINE_INIT_SRC),)
MACHINE_INIT_SRC := $(MACHINE_INIT_DEFAULT)
endif
ifndef BUILDDIR
BUILDDIR = output/$(MACHINE)
endif
VERSION_HEADER := version.h
GIT_VERSION := $(shell git rev-parse --short HEAD)
ifeq ($(shell git status --porcelain --untracked-files=no),)
else
GIT_VERSION := $(GIT_VERSION)-dirty
endif
VERSION_EXTENSION = v$(VERSION)-$(GIT_VERSION)
FILENAME_EXTENSION = $(VERSION_EXTENSION)-$(MACHINE)
# Deterministic build date: honor SOURCE_DATE_EPOCH, else the HEAD commit date,
# else wall-clock (no-git fallback). Keeps same-commit builds byte-identical
# (BUILD_DATE is baked into the image and covered by the trailing CRC).
SOURCE_DATE_EPOCH ?= $(shell git show -s --format=%ct HEAD 2>/dev/null)
ifeq ($(SOURCE_DATE_EPOCH),)
BUILD_DATE := $(shell date +"%Y-%m-%d %H:%M:%S")
else
BUILD_DATE := $(shell date -u -d @$(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S" 2>/dev/null \
|| date -u -r $(SOURCE_DATE_EPOCH) +"%Y-%m-%d %H:%M:%S")
endif
# $(MACHINE_SRC) is listed here so an unknown $MACHINE fails before anything else
# is built, including the tools/ subdirectory.
all: create_build_dir $(VERSION_HEADER) $(MACHINE_SRC) $(SUBDIRS) $(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin
bank_size:
tools/bank_occupancy.sh "$(MACHINE)"
create_build_dir: $(SDCC)
mkdir -p "$(BUILDDIR)"
mkdir -p "$(BUILDDIR)/uip"
mkdir -p "$(BUILDDIR)/httpd"
mkdir -p "$(BUILDDIR)/machine"
# Every machine is a pair machine/<MACHINE>.c + machine/<MACHINE>.h. Selecting
# them by name means no #if/#elif chain, so an unknown or empty $MACHINE is
# caught here instead of by a #error further down the build.
$(MACHINE_SRC):
@echo "ERROR: MACHINE='$(MACHINE)' has no definition (expected $(MACHINE_SRC))." >&2
@echo " Every machine is one file pair under machine/, named after the" >&2
@echo " MACHINE_* symbol it defines; see machine/*.c for the full list." >&2
@echo " Example: make MACHINE=KP_9000_6XHML_X2" >&2
@false
# Keep the per-machine definition in first position to fail immediately on an
# invalid $MACHINE value
SRCS = \
$(MACHINE_SRC) \
$(MACHINE_INIT_SRC) \
cmd_editor.c \
cmd_parser.c \
dhcp.c \
html_data.c \
rtlplayground.c \
boot.c \
sfp.c \
dns.c \
dns_cli.c \
sessions.c \
ntp.c \
ntp_cli.c \
syslog.c \
udp_apps.c
# RTL837x
SRCS += \
rtl837x_bandwidth.c \
rtl837x_cabletest.c \
rtl837x_flash.c \
rtl837x_igmp.c \
rtl837x_init.c \
rtl837x_nic.c \
rtl837x_leds.c \
rtl837x_leds_dump.c \
rtl837x_phy.c \
rtl837x_pins.c\
rtl837x_port.c \
rtl837x_stp.c \
rtl837x_lldp.c \
rtl837x_storm.c \
rtl837x_lacp.c \
rtl837x_trap.c
SRCS += \
httpd/httpd.c \
httpd/page_impl.c
SRCS += \
uip/timer.c \
uip/uip.c \
uip/uiplib.c \
uip/uip_arp.c \
uip/uip-fw.c \
uip/uip-neighbor.c \
uip/uip-split.c
OBJS = ${SRCS:%.c=$(BUILDDIR)/%.rel}
DEPS := ${SRCS:%.c=$(BUILDDIR)/%.d}
HTML := $(shell find html -name '*.js' -or -name '*.html' -or -name '*.svg' -or -name '*.css' -or -name '*.ico')
# Minified copy of the web UI sources, used as the fileadder input.
# The raw html/ sources stay untouched for development; the minified
# copy is a build artifact under output/.
HTML_MIN := $(BUILDDIR)/html_min
HTML_MIN_LIST := $(BUILDDIR)/html_min.list
HTML_MIN_STAMP := $(BUILDDIR)/html_min.stamp
.PHONY: html_min
html_min: $(HTML_MIN_STAMP)
$(HTML_MIN_LIST): FORCE
@mkdir -p $(BUILDDIR)
@echo $(sort $(HTML)) > $@.tmp
@cmp -s $@.tmp $@ && rm -f $@.tmp || mv $@.tmp $@
$(HTML_MIN_STAMP): $(HTML) $(HTML_MIN_LIST) tools/minify.py $(if $(wildcard $(HTML_MIN)),,FORCE)
rm -rf $(HTML_MIN)
mkdir -p $(HTML_MIN)
@for f in $(HTML); do python3 tools/minify.py $$f $(HTML_MIN)/$$(basename $$f) || exit 1; done
@touch $@
html_data.c html_data.h &: $(HTML_MIN_STAMP) | tools
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -b BANK1 -z -d $(HTML_MIN) -p html_data
$(VERSION_HEADER): FORCE
@printf '%s\n' "#ifndef VERSION_H" "#define VERSION_H" \
"#define VERSION_SW \"$(VERSION_EXTENSION)\"" \
"#define BUILD_DATE \"$(BUILD_DATE)\"" \
"#define SDCC_TOOLCHAIN \"$(SDCC_TOOLCHAIN)\"" \
"#endif" > $(VERSION_HEADER).tmp
@cmp -s $(VERSION_HEADER).tmp $(VERSION_HEADER) \
&& rm -f $(VERSION_HEADER).tmp \
|| mv $(VERSION_HEADER).tmp $(VERSION_HEADER)
httpd: html_data.h
$(SUBDIRS):
$(MAKE) -C $@ BUILDDIR=$(BUILDDIR)
clean: $(SUBDIRSCLEAN)
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
-if [ -d $(BUILDDIR) ]; then find $(BUILDDIR) -type f ! -name "*.bin" -delete; fi
distclean: $(SUBDIRSCLEAN)
-rm -f html_data.c html_data.h $(VERSION_HEADER) $(HTML_MIN_LIST) $(HTML_MIN_STAMP)
-rm -rf $(BUILDDIR)
-rm -rf toolchain
ifneq ($(SDCC),)
$(SDCC):
sh sdcc/build.sh $(abspath $(SDCC_PREFIX))
endif
$(SUBDIRSCLEAN):
$(MAKE) -C $(@:clean=) clean
# Objects depend on the flags they were built with, through a stamp file that
# is rewritten only when CC_FLAGS actually changes.
CCFLAGS_STAMP := $(BUILDDIR)/.ccflags
.PHONY: FORCE
FORCE:
$(CCFLAGS_STAMP): FORCE | create_build_dir
@echo '$(CC_FLAGS)' | cmp -s - $@ 2>/dev/null || echo '$(CC_FLAGS)' > $@
$(BUILDDIR)/%.rel: %.c $(CCFLAGS_STAMP) | create_build_dir html_data.h
$(CC) -MMD $(CC_FLAGS) -o $@ -c $<
$(BUILDDIR)/%.rel: %.asm $(CCFLAGS_STAMP) | create_build_dir
${ASM} ${AFLAGS} -o $@ $<
# mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)/rtlplayground.ihx: $(OBJS) $(BUILDDIR)/crtbank.rel $(BUILDDIR)/crc16.rel
$(CC) $(CC_FLAGS) --xram-size 49151 -Wl-bHOME=0x00000 -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-bBANK3=0x34000 -Wl-r -o $@ $^
$(BUILDDIR)/rtlplayground.img: $(BUILDDIR)/rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)/rtlplayground-$(FILENAME_EXTENSION).bin: $(BUILDDIR)/rtlplayground.img | tools
if [ -e $@ ]; then rm $@; fi
tools/$(BUILDDIR)/imagebuilder -i $^ $@
tools/$(BUILDDIR)/fileadder -a $(DEFAULT_CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)/fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)/fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -z -d $(HTML_MIN) -b BANK1 $@
tools/$(BUILDDIR)/crc_calculator -u $@
ln -sf $(MACHINE)/rtlplayground-$(FILENAME_EXTENSION).bin $(BUILDDIR)/../rtlplayground.bin
.PHONY: clean distclean all $(SUBDIRS) $(SUBDIRSCLEAN) create_build_dir
# Every machine/ definition is compiled, so a machine added to machine/ is
# covered without registering it anywhere. A board only counts once both its
# <machine>.c and its <machine>.h are present: the header is what the rest of
# the build includes, so a .c without one is an incomplete board. The _init.c
# files are excluded here: they are the boot hooks, compiled separately below
# (the board's own if it exists, otherwise default_machine_init.c). The
# machine-specific defines are filtered out of $(CC_FLAGS) and supplied per
# iteration instead, so this also works as "make machine_check MACHINE=...".
MACHINE_DEFS := $(sort $(filter $(patsubst machine/%.h,%,$(wildcard machine/*.h)),$(patsubst machine/%.c,%,$(filter-out machine/%_init.c,$(wildcard machine/*.c)))))
MACHINE_LESS_CC_FLAGS = $(filter-out -DMACHINE_%,$(CC_FLAGS))
.PHONY: machine_check
machine_check: $(SDCC)
@mkdir -p $(BUILDDIR)/tmp
@set -eo pipefail; \
for MACHINE in $(MACHINE_DEFS); \
do \
echo "Checking $${MACHINE}"; \
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c machine/$${MACHINE}.c; \
INIT=machine/$${MACHINE}_init.c; \
if [ ! -e $$INIT ] && [ ! -L $$INIT ]; then INIT=$(MACHINE_INIT_DEFAULT); fi; \
$(CC) $(MACHINE_LESS_CC_FLAGS) -DMACHINE_NAME=$${MACHINE} -MMD -o $(BUILDDIR)/tmp/machine_check -c $$INIT; \
done
@rm -rf $(BUILDDIR)/tmp
-include $(DEPS)