# generate objects from sources # arg 1: target.SRCS # arg 2: object suffix prefix # returns: target.OBJS objects = $(foreach f,$($1),$(addsuffix $2.o,$(basename $f))) # generate depends from .S .c .cpp sources # arg 1: target.SRCS # arg 2: dependency suffix prefix # returns: target.DEPS depends = $(foreach f,$(filter %.S %.c %.cpp,$($1)),$(addsuffix $2.d,$(basename $f))) # default target all: targets # TARGETBIN: binaries using the target architecture $(foreach T,${TARGETBIN},\ $(eval $T.OBJS += $(call objects,$T.SRCS,_${ARCH}) ) \ $(eval $T.DEPS += $(call depends,$T.SRCS,_${ARCH}) ) \ $(eval include $($T.DEPS) ) \ $(eval $T.elf: ${$T.OBJS} ) \ $(eval DEFAULT_TARGETS += $T.elf) \ ) # TARGETLIB: static libraries using the target architecture $(foreach T,${TARGETLIB},\ $(eval $T.OBJS += $(call objects,$T.SRCS,_${ARCH}) ) \ $(eval $T.DEPS += $(call depends,$T.SRCS,_${ARCH}) ) \ $(eval include $($T.DEPS) ) \ $(eval $T.a: ${$T.OBJS} ) \ $(eval DEFAULT_TARGETS += $T.a) \ ) # HOSTTARGETBIN: binaries using the host compiler $(foreach T,${HOSTTARGETBIN},\ $(eval $T.OBJS += $(call objects,$T.SRCS,) ) \ $(eval $T.DEPS += $(call depends,$T.SRCS,) ) \ $(eval include $($T.DEPS) ) \ $(eval $T: ${$T.OBJS}; @echo ' LD HOST $T'; ${HOST_CC} ${HOST_LDFLAGS} -o $T ${$T.OBJS} ) \ $(eval DEFAULT_TARGETS += $T) \ ) TESTS.DEPS = $(foreach F,${TESTS},$(addsuffix .d,$F)) include ${TESTS.DEPS} debug: @echo "TARGETBIN ${TARGETBIN}" @echo "TARGETLIB ${TARGETLIB}" @echo "HOSTTARGETBIN ${HOSTTARGETBIN}" @echo "HOSTTARGETLIB ${HOSTTARGETLIB}" @echo "DEFAULT_TARGETS ${DEFAULT_TARGETS}" @echo "TESTS ${TESTS}" @echo " DEPS ${TESTS.DEPS}" %.info: @echo "Target: $(basename $@)" @echo " SRCS: ${$(basename $@).SRCS}" @echo " OBJS: ${$(basename $@).OBJS}" @echo " DEPS: ${$(basename $@).DEPS}" targets: ${DEFAULT_TARGETS} @echo " -> Built ${DEFAULT_TARGETS}" # extra flags ${ARCH}_CFLAGS += -I../lib/libk \ -Werror=implicit-function-declaration ${ARCH}_CXXFLAGS += -I../lib/libk -Drestrict=__restrict__ # Target depndency rules %_${ARCH}.d: %.S @${${ARCH}_CC} ${${ARCH}_CFLAGS} -M -MT $(<:.S=_${ARCH}.o) $< -MF $@ %_${ARCH}.d: %.c @${${ARCH}_CC} ${${ARCH}_CFLAGS} -M -MT $(<:.c=_${ARCH}.o) $< -MF $@ %_${ARCH}.d: %.cpp @${${ARCH}_CXX} ${${ARCH}_CXXFLAGS} -M -MT $(<:.cpp=_${ARCH}.o) $< -MF $@ # Host dependency rules %.d: %.c @${HOST_CC} ${HOST_CFLAGS} -M -MT $(<:.c=.o) $< -MF $@ %.d: %.cc @${HOST_CXX} ${HOST_CXXFLAGS} -M -MT $(<:.cc=) $< -MF $@ # Target suffix rules %.a: @echo ' AR $@' @${${ARCH}_AR} ${${ARCH}_ARFLAGS} $@ $(filter %.o,$^) %_${ARCH}.o: %.s @echo ' AS $<' @${${ARCH}_AS} ${${ARCH}_ASFLAGS} -c -o $@ $< %_${ARCH}.o: %.S @echo ' CC $<' @${${ARCH}_CC} ${${ARCH}_CFLAGS} -c -o $@ $< %_${ARCH}.o: %.c @echo ' CC $<' @${${ARCH}_CC} ${${ARCH}_CFLAGS} -c -o $@ $< %_${ARCH}.o: %.cpp @echo ' CXX $<' @${${ARCH}_CXX} ${${ARCH}_CXXFLAGS} -c -o $@ $< %.elf: @echo ' LD $@' @${${ARCH}_LD} ${${ARCH}_LDFLAGS} -o $@ $^ @echo -n ' B2b ' @b2sum $@ | cut -d' ' -f1 # Host suffix rules %.o: %.c @echo ' CC HOST $<' @${HOST_CC} ${HOST_CFLAGS} -c -o $@ $< # test rules test_%: test_%.cc @echo ' CXX TEST $@' @${HOST_CXX} ${HOST_CXXFLAGS} $< -o $@ .PHONY: test.base valgrind.base clean.base FORCE test.base: ${TESTS} @echo " -> Running tests in $(shell pwd | xargs basename)" @$(foreach f,$^,echo " -> $f"; ./$f &&) echo "Done" valgrind.base: ${TESTS} @echo " -> Running valgrind on tests in $(shell pwd | xargs basename)" @$(foreach f,$^,echo " -> $f"; valgrind --leak-check=full ./$f;) clean.base: FORCE @echo " -> Cleaning $(shell pwd | xargs basename)" @$(foreach V,$(filter %.OBJS, ${.VARIABLES}), rm -rf $($(V))) @$(foreach V,$(filter %.DEPS, ${.VARIABLES}), rm -rf $($(V))) @rm -rf *.a @rm -rf ${TESTS} %: %.base ; FORCE: ;