source = fuuko34.c
cpp_source = renamed_source.cc

ifeq ($(OSTYPE),cygwin)
eext = .exe
gcc_opt = -O3 -Wall -Werror
# clang 3.5.2 generates incorrect code with optimization enabled :(
# https://llvm.org/bugs/show_bug.cgi?id=25045
clang_opt = -O0 -Wall -Werror
else
eext =
gcc_opt = -O3 -Wall -Werror
clang_opt = -O3 -Wall -Werror
endif

encode1g = encode_gcc_c90$(eext)
encode2g = encode_gcc_c99$(eext)
encode3g = encode_gcc_c11$(eext)
encode4g = encode_gcc_cpp98$(eext)
encode5g = encode_gcc_cpp11$(eext)
encode1c = encode_clang_c90$(eext)
encode2c = encode_clang_c99$(eext)
encode3c = encode_clang_c11$(eext)
encode4c = encode_clang_cpp98$(eext)
encode5c = encode_clang_cpp11$(eext)

targets = \
	$(encode1g) \
	$(encode2g) \
	$(encode3g) \
	$(encode4g) \
	$(encode5g) \
	$(encode1c) \
	$(encode2c) \
	$(encode3c) \
	$(encode4c) \
	$(encode5c)

all: $(targets)

$(cpp_source): $(source)
	ln -s $< $@

$(encode1g): $(source)
	gcc $(gcc_opt) -std=c90 $< -lm -o $@

$(encode2g): $(source)
	gcc $(gcc_opt) -std=c99 $< -lm -o $@

$(encode3g): $(source)
	gcc $(gcc_opt) -std=c11 $< -lm -o $@

$(encode4g): $(cpp_source)
	g++ $(gcc_opt) -std=c++98 $< -lm -o $@

$(encode5g): $(cpp_source)
	g++ $(gcc_opt) -std=c++11 $< -lm -o $@

$(encode1c): $(source)
	clang $(clang_opt) -std=c90 $< -lm -o $@

$(encode2c): $(source)
	clang $(clang_opt) -std=c99 $< -lm -o $@

$(encode3c): $(source)
	clang $(clang_opt) -std=c11 $< -lm -o $@

$(encode4c): $(cpp_source)
	clang++ $(clang_opt) -std=c++98 $< -lm -o $@

$(encode5c): $(cpp_source)
	clang++ $(clang_opt) -std=c++11 $< -lm -o $@


test: \
	test_encode_gcc1.passed \
	test_encode_gcc2.passed \
	test_encode_gcc3.passed \
	test_encode_gcc4.passed \
	test_encode_gcc5.passed \
	test_encode_clang1.passed \
	test_encode_clang2.passed \
	test_encode_clang3.passed \
	test_encode_clang4.passed \
	test_encode_clang5.passed \
	test_entropy.passed
	@echo "All good."

test_encode_gcc1.passed: test_encode_input.bin test_encode_output1g.bin
	cmp $^ && touch $@ && echo "PASSED: [gcc/c90]"

test_encode_gcc2.passed: test_encode_input.bin test_encode_output2g.bin
	cmp $^ && touch $@ && echo "PASSED: [gcc/c99]"

test_encode_gcc3.passed: test_encode_input.bin test_encode_output3g.bin
	cmp $^ && touch $@ && echo "PASSED: [gcc/c11]"

test_encode_gcc4.passed: test_encode_input.bin test_encode_output4g.bin
	cmp $^ && touch $@ && echo "PASSED: [g++/c++98]"

test_encode_gcc5.passed: test_encode_input.bin test_encode_output5g.bin
	cmp $^ && touch $@ && echo "PASSED: [g++/c++11]"

test_encode_clang1.passed: test_encode_input.bin test_encode_output1c.bin
	cmp $^ && touch $@ && echo "PASSED: [clang/c90]"

test_encode_clang2.passed: test_encode_input.bin test_encode_output2c.bin
	cmp $^ && touch $@ && echo "PASSED: [clang/c99]"

test_encode_clang3.passed: test_encode_input.bin test_encode_output3c.bin
	cmp $^ && touch $@ && echo "PASSED: [clang/c11]"

test_encode_clang4.passed: test_encode_input.bin test_encode_output4c.bin
	cmp $^ && touch $@ && echo "PASSED: [clang++/c++98]"

test_encode_clang5.passed: test_encode_input.bin test_encode_output5c.bin
	cmp $^ && touch $@ && echo "PASSED: [clang++/c++11]"

test_entropy.passed: test_encode_output1g.c test_encode_output1gx.c
	if diff -q $^; then echo "FAILED: Unexpected match"; rm -f $@; false; else touch $@ && echo "PASSED: [entropy]"; fi

test_encode_input.bin: generate_test_input.pl
	perl $< $@

test_encode_output1g.bin: test_encode_output1g$(eext)
	./$< > $@

test_encode_output2g.bin: test_encode_output2g$(eext)
	./$< > $@

test_encode_output3g.bin: test_encode_output3g$(eext)
	./$< > $@

test_encode_output4g.bin: test_encode_output4g$(eext)
	./$< > $@

test_encode_output5g.bin: test_encode_output5g$(eext)
	./$< > $@

test_encode_output1c.bin: test_encode_output1c$(eext)
	./$< > $@

test_encode_output2c.bin: test_encode_output2c$(eext)
	./$< > $@

test_encode_output3c.bin: test_encode_output3c$(eext)
	./$< > $@

test_encode_output4c.bin: test_encode_output4c$(eext)
	./$< > $@

test_encode_output5c.bin: test_encode_output5c$(eext)
	./$< > $@

test_encode_output1g$(eext): test_encode_output1g.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output2g$(eext): test_encode_output2g.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output3g$(eext): test_encode_output3g.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output4g$(eext): test_encode_output4g.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output5g$(eext): test_encode_output5g.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output1c$(eext): test_encode_output1c.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output2c$(eext): test_encode_output2c.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output3c$(eext): test_encode_output3c.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output4c$(eext): test_encode_output4c.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output5c$(eext): test_encode_output5c.c
	gcc -Wall -O0 -std=c90 $< -o $@

test_encode_output1g.c: test_encode_input.bin $(encode1g)
	./$(encode1g) < $< > $@

test_encode_output1gx.c: test_encode_input.bin $(encode1g)
	./$(encode1g) extra_arg < $< > $@

test_encode_output2g.c: test_encode_input.bin $(encode2g)
	./$(encode2g) < $< > $@

test_encode_output3g.c: test_encode_input.bin $(encode3g)
	./$(encode3g) < $< > $@

test_encode_output4g.c: test_encode_input.bin $(encode4g)
	./$(encode4g) < $< > $@

test_encode_output5g.c: test_encode_input.bin $(encode5g)
	./$(encode5g) < $< > $@

test_encode_output1c.c: test_encode_input.bin $(encode1c)
	./$(encode1c) < $< > $@

test_encode_output2c.c: test_encode_input.bin $(encode2c)
	./$(encode2c) < $< > $@

test_encode_output3c.c: test_encode_input.bin $(encode3c)
	./$(encode3c) < $< > $@

test_encode_output4c.c: test_encode_input.bin $(encode4c)
	./$(encode4c) < $< > $@

test_encode_output5c.c: test_encode_input.bin $(encode5c)
	./$(encode5c) < $< > $@

clean:
	-rm -f $(targets) $(cpp_source) test_*

backup:
	-rm -f backup.tar.gz
	tar cf backup.tar *.c *.cc *.log *.pl *.txt Makefile entry/*
	gzip -9 backup.tar
