NAME    := $(shell grep 'define PROGRAM ".*"' sys/sys.h | cut -d \" -f 2)
VERSION := $(shell grep 'define VERSION ".*"' sys/sys.h | cut -d \" -f 2)

SYSTEMS := linux osx windows

# probably needs more mingw mappings
SYSMAP  := Linux/linux MINGW32_NT-6.1/windows Darwin/osx

SYS     := $(notdir $(filter $(shell uname)%,$(SYSMAP)))
MAINS   := $(foreach i, $(SYSTEMS), sys/$i.cc)
MAIN    := sys/$(SYS).cc

DIRS := sys

PRE := $(PWD)/lib
LIBS := gc ffi gmp guile-2.0 # readline
LIBDIRS := $(addprefix lib/, $(LIBS))
LIBFILES := $(foreach i, $(LIBS), lib/lib/lib$i.a)

#libffi wants to be treated special with the include dirs
ffiver  := 3.0.12

# preserve the right order of the LIBS above and the LIBURLS below
LIBURLS := http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc-7.2d.tar.gz
LIBURLS += ftp://sourceware.org/pub/libffi/libffi-$(ffiver).tar.gz
LIBURLS += ftp://ftp.gmplib.org/pub/gmp/gmp-5.1.1.tar.bz2
#LIBURLS += ftp://ftp.cwru.edu/pub/bash/readline-6.2.tar.gz
LIBURLS += http://hydra.nixos.org/build/4290536/download/3/guile-2.0.7.157-929d1.tar.gz #ftp://ftp.gnu.org/gnu/guile/guile-2.0.7.tar.gz 

LIBPKGS := $(addprefix lib/, $(notdir $(LIBURLS)))

SRC := $(filter-out $(filter-out $(MAIN), $(MAINS)), $(wildcard $(addsuffix /*.cc, $(DIRS))))
HDR := $(wildcard $(addsuffix /*.h, $(DIRS)))
RES := $(wildcard $(addprefix res/*, .ico))
OBJ := $(SRC:%.cc=%.o)

FILES := Makefile $(HDR) $(wildcard $(addsuffix /*.cc, $(DIRS)))

LDFLAGSwindows := -lgnu -lintl -liconv -lintl -lws2_32 
LDFLAGSlinux := -ldl -lrt -lpthread -lcrypt
LDFLAGSosx := 
LDFLAGS := -lguile-2.0 -lltdl -lgc -lgmp -lffi -lunistring -lm $(LDFLAGS$(SYS))

CXXFLAGSwindows := -static -static-libgcc -mwindows -mwin32 -mthreads
CXXFLAGSlinux :=
CXXFLAGSosx :=
CXXFLAGS := -Os -rdynamic -fvisibility=hidden -s -I$(PRE)/include -I$(PRE)/include/guile/2.0 -L$(PRE)/lib $(CXXFLAGS$(SYS))

$(NAME): $(LIBFILES) $(OBJ)
	$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)

# We need to statically build and link all libraries, to provide a uniform environment on every OS.
# That means manually configuring and building from the source packages of all dependencies.

$(LIBPKGS):
	wget -Plib $(filter %$(notdir $@), $(LIBURLS))

$(LIBDIRS): $(LIBPKGS)
	test -d $@ || mkdir $@
	tar xaf lib/$(notdir $(filter $@% ,$(join $(LIBDIRS), $(addprefix /, $^)))) -C $@ --strip-components=1

CFGFLAGS := --prefix=$(PRE) --disable-shared --disable-fast-install --with-gnu-ld # --without-pic --disable-libtool-lock 

define make_library
$(1): $($(2)deps)
	for p in $(wildcard $(foreach d,$2 $2_$(SYS),lib/patches/$d.diff)); do patch -d lib/$(2) -i $$$$p; done
	cd lib/$(2) && ./configure $(CFGFLAGS) $($(2)flags) && make install
endef

gcdeps  := lib/gc
gcflags := --without-ecos --disable-gcj-support --disable-java-finalization #--disable-threads --disable-atomic-uncollectible
ffideps  := lib/ffi
ffiflags :=
gmpdeps  := lib/gmp
gmpflags :=  --without-readline
guile-2.0deps  := lib/lib/libffi.a lib/lib/libgc.a lib/lib/libgmp.a lib/guile-2.0
guile-2.0flags := --disable-deprecated --enable-nls --with-libgmp-prefix=$(PRE)  LIBFFI_CFLAGS='-I$(PRE)/lib/libffi-$(ffiver)/include' LIBFFI_LIBS='-lffi' BDW_GC_LIBS='-lgc' BDW_GC_CFLAGS='-I$(PRE)'  CFLAGS=' -s -rdynamic' CPPFLAGS='-D HAVE_GC_SET_FINALIZER_NOTIFIER -D HAVE_GC_GET_FREE_SPACE_DIVISOR -D HAVE_GC_GET_HEAP_USAGE_SAFE -D HAVE_GC_SET_FINALIZE_ON_DEMAND'

#all the library rules
$(foreach l,$(LIBFILES),$(eval $(call make_library,$(l),$(l:lib/lib/lib%.a=%))))

clean:
	rm -f -r $(NAME)* $(OBJ)

cleanlibs:
	rm -fr lib/lib lib/include lib/bin lib/share
	for i in $(LIBDIRS);do test -d $$i && cd $$i && make distclean; done

tags:
	@echo "$(HDR) $(SRC)"|tr ' ' '\n' | $(TAGS) -e --language-force=C++ -f TAGS -L -

archive:
	tar czf ../$(NAME).$(VERSION).tgz --exclude '.*' --exclude '._*' $(FILES)

deb:

dmg:

nsis:

todo:
	@grep -r -n --exclude="Makefile" TODO *

check:
	$(CXX) $(CXXFLAGS) -fsyntax-only --pedantic -Wno-gnu $(SRC)

test: $(SRC)
	$(CXX) $(CXXFLAGS) -O0 -o $(NAME) $^ $(LDLIBS)
	./$(NAME)

debug: $(SRC)
	$(CXX) -g -o $(NAME) $^ $(LDLIBS)

recap:
	@echo $(NAME) $(VERSION) $(SYS) $(LIB)
	@echo
	@for i in $(FILES); do echo $$i; done

.PHONY: clean cleanlibs test check debug archive todo tags recap
