ifeq ($(LLVM),1)
	LLVM = 1
	CC = clang
	LD = ld.lld
else
	LLVM = 0
	CC = gcc
	LD = ld
endif

CFLAGS = \
	-O2 \
	-std=c2x \
	-Wall    \
	-Wextra  \
	-Werror

LDFLAGS = -pthread -lrt

ifeq ($(DEBUG),1)
	DEBUG = 1
	CFLAGS += -g -fsanitize=address,leak,undefined
else
	DEBUG = 0
	CFLAGS  += -flto
	LDFLAGS += -flto
endif

ifeq ($(SECURITY),1)
	SECURITY = 1
	CFLAGS += \
		-fwrapv \
		-fno-strict-aliasing \
		-fno-delete-null-pointer-checks \
		-D_FORTIFY_SOURCE=2 \
		-fstack-protector-strong \
		-fPIE -fPIC -fpic \
		-fno-builtin-fprintf -fno-builtin-fwprintf \
		-fno-builtin-printf -fno-builtin-snprintf \
		-fno-builtin-sprintf -fno-builtin-swprintf \
		-fno-builtin-wprintf \
		-fno-builtin-memcpy -fno-builtin-memmove \
		-fno-builtin-memset -fno-builtin-strcat \
		-fno-builtin-strcpy -fno-builtin-strncat \
		-fno-builtin-strncpy -fno-builtin-wcscat \
		-fno-builtin-scwcpy -fno-builtin-wcsncat \
		-fno-builtin-wcsncpy -fno-builtin-wmemcpy \
		-fno-builtin-wmemmove -fno-builtin-wmemset \
		-Warray-bounds \
		-Wdiv-by-zero \
		-Wshift-count-negative -Wshift-count-overflow \
		-fstack-protector
	ifeq ($(LLVM),0)
		CFLAGS += -fwrapv-pointer \
			-Wclobbered
	endif
else
	SECURITY = 0
endif

ARGS = $(LLVM) $(DEBUG) $(SECURITY)

.PHONY: all clean controller worker test analyze phony

all: build/controller build/worker

clean:
	@rm -rf build

controller: build/controller

worker: build/worker

build/%.o: %.c build/ARGS 
	@mkdir -p $(@D)
	@$(CC) $(CFLAGS) -c $(patsubst build/ARGS,,$^) -o $@

build/%: %.c build/lib.o build/ARGS 
	@mkdir -p $(@D)
	@$(CC) $(CFLAGS) $(LDFLAGS) $(patsubst build/ARGS,,$^) -o $@

build/lib.o: $(patsubst %.c,build/%.o,$(shell find lib -type f -name '*.c' -print))
	@mkdir -p $(@D)
	@$(LD) -r $^ -o $@

build/ARGS: phony
	@mkdir -p $(@D)
	@if [[ `cat build/ARGS 2>&1` != '$(ARGS)' ]]; then \
		echo -n $(ARGS) >build/ARGS; \
		echo hi; \
	fi