# variables VCS_ROOT = $(shell git rev-parse --show-toplevel) CWD = $(shell pwd) # generate build rules from variables # This makefile defines the following targets: # - all: default goal, build all default targets # generate objects from sources # arg 1: target.SRCS # arg 2: object suffix prefix # returns: target.OBJS objects = $(foreach f,$($1),$(addprefix build/,$(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)),$(addprefix build/,$(addsuffix $2.d,$(basename $f)))) # default target .DEFAULT_GOAL := all # 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 ' HOST LD $T'; ${HOST_CXX} ${HOST_LDFLAGS} -o $T ${$T.OBJS} ) \ $(eval DEFAULT_TARGETS += $T) \ ) list-targets: @echo TARGETBIN @echo ${TARGETBIN} | tr ' ' '\n' | xargs -n1 echo " " @echo TARGETLIB @echo ${TARGETLIB} | tr ' ' '\n' | xargs -n1 echo " " @echo HOSTTARGETBIN @echo ${HOSTTARGETBIN} | tr ' ' '\n' | xargs -n1 echo " " @echo HOSTTARGETLIB @echo ${HOSTTARGETLIB} | tr ' ' '\n' | xargs -n1 echo " " @echo DEFAULT_TARGETS @echo ${DEFAULT_TARGETS} | tr ' ' '\n' | xargs -n1 echo " " @echo TESTS @echo ${TESTS} | tr ' ' '\n' | xargs -n1 echo " " %.info: @echo "Target: $(basename $@)" @echo " ARCH: ${ARCH}" @echo " SRCS: ${$(basename $@).SRCS}" @echo " OBJS: ${$(basename $@).OBJS}" @echo " DEPS: ${$(basename $@).DEPS}" @echo " LD ${${ARCH}_LDFLAGS}" all: ${DEFAULT_TARGETS} @echo " -> Built all in ${COMPONENT}" # extra flags ${ARCH}_CFLAGS += -I${VCS_ROOT}/lib/libk \ -Werror=implicit-function-declaration ${ARCH}_CXXFLAGS += -I${VCS_ROOT}/lib/libk -Drestrict=__restrict__ # Target suffix rules # -MD output makefile dependency rule # -MT target change the target of the rule # -MF file write the dependencies to file %.a: @echo ' AR $@' @${${ARCH}_AR} ${${ARCH}_ARFLAGS} $@ $(filter %.o,$^) build/%_${ARCH}.o: %.s @echo ' AS $<' @mkdir -p $(dir $@) @${${ARCH}_AS} ${${ARCH}_ASFLAGS} -c -o $@ $< build/%_${ARCH}.o: %.S @echo ' CC $<' @mkdir -p $(dir $@) @${${ARCH}_CC} ${${ARCH}_CFLAGS} -MD -MT $@ -MF $(@:.o=.d) -c -o $@ $< build/%_${ARCH}.o: %.c @echo ' CC $<' @mkdir -p $(dir $@) @${${ARCH}_CC} ${${ARCH}_CFLAGS} -MD -MT $@ -MF $(@:.o=.d) -c -o $@ $< %.elf: @echo ' LD $@' @${${ARCH}_LD} ${${ARCH}_LDFLAGS} -o $@ $^ @echo -n ' B2b ' @b2sum $@ | cut -d' ' -f1 # Host suffix rules build/%.o: %.c @echo ' HOST CC $<' @mkdir -p $(dir $@) @${HOST_CC} ${HOST_CFLAGS} -MD -MT $@ -MF $(@:.o=.d) -c -o $@ $< build/%.o: %.cc @echo ' HOST CXX $<' @mkdir -p $(dir $@) @${HOST_CXX} ${HOST_CXXFLAGS} -MD -MT $@ -MF $(@:.o=.d) -c -o $@ $< .PHONY: test test.quiet valgrind valgrind.quiet clean.base FORCE test: ${TESTS} @echo " -> Running tests in $(CWD:${VCS_ROOT}/%=%)" @[[ -z "${TESTS}" ]] || ${VCS_ROOT}/scripts/test_runner.py --verbose ${TESTS} test.quiet: ${TESTS} @echo " -> Running tests in $(CWD:${VCS_ROOT}/%=%)" @[[ -z "${TESTS}" ]] || ${VCS_ROOT}/scripts/test_runner.py ${TESTS} valgrind: ${TESTS} @echo " -> Running valgrind on tests in $(CWD:${VCS_ROOT}/%=%)" @[[ -z "${TESTS}" ]] || ${VCS_ROOT}/scripts/test_runner.py --verbose --valgrind ${TESTS} valgrind.quiet: ${TESTS} @echo " -> Running valgrind on tests in $(CWD:${VCS_ROOT}/%=%)" @[[ -z "${TESTS}" ]] || ${VCS_ROOT}/scripts/test_runner.py --valgrind ${TESTS} clean: 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 ${CLEAN_FILES} @rm -rf ${TESTS} FORCE: ;