SHELL		= /bin/sh
MAKE		= make

CC		= cc
CFLAGS		= -DNDEBUG
LDFLAGS		= $(CFLAGS)
#MACROS		= -DHNEFATAFL_AIM_ZHASH

PRGNAM		= hnefatafl_aim
OBJ_A		= lib$(PRGNAM).a
OBJ_SO		= lib$(PRGNAM).so
OBJS		= aiminimax.o\
		aiminimaxt.o\
		algorithm.o\
		config.o

HDR		= $(PRGNAM).h
HDRS		= config.h\
		aiminimaxt.h\
		aiminimax.h\
		algorithm.h

HDR_DIR		= ../core/.hdr
HDR_DCOMMENT	= $(HDR_DIR)/dcomment.awk
HDR_LICENSE	= $(HDR_DIR)/LICENSE

GLEIPNIR	= gleipnir
GLEIPNIR_DIR	= ../$(GLEIPNIR)

GLINE		= $(GLEIPNIR)_line
GLINE_H		= $(GLINE).h

GLINES		= $(GLEIPNIR)_lines
GLINES_H	= $(GLINES).h

GLINEREAD	= $(GLEIPNIR)_lineread
GLINEREAD_H	= $(GLINEREAD).h

CORE		= hnefatafl
CORE_A		= lib$(CORE).a
CORE_SO		= lib$(CORE).so
CORE_H		= $(CORE).h
CORE_DIR	= ../core

DEPS_A		= $(CORE_DIR)/$(CORE_A)
DEPS_SO		= $(CORE_DIR)/$(CORE_SO)
DEPS_H		= $(CORE_DIR)/$(CORE_H)\
		$(GLEIPNIR_DIR)/$(GLINE_H)\
		$(GLEIPNIR_DIR)/$(GLINES_H)\
		$(GLEIPNIR_DIR)/$(GLINEREAD_H)

LDLIBS		= -lm\
		-l$(CORE)
INC		= -I.\
		-I$(CORE_DIR)\
		-I$(CORE_DIR)/zhash\
		-I$(GLEIPNIR_DIR)
LIB		= -L$(CORE_DIR)

CLANG		= scan-build
CPPCHECK	= cppcheck --enable=all
GCC		= gcc -g -std=c89\
		-pedantic-errors -Waggregate-return -Wall\
		-Wbad-function-cast -Wcast-align -Wcast-qual -Wcomment\
		-Wconversion -Wdeclaration-after-statement\
		-Wdisabled-optimization -Wdouble-promotion -Werror\
		-Wextra -Wfloat-equal -Wformat=2\
		-Wframe-larger-than=256 -Winline -Winit-self\
		-Winvalid-pch -Wjump-misses-init -Wlarger-than=320\
		-Wlogical-op -Wlong-long -Wmissing-declarations\
		-Wmissing-format-attribute -Wmissing-include-dirs\
		-Wmissing-prototypes -Wnested-externs\
		-Wold-style-declaration -Wold-style-definition -Wpacked\
		-Wredundant-decls -Wshadow -Wstack-protector\
		-Wstack-usage=256 -Wstrict-aliasing -Wstrict-overflow=5\
		-Wstrict-prototypes -Wswitch-default -Wswitch-enum\
		-Wsync-nand -Wtrampolines -Wundef -Wuninitialized\
		-Wunreachable-code -Wunsafe-loop-optimizations -Wunused\
		-Wvector-operation-performance -Wvla -Wwrite-strings
LINT		= splint -strict -strict-lib -ansi89limits\
		-booltype HNEF_BOOL -boolfalse HNEF_FALSE\
		-booltrue HNEF_TRUE -systemdirerrors -exportany\
		-bounds +likelybounds

all: static

static: $(OBJ_A)

dynamic: $(OBJ_SO)

$(OBJ_A): $(DEPS_H) $(DEPS_A) $(OBJS)
	ar rcs $(OBJ_A) $(OBJS)

$(OBJ_SO): $(DEPS_H) $(DEPS_SO) $(OBJS)
	$(CC) $(LDFLAGS) $(LDLIBS) $(INC) $(LIB) $(MACROS)\
		-shared -Wl,-soname,$(OBJ_SO) -o $(OBJ_SO) $(OBJS)

aiminimax.o: aiminimax.c aiminimax.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o aiminimax.o aiminimax.c

aiminimaxt.o: aiminimaxt.c aiminimaxt.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o aiminimaxt.o aiminimaxt.c

algorithm.o: algorithm.c algorithm.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o algorithm.o algorithm.c

config.o: config.c config.h
	$(CC) $(CFLAGS) $(INC) $(MACROS)\
		-fpic -c -o config.o config.c

$(GLEIPNIR_DIR)/$(GLINE_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINE_H)

$(GLEIPNIR_DIR)/$(GLINES_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINES_H)

$(GLEIPNIR_DIR)/$(GLINEREAD_H): FORCE
	cd $(GLEIPNIR_DIR)	&& $(MAKE) $(GLINEREAD_H)

$(CORE_DIR)/$(CORE_A): FORCE
	cd $(CORE_DIR)		&& $(MAKE) $(CORE_A)\
					CC="$(CC)"\
					CFLAGS="$(CFLAGS)"

$(CORE_DIR)/$(CORE_SO): FORCE
	cd $(CORE_DIR)		&& $(MAKE) $(CORE_SO)\
					CC="$(CC)"\
					CFLAGS="$(CFLAGS)"\
					LDFLAGS="$(LDFLAGS)"

$(CORE_DIR)/$(CORE_H): FORCE
	cd $(CORE_DIR)		&& $(MAKE) $(CORE_H)

clean:
	rm -f $(OBJS)

mrproper: clean
	rm -f $(OBJ_A) $(OBJ_SO)

clean-dist: mrproper
	rm -f $(HDR)

dist: clean-dist
	$(MAKE) $(HDR)

$(HDR): $(HDRS) $(CORE_DIR)/$(CORE_H)
	cat $(HDR_LICENSE)				> $(HDR)
	printf '%s\n%s\n'\
		'#ifndef HNEFATAFL_AIM'\
		'#define HNEFATAFL_AIM'			>> $(HDR)
	cat	$(CORE_DIR)/hnefatafl.h\
		| grep '^#define HNEFATAFL_ZHASH'\
		&& printf '%s' $(MACROS)\
			| grep 'HNEFATAFL_AIM_ZHASH'\
			&& printf '#define HNEFATAFL_AIM_ZHASH\n'\
							>> $(HDR)\
			|| true\
		|| true
	printf '#endif\n\n'				>> $(HDR)
	$(HDR_DCOMMENT) $(HDRS)				>> $(HDR)

clang: clean
	$(CLANG) $(CC) -g -std=c99 -O0 $(INC) -c *.c

cppcheck:
	$(CPPCHECK) $(INC) *.c

gcc: clean
	$(MAKE) dynamic CC="$(GCC)" CFLAGS="" LDFLAGS=""

lint:
	$(LINT) $(INC) $(MACROS) -systemdirs\
		"/usr/include:$(GLEIPNIR_DIR):$(CORE_DIR)"\
		*.c

.PHONY: all clean mrproper\
	dynamic static\
	clean-dist dist\
	clang cppcheck gcc lint

FORCE:

