CFA?=cfa DEMOS?=control treatment LANGS?=cfa c cc CFLAGS=-O3 #-DNDEBUG SOURCES=$(foreach demo,$(DEMOS),$(foreach lang,$(LANGS),$(demo).$(lang))) TGT_SLUGS=$(call BOUND_ALTS,$(SOURCES)) EXES=$(addsuffix .runme,$(TGT_SLUGS)) ASMS=$(addsuffix .s,$(TGT_SLUGS)) TGTS=$(EXES) $(ASMS) define BOUND_ALTS $(1) $(addsuffix .unsound,$(1)) endef define COMPILER_FOR $(strip $(if $(findstring .cfa,$(1)),$(CFA), $(if $(findstring .cc,$(1)),$(CXX), $(if $(findstring .c,$(1)),$(CC), unknown$(1))))) endef .SUFFIXES: # disable make built-in rules, notably `% : %.s`, which introduces circularity .SECONDEXPANSION: # evaluate prereq dynamically all: $(TGTS) exes: $(EXES) asms: $(ASMS) .PHONY: all exes asms echo_% clean $(TGTS): tgt_slug=$(basename $@) $(TGTS): unsound_flag=$(if $(findstring .unsound,$(tgt_slug)),-DUNSOUND_BOUND) $(TGTS): source=$(subst .unsound,,$(tgt_slug)) $(TGTS): compiler=$(call COMPILER_FOR,$(suffix $(source))) $(EXES): out_type_flag=-DRUNIT $(ASMS): out_type_flag=-S $(TGTS): Makefile $(TGTS): $$(source) $(compiler) $< $(unsound_flag) $(out_type_flag) $(CFLAGS) -MMD -MF $@.d -o $@ echo_%: @echo '$($(@:echo_%=%))' clean: rm -f *.s *.runme *.d -include *.d