SHELL		= /bin/sh
MAKE		= make

CC		= cc
CFLAGS		= -DNDEBUG
LDFLAGS		= $(CFLAGS)

PRGNAM		= test
BIN		= $(PRGNAM)
OBJS		= config.o\
		messages.o\
		test_line.o\
		test_lines.o\
		test_lineread.o\
		test_lang.o\
		$(PRGNAM).o

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=128 -Winline -Winit-self\
		-Winvalid-pch -Wjump-misses-init -Wlarger-than=128\
		-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=128 -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 -nof -strict -strict-lib -ansi89limits\
		-exportany -systemdirerrors -bounds +likelybounds\
		+boolint
VALGRIND	= valgrind --leak-check=full

LINE		= gleipnir_line
LINE_A		= lib$(LINE).a
LINE_SO		= lib$(LINE).so
LINE_DIR	= ../$(LINE)

LINES		= gleipnir_lines
LINES_A		= lib$(LINES).a
LINES_SO	= lib$(LINES).so
LINES_DIR	= ../$(LINES)

LINEREAD	= gleipnir_lineread
LINEREAD_A	= lib$(LINEREAD).a
LINEREAD_SO	= lib$(LINEREAD).so
LINEREAD_DIR	= ../$(LINEREAD)

LANG		= gleipnir_lang
LANG_A		= lib$(LANG).a
LANG_SO		= lib$(LANG).so
LANG_DIR	= ../$(LANG)

INC		= -I.\
		-I$(LINE_DIR)\
		-I$(LINES_DIR)\
		-I$(LINEREAD_DIR)\
		-I$(LANG_DIR)
LIB		= -L.\
		-L$(LINE_DIR)\
		-L$(LINES_DIR)\
		-L$(LINEREAD_DIR)\
		-L$(LANG_DIR)
LDLIBS		= -l$(LINE)\
		-l$(LINES)\
		-l$(LINEREAD)\
		-l$(LANG)

all: static

dynamic: $(OBJS)\
		$(LINE_DIR)/$(LINE_SO)\
		$(LINES_DIR)/$(LINES_SO)\
		$(LINEREAD_DIR)/$(LINEREAD_SO)\
		$(LANG_DIR)/$(LANG_SO)
	$(CC) $(CFLAGS) $(LDLIBS) $(LIB) $(INC) -o $(BIN) $(OBJS)

static: $(OBJS)\
		$(LINE_DIR)/$(LINE_A)\
		$(LINES_DIR)/$(LINES_A)\
		$(LINEREAD_DIR)/$(LINEREAD_A)\
		$(LANG_DIR)/$(LANG_A)
	$(CC) $(CFLAGS) $(INC) -o $(BIN) $(OBJS)\
		$(LINE_DIR)/$(LINE_A)\
		$(LINES_DIR)/$(LINES_A)\
		$(LINEREAD_DIR)/$(LINEREAD_A)\
		$(LANG_DIR)/$(LANG_A)

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

messages.o: messages.c messages.h
	$(CC) $(CFLAGS) $(INC) -c -o messages.o messages.c

test.o: test.c
	$(CC) $(CFLAGS) $(INC) -c -o test.o test.c

test_line.o: test_line.c test_line.h
	$(CC) $(CFLAGS) $(INC) -c -o test_line.o test_line.c

test_lines.o: test_lines.c test_lines.h
	$(CC) $(CFLAGS) $(INC) -c -o test_lines.o test_lines.c

test_lineread.o: test_lineread.c test_lineread.h
	$(CC) $(CFLAGS) $(INC) -c -o test_lineread.o test_lineread.c

test_lang.o: test_lang.c test_lang.h
	$(CC) $(CFLAGS) $(INC) -c -o test_lang.o test_lang.c

$(LINE_DIR)/$(LINE_SO): FORCE
	cd $(LINE_DIR)		&& $(MAKE) dynamic

$(LINE_DIR)/$(LINE_A): FORCE
	cd $(LINE_DIR)		&& $(MAKE) static

$(LINES_DIR)/$(LINES_SO): FORCE
	cd $(LINES_DIR)		&& $(MAKE) dynamic

$(LINES_DIR)/$(LINES_A): FORCE
	cd $(LINES_DIR)		&& $(MAKE) static

$(LINEREAD_DIR)/$(LINEREAD_SO): FORCE
	cd $(LINEREAD_DIR)	&& $(MAKE) dynamic

$(LINEREAD_DIR)/$(LINEREAD_A): FORCE
	cd $(LINEREAD_DIR)	&& $(MAKE) static

$(LANG_DIR)/$(LANG_SO): FORCE
	cd $(LANG_DIR)		&& $(MAKE) dynamic

$(LANG_DIR)/$(LANG_A): FORCE
	cd $(LANG_DIR)		&& $(MAKE) static

clean:
	rm -f $(OBJS)

mrproper: clean
	rm -f $(BIN)

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

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

gcc: $(OBJS)\
		$(LINE_DIR)/$(LINE_SO)\
		$(LINES_DIR)/$(LINES_SO)\
		$(LINEREAD_DIR)/$(LINEREAD_SO)\
		$(LANG_DIR)/$(LANG_SO)
	$(GCC) $(LDLIBS) $(LIB) $(INC) -o $(BIN) $(OBJS)

lint:
	$(LINT) $(INC) -systemdirs\
		"/usr/include:$(LINE_DIR):$(LINES_DIR):$(LINEREAD_DIR):$(LANG_DIR)"\
		*.c

run: dynamic
	@LD_LIBRARY_PATH="$(LINE_DIR):$(LINES_DIR):$(LINEREAD_DIR):$(LANG_DIR)"\
		./$(BIN)

run_v: dynamic
	@LD_LIBRARY_PATH="$(LINE_DIR):$(LINES_DIR):$(LINEREAD_DIR):$(LANG_DIR)"\
		./$(BIN) -v

valgrind: dynamic
	@LD_LIBRARY_PATH="$(LINE_DIR):$(LINES_DIR):$(LINEREAD_DIR):$(LANG_DIR)"\
		$(VALGRIND) $(VALGFLAGS) ./$(BIN)

valgrind_v: dynamic
	@LD_LIBRARY_PATH="$(LINE_DIR):$(LINES_DIR):$(LINEREAD_DIR):$(LANG_DIR)"\
		$(VALGRIND) $(VALGFLAGS) ./$(BIN) -v

.PHONY: all clean mrproper\
	dynamic static\
	clang cppcheck gcc lint\
	run run_v valgrind valgrind_v

FORCE:

