SRC = src/main.c src/helper.c src/io.c src/md2.c src/md2_impls/md2_common.c src/md2_impls/md2_0.c src/md2_impls/md2_1.c src/md2_impls/md2_2.c src/md2_impls/md2_3.c src/md2_impls/md2_reference/md2_reference.c
OBJ = ${subst src,build,${SRC:.c=.o}}
CC = gcc
DETAILED_BENCHMARK ?= 0
CFLAGS = -Ilib -std=c11 -Wall -Wextra -O3
ifeq ($(DETAILED_BENCHMARK), true)
	CFLAGS += -DMD2_DETAILED_BENCHMARK
endif
LDFLAGS = -pthread
TESTFILES = t/1 t/2 t/5 t/7 t/10 t/25 t/50 t/75 t/100 t/250 t/500 #t/750 t/1000 t/1500 t/2000 t/2500 t/3000 t/3500 t/4000 t/4500 t/5000 t/5500 t/6000 t/6500 t/7000 t/7500 t/8000 t/8500 t/9000 t/9500 t/10000
TESTFILES_SIZES = ${subst t/,,${TESTFILES}}
BLUE=\033[1;36m
RED=\033[1;31m
GREEN=\033[1;32m
NC=\033[0m

all: md2

clean:
	rm -rf md2 build

help:
	@echo === Project Build Help ===
	@echo
	@echo Available targets:
	@echo - all: build everything
	@echo "       When DETAILED_BENCHMARK=true is passed, the detailed benchmarks are enabled."
	@echo "       This will decrease the overall performance of the program."
	@echo - clean: clean distfiles
	@echo - help: show this help
	@echo - benchmarks: run benchmarks
	@echo - valgrind-check: run checks with valgrind

build/%.o: src/%.c
	@mkdir -p build/md2_impls/md2_reference
	${CC} -c ${CFLAGS} -o $@ $<

md2: ${OBJ} 
	${CC} -o $@ $(OBJ) ${LDFLAGS}

t/%:
	@mkdir -p t
	@echo
	@echo -e "${BLUE}=== Generating ${subst t/,,$@}MB of random data... ===${NC}"
	dd if=/dev/urandom of=$@ bs=1M count=${subst t/,,$@} status=progress
	@echo -e "${BLUE}===                done                     ===${NC}"
	@echo

benchmarks.csv: md2 ${TESTFILES}
	@rm -f $@
	@echo -n "Implementierung" > $@
	@for t in $(TESTFILES_SIZES); do \
		echo -n ";$$t" >> $@; \
	done
	@echo "" >> $@

	@for i in 0 1 2 3 4; do \
		echo ;\
		echo -e "${BLUE}=== Testing implementation $$i ===${NC}";\
		echo -n "Implementierung-$$i" >> $@; \
		for t in $(TESTFILES_SIZES); do \
			echo -n "- with $${t}MB ... "; \
			if ! rr=$$(./md2 t/$${t} -B3 -V$${i}); then \
				echo; \
				echo -e "${RED}ERROR -> SKIPPED!${NC}"; \
				echo -n ";0" >> $@; \
			else \
				r=$$(echo $$rr | xargs | sed -e 's/.*took \(.*\) seconds.*/\1/'); \
				echo "$${r}s"; \
				echo -n ";$${r}" >> $@; \
			fi; \
		done; \
		echo "" >> $@; \
		echo -e "${BLUE}===           done           ===${NC}";\
		echo;\
    done

benchmarks: benchmarks.csv

valgrind-check: md2 t/3

	@for i in 0 1 2 3; do \
		echo; \
		echo -e "${BLUE}=== Testing implementation $$i ===${NC}";\
		if ! valgrind --error-exitcode=1 --leak-check=full --tool=memcheck -s ./md2 t/3 -V$$i -B1; then \
			echo -e "${RED}ERROR found! (see above)${NC}"; \
			exit 1; \
		fi; \
		echo -e "${BLUE}===           done           ===${NC}";\
		echo; \
	done

	@if ! valgrind -s ./md2 -T; then \
		echo -e "${RED}ERROR found! (see above)${NC}"; \
		exit 1;\
	fi

	@echo -e "${GREEN}=== all implementations PASSED valgrind ===${NC}"

.PHONY: all clean help benchmarks lint