CFA = cfa
DEPFLAGS = -MMD -MP
CFLAGS = -O2
ifdef N
CFLAGS += -DN=$(N)
endif
CXXFLAGS = $(CFLAGS) --std=c++14

.PHONY: all clean distclean run-c run-cpp run-cfa run

all: c-bench cpp-bench cfa-bench cpp-vbench

# rewrite object generation to auto-determine deps
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS)
COMPILE.cpp = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS)
COMPILE.cfa = $(CFA) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS)

c-%.o : c-%.c
c-%.o : c-%.c c-%.d
	$(COMPILE.c) $(OUTPUT_OPTION) -c $<

cpp-%.o : cpp-%.cpp
cpp-%.o : cpp-%.cpp cpp-%.d
	$(COMPILE.cpp) $(OUTPUT_OPTION) -c $<

cfa-%.o : cfa-%.c
cfa-%.o : cfa-%.c cfa-%.d
	$(COMPILE.cfa) $(OUTPUT_OPTION) -c $<

COBJS = c-stack.o c-pair.o c-print.o
CPPOBJS = 
CPPVOBJS = cpp-vstack.o
CFAOBJS = cfa-stack.o cfa-pair.o cfa-print.o

CFILES = c-bench.c bench.h $(COBJS:.o=.h) $(COBJS:.o=.c)
CPPFILES = cpp-bench.cpp bench.hpp cpp-stack.hpp cpp-print.hpp
CPPVFILES = cpp-vbench.cpp bench.hpp object.hpp $(CPPVOBJS:.o=.hpp) $(CPPVOBJS:.o=.cpp) cpp-vprint.hpp
CFAFILES = cfa-bench.c bench.h cfa-stack.h cfa-print.h cfa-stack.c cfa-print.c

c-bench: c-bench.c c-bench.d $(COBJS)
	$(COMPILE.c) -o $@ $< $(COBJS) $(LDFLAGS)

cpp-bench: cpp-bench.cpp cpp-bench.d $(CPPOBJS)
	$(COMPILE.cpp) -o $@ $< $(CPPOBJS) $(LDFLAGS)

cpp-vbench: cpp-vbench.cpp cpp-vbench.d $(CPPVOBJS)
	$(COMPILE.cpp) -o $@ $< $(CPPVOBJS) $(LDFLAGS)

cfa-bench: cfa-bench.c cfa-bench.d $(CFAOBJS)
	$(COMPILE.cfa) -o $@ $< $(CFAOBJS) $(LDFLAGS)

clean:
	-rm $(COBJS) c-bench
	-rm $(CPPOBJS) cpp-bench
	-rm $(CPPVOBJS) cpp-vbench
	-rm $(CFAOBJS) cfa-bench

distclean: clean
	-rm $(COBJS:.o=.d) c-bench.d
	-rm $(CPPOBJS:.o=.d) cpp-bench.d
	-rm $(CPPVOBJS:.o=.d) cpp-vbench.d
	-rm $(CFAOBJS:.o=.d) cfa-bench.d

run-c: c-bench
	@echo
	@echo '## C ##'
	@/usr/bin/time -f 'max_memory:\t%M kilobytes' ./c-bench
	@printf 'source_size:\t%8d lines\n' `cat $(CFILES) | wc -l`
	@printf 'redundant_type_annotations:%8d count\n' `cat $(CFILES) | fgrep '/***/' -c`
	@printf 'binary_size:\t%8d bytes\n' `stat -c %s c-bench`

run-cfa: cfa-bench
	@echo
	@echo '## Cforall ##'
	@/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cfa-bench
	@printf 'source_size:\t%8d lines\n' `cat $(CFAFILES) | wc -l`
	@printf 'redundant_type_annotations:%8d count\n' `cat $(CFAFILES) | fgrep '/***/' -c`
	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cfa-bench`

run-cpp: cpp-bench
	@echo
	@echo '## C++ ##'
	@/usr/bin/time -f 'max_memory:\t %M kilobytes' ./cpp-bench
	@printf 'source_size:\t%8d lines\n' `cat $(CPPFILES) | wc -l`
	@printf 'redundant_type_annotations:%8d count\n' `cat $(CPPFILES) | fgrep '/***/' -c`
	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-bench`

run-cppv: cpp-vbench
	@echo
	@echo '## C++ virtual ##'
	@/usr/bin/time -f 'max_memory:\t%M kilobytes' ./cpp-vbench
	@printf 'source_size:\t%8d lines\n' `cat $(CPPVFILES) | wc -l`
	@printf 'redundant_type_annotations:%8d count\n' `cat $(CPPVFILES) | fgrep '/***/' -c`
	@printf 'binary_size:\t%8d bytes\n' `stat -c %s cpp-vbench`

run: run-c run-cfa run-cpp run-cppv

# so make doesn't fail without dependency files
%.d: ;

# so make won't delete dependency files
.PRECIOUS: %.d

# include dependency files
-include: $(COBJS:.o=.d)
-include: $(CPPOBJS:.o=.d)
-include: $(CFAOBJS:.o=.d)
-include: c-bench.d
-include: cpp-bench.d
-include: cfa-bench.d
