build=OUT
COV_DIR=$(OUT)/coverage/
SRC_DIR=src
APP_DIR=src/apps/
OUT=build

CC=gcc

CCFLAGS = -Wall -Werror
CCFLAGS += -std=c99 -D_POSIX_C_SOURCE=200809L
CCFLAGS += -I$(SRC_DIR)

.PHONY: release debug

CONFIG = $(OUT)/.config.mk

-include $(CONFIG)

ifeq ($(DEBUG), 1)
CCFLAGS += -DLOG_LEVEL=5 -DDEBUG
CCFLAGS += -O0 -ggdb
endif

ifeq ($(COVERAGE), 1)
LDFLAGS += -lgcov --coverage
CCFLAGS += -O0 --coverage
CCFLAGS += -fprofile-arcs -ftest-coverage
endif

ifeq ($(RELEASE), 1)
CCFLAGS += -O3
endif

CCFLAGS += -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDFLAGS += -lglib-2.0

C_SOURCES = $(shell find $(SRC_DIR) -name "*.c")
ALL_OBJS = $(patsubst $(SRC_DIR)/%.c, $(OUT)/%.o, $(C_SOURCES))
APP_OBJS = $(filter $(OUT)/apps/%, $(ALL_OBJS))
TEST_OBJS = $(filter $(OUT)%test.o, $(ALL_OBJS))
OBJS = $(filter-out $(TEST_OBJS) $(APP_OBJS), $(ALL_OBJS))
APPS = $(patsubst %.o, %, $(APP_OBJS))
.PHONY: all
all: gbdb gbasm tests

.PHONY: config-debug config-release config-default config-coverage

$(CONFIG):
	@mkdir -p $(OUT)

config-debug: $(CONFIG)
	@echo "DEBUG=1" > $(CONFIG)

config-release: $(CONFIG)
	@echo "RELEASE=1" > $(CONFIG)

config-coverage: $(CONFIG)
	@echo "COVERAGE=1" > $(CONFIG)

config-default: $(CONFIG)
	@echo "" > $(CONFIG)

.PHONY: gbdb gbasm

gbdb: $(OUT)/apps/gbdb
gbasm: $(OUT)/apps/gbasm

.PHONY: gbasm-test sample-test tests

TESTS = $(patsubst %.o, %, $(filter %/test.o, $(ALL_OBJS)))
tests: $(TESTS)

$(ALL_APPS) $(ALL_OBJS): $(CONFIG)

$(OUT)/%.o: $(SRC_DIR)/%.c
	@echo "    CC   $@"
	@$(shell mkdir -p $(@D))
	@$(CC) -c $(CCFLAGS) -o $@ $<

.SECONDEXPANSION:
$(APPS) $(TESTS): $(OBJS) $$@.o
	@echo "    LD   $@"
	@$(shell mkdir -p $(@D))
	@$(CC) $^ $(LDFLAGS) -o $@


.PHONY: check cov-report

define run_tests =
	@for i in $(TESTS); do \
		echo "    TEST $$i"; \
		$$i; \
		if [ $$? -ne 0 ]; then \
			exit 1; \
		fi; \
	done;
endef

.PHONY: check coverage coverage-report
check: $(TESTS)
	$(run_tests)

COV_BASE=$(COV_DIR)/cov_base.info
.PHONY: $(COV_BASE)
$(COV_BASE):
	@mkdir -p $(COV_DIR)
	@lcov -q -c -i -d $(OUT) -o $(COV_BASE)

$(COV_DIR)/coverage.info coverage: $(TESTS) $(COV_BASE)
	$(call run_tests)
	@lcov -q -c -d $(OUT) -o $(COV_DIR)results.info -t results
	@lcov -q -a $(COV_DIR)results.info -o $(COV_DIR)coverage.info
	@lcov --summary $(COV_DIR)coverage.info

coverage-report: coverage
	@mkdir -p $(COV_DIR)/html/
	@genhtml -q --prefix $(PWD) --output-directory=$(COV_DIR)/html $(COV_DIR)/coverage.info

.PHONY: clean realclean cov-clean

cov-clean:
	@find $(OUT)/ \( -iname *.gcno -o -iname *.gcda \) -delete
	@rm -rf $(COV_DIR)

clean: cov-clean
	@rm -f $(ALL_OBJS) $(APPS) $(TESTS)

realclean: clean
	@rm -f $(CONFIG)
