+%.mk:
+# turn off evil implicit rules
+.SUFFIXES:
+%: %.o
+%: %.c
+%: %.cc
+%: %.C
+%: %.cpp
+%: %.p
+%: %.f
+%: %.F
+%: %.r
+%: %.s
+%: %.S
+%: %.mod
+%: %.sh
+%: %,v
+%: RCS/%,v
+%: RCS/%
+%: s.%
+%: SCCS/s.%
+
+config.mak:
+ cp config.mak.def $@
+-include config.mak
+
+define default_template
+$(1).BINS_TEMPL:=bin bin-static
+$(1).NAMES:=$$(filter $(1)/%,$$(NAMES))
+$(1).OBJS:=$$($(1).NAMES:%=$(B)/%.o)
+endef
+$(foreach d,$(DIRS),$(eval $(call default_template,$(d))))
+common.BINS_TEMPL:=
+api.BINS_TEMPL:=
+math.BINS_TEMPL:=bin
+
+define template
+D:=$$(patsubst %/,%,$$(dir $(1)))
+N:=$(1)
+$(1).BINS := $$($$(D).BINS_TEMPL:bin%=$(B)/$(1)%)
+-include src/$(1).mk
+#$$(warning D $$(D) N $$(N) B $$($(1).BINS))
+$(B)/$(1) $(B)/$(1)-static: $$($(1).OBJS)
+$(B)/$(1).so: $$($(1).LOBJS)
+# make sure dynamic and static binaries are not run parallel (matters for some tests eg ipc)
+$(B)/$(1)-static.err: $(B)/$(1).err
+endef
+$(foreach n,$(NAMES),$(eval $(call template,$(n))))
+
+BINS:=$(foreach n,$(NAMES),$($(n).BINS)) $(B)/api/main
+LIBS:=$(foreach n,$(NAMES),$($(n).LIBS)) $(B)/common/runtest
+ERRS:=$(BINS:%=%.err)
+
+debug:
+ @echo NAMES $(NAMES)
+ @echo BINS $(BINS)
+ @echo LIBS $(LIBS)
+ @echo ERRS $(ERRS)
+ @echo DIRS $(DIRS)
+
+define target_template
+$(1).ERRS:=$$(filter $(B)/$(1)/%,$$(ERRS))
+$(B)/$(1)/all: $(B)/$(1)/REPORT
+$(B)/$(1)/run: $(B)/$(1)/cleanerr $(B)/$(1)/REPORT
+$(B)/$(1)/cleanerr:
+ rm -f $$(filter-out $(B)/$(1)/%-static.err,$$($(1).ERRS))
+$(B)/$(1)/clean:
+ rm -f $$(filter $(B)/$(1)/%,$$(OBJS) $$(LOBJS) $$(BINS) $$(LIBS)) $(B)/$(1)/*.err
+$(B)/$(1)/REPORT: $$($(1).ERRS)
+ cat $(B)/$(1)/*.err >$$@
+run: $(B)/$(1)/run
+$(B)/REPORT: $(B)/$(1)/REPORT
+.PHONY: $(B)/$(1)/all $(B)/$(1)/clean
+endef
+$(foreach d,$(DIRS),$(eval $(call target_template,$(d))))
+
+$(B)/common/libtest.a: $(common.OBJS)
+ rm -f $@
+ $(AR) rc $@ $^
+ $(RANLIB) $@
+
+$(B)/common/all: $(B)/common/runtest
+
+$(ERRS): $(B)/common/runtest | $(BDIRS)
+$(BINS) $(LIBS): $(B)/common/libtest.a
+$(OBJS): src/common/test.h | $(BDIRS)
+$(BDIRS):
+ mkdir -p $@
+
+$(B)/common/options.h: src/common/options.h.in
+ $(CC) -E - <$< | sed -e '1,/optiongroups_unistd_end/d' -e '/^#/d' -e '/^[[:space:]]*$$/d' -e 's/^/#define /' >$@
+
+$(B)/common/mtest.o: src/common/mtest.h
+$(math.OBJS): src/common/mtest.h
+
+$(B)/api/main: $(api.OBJS)
+api/main.OBJS:=$(api.OBJS)
+$(api.OBJS):$(B)/common/options.h
+$(api.OBJS):CFLAGS+=-pedantic-errors -Werror -Wno-unused -D_XOPEN_SOURCE=700
+
+all:$(B)/REPORT
+run:$(B)/REPORT