.POSIX:

DESTDIR :=
PREFIX  := /usr
BINDIR  := /bin
MANDIR  := /share/man
INSTALL := install
OS      := unix

HOSTCC  := gcc
CC      := $(HOSTCC)
MAKE	:= make

BINVM   := bin/vm
BINVMRUN:= bin/vm
CROSSCC := i686-w64-mingw32-gcc

CFLAGS := -O2
# defined with =, not := as ext/CFLAGS and ext/LDFLAGS are not yet ready
OL_CFLAGS = `cat $(PWD)/ext/CFLAGS`
OL_LDFLAGS = `cat $(PWD)/ext/LDFLAGS`

# for cross compiling, use these variables to set additional flags
CROSS_CFLAGS =
CROSS_LDFLAGS =

## Pseudo targets

all: owl documentation
owl: bin/ol
documentation: owl doc/ol.1.gz doc/ovm.1.gz


### Lisp boostrap

## virtual machine


bin/vm: c/vm.c
	$(CC) $(CFLAGS) $(OL_CFLAGS) -o $@ $? $(LDFLAGS) $(OL_LDFLAGS)

bin/vm-simple:
	# write a host vm later used to build extensions
	# TODO: assuming unix is the host
	touch ext/unix/enabled
	bin/make_c.sh simple
	echo 'static void *heap = 0;' | cat - c/_vm.c | $(HOSTCC) -o $@ $(CFLAGS) $(OL_CFLAGS) -x c -

c/_vm.c: bin/vm-simple c/ovm.c c/ovm.h ext/*/*.c
	# remove comments and most white-space
	#sed -f bin/compact.sed $? >$@
	# clean old build system choice
	rm -f ext/unix/enabled
	rm -f ext/win32/enabled

	# enable chosen os functions
	touch ext/$(OS)/enabled
	bin/make_c.sh

c/vm.c: c/_vm.c
	echo 'static void *heap = 0;' | cat - $? >$@

## bytecode image (fixedpoint)

fasl/ol.fasl: fasl/init.fasl owl/*.scm owl/*/*.scm scheme/*.scm tests/*.scm tests/*.sh
	# selfcompile boot.fasl until a fixed point is reached
	$(MAKE) bin/vm
	CFLAGS="$(CFLAGS) $(OL_CFLAGS)" LDFLAGS="$(LDFLAGS) $(OL_LDFLAGS)" $(BINVMRUN) fasl/init.fasl -r bin/fasl-build.scm -f $(BINVM) fasl/boot.fasl -r owl/ol.scm -o fasl/bootp.fasl

## binary image

c/ol.c: fasl/ol.fasl
	# compile the repl using the fixed point image
	$(BINVMRUN) fasl/ol.fasl --run owl/ol.scm -s some -o $@

bin/ol: c/ol.c
	# compile the real owl repl binary
	$(CC) $(CFLAGS) $(OL_CFLAGS) -o bin/olp $? $(LDFLAGS) $(OL_LDFLAGS)
	# CC="$(CC)" LDFLAGS="$(LDFLAGS) $(OL_LDFLAGS)" CFLAGS="$(CFLAGS) $(OL_CFLAGS)" sh tests/run all bin/olp
	test '!' -f $@ || mv $@ bin/ol-old
	mv bin/olp $@

bin/ol.exe: c/ol.c
	# compile the real owl repl binary
	$(CC) $(CFLAGS) $(OL_CFLAGS) -o bin/ol $? $(LDFLAGS) $(OL_LDFLAGS)

c/ol-small.c: fasl/ol.fasl
	# small version for release
	$(BINVMRUN) fasl/ol.fasl --run owl/ol.scm -s none -o $@

### Documentation

## manual pages

.SUFFIXES: .1 .1.gz
.1.1.gz:
	gzip -9n < $< > $@

## other documentation

web-manual.html: web-manual.md
	pandoc --metadata title=owllisp --toc -f gfm -s $< > $@

web-manual.md: Makefile bin/feather doc/*.md owl/*.scm owl/*/*.scm scheme/*.scm
	bin/ol -r bin/feather -o web-manual.md \
		doc/intro.md doc/libraries.md \
		"## Data Structures" \
		owl/lazy.scm \
		owl/queue.scm \
		owl/string.scm \
		owl/list.scm \
		owl/vector.scm \
		owl/list-extra.scm \
		owl/bytevector.scm \
		owl/rlist.scm \
		owl/ff.scm \
		owl/iff.scm \
		"## Owl Things" \
		owl/fasl.scm \
		owl/lcd.scm \
		owl/compile.scm \
		owl/gensym.scm \
		owl/variable.scm \
		owl/proof.scm \
		owl/syntax-rules.scm \
		owl/thread.scm \
		"## Math" \
		owl/math.scm \
		owl/math/integer.scm \
		owl/math/rational.scm \
		owl/math/complex.scm \
		owl/math/extra.scm \
		"## Misc" \
		owl/args.scm \
		owl/metric.scm \
		owl/parse.scm \
		owl/date.scm \
		owl/digest.scm \
		owl/readline.scm \
		owl/regex.scm \
		owl/random.scm \
		owl/io.scm \
		owl/render.scm \
		owl/format.scm \
		owl/sort.scm \
		owl/syscall.scm \
		owl/sys.scm \
		owl/os.scm \
		owl/terminal.scm \
		owl/time.scm \
		owl/unicode.scm \
		doc/internals.md \
		doc/vm.md \
		doc/primops.md \
		"## Compiler" \
		owl/eval.scm owl/eval/alpha.scm owl/eval/assemble.scm owl/eval/ast.scm owl/eval/cgen.scm owl/eval/closure.scm owl/eval/rtl.scm owl/eval/cps.scm owl/eval/data.scm owl/eval/env.scm owl/eval/fixedpoint.scm owl/eval/register.scm \
		doc/thanks.md \
		doc/related.md \
		doc/faq.md



manual.man: manual.md
	pandoc $? -s -t man >$@
	pandoc --pdf-engine xelatex -o $@ $?


### Tests

fasltest: bin/vm fasl/ol.fasl
	echo "tests ok :3"
	# sh tests/run all bin/vm fasl/ol.fasl

test: bin/ol
	echo "yup :3"
	# sh tests/run all bin/ol

random-test: bin/vm bin/ol fasl/ol.fasl
	echo "fine :3"
	# sh tests/run random bin/vm fasl/ol.fasl
	# sh tests/run random bin/ol

mkrat-test: tests/mkrat/ext.c tests/mkrat/test.scm
	bin/ol -o tests/mkrat/test.c tests/mkrat/test.scm
	$(CC) -g $(CFLAGS) $(OL_CFLAGS) $(LDFLAGS) $(OL_LDFLAGS) -Ic -o tests/mkrat/test \
		-DPRIM_CUSTOM -DPRIM_FP_API tests/mkrat/ext.c tests/mkrat/test.c
	tests/mkrat/test

## Automatically generated data

owl/unicode-char-folds.scm:
	echo "(define char-folds '(" >owl/unicode-char-folds.scm
	curl http://www.unicode.org/Public/6.0.0/ucd/CaseFolding.txt | grep "[0-9A-F]* [SFC]; " | sed -re 's/ #.*//' -e 's/( [SFC])?;//g' -e 's/^/ /' -e 's/ / #x/g' -e 's/ /(/' -e 's/$$/)/' | tr "[A-F]" "[a-f]" >> owl/unicode-char-folds.scm
	echo '))' >>owl/unicode-char-folds.scm

## Release tarball

tarball: c/ol.c bin/ol
	# check that version is specified
	echo "${VERSION}" | grep [0-9]
	# make a new tarball
	-rm -rf owl-${VERSION}
	mkdir owl-${VERSION}
	cp -va bin owl-${VERSION} # keep times
	-rm owl-${VERSION}/bin/vm owl-${VERSION}/bin/ol owl-${VERSION}/bin/ol-old
	cp -va Makefile c fasl LICENCE README.md owl scheme tests doc owl-${VERSION}
	tar -f - -c owl-${VERSION} | gzip -9 > owl-${VERSION}.tar.gz
	# check that build of the contents succeeds
	find owl-${VERSION}
	cd owl-${VERSION} && $(MAKE)
	owl-${VERSION}/bin/ol --version
	bin/vm fasl/ol.fasl --run owl/ol.scm -s none -o ol-${VERSION}.c
	cc -O -o ol-${VERSION} ol-${VERSION}.c
	./ol-${VERSION} --version
	gzip -9 ol-${VERSION}.c


## Installation

install: bin/ol bin/vm doc/ol.1.gz doc/ovm.1.gz
	-mkdir -p $(DESTDIR)$(PREFIX)$(BINDIR)
	-mkdir -p $(DESTDIR)$(PREFIX)$(MANDIR)/man1
	$(INSTALL) -m 755 bin/ol $(DESTDIR)$(PREFIX)$(BINDIR)/ol
	$(INSTALL) -m 755 bin/vm $(DESTDIR)$(PREFIX)$(BINDIR)/ovm
	$(INSTALL) -m 644 doc/ol.1.gz $(DESTDIR)$(PREFIX)$(MANDIR)/man1/ol.1.gz
	$(INSTALL) -m 644 doc/ovm.1.gz $(DESTDIR)$(PREFIX)$(MANDIR)/man1/ovm.1.gz

bin/feather.bin: bin/ol
	./bin/ol -O2 -x c -o - ./bin/feather | $(CC) -x c $(CFLAGS) $(OL_CFLAGS) -o $@ -

install-tools: bin/feather.bin doc/feather.1.gz
	$(INSTALL) -m 755 bin/feather.bin $(DESTDIR)$(PREFIX)$(BINDIR)/feather
	$(INSTALL) -m 644 doc/feather.1.gz $(DESTDIR)$(PREFIX)$(MANDIR)/man1/feather.1.gz

uninstall:
	-rm -f $(DESTDIR)$(PREFIX)$(BINDIR)/ol
	-rm -f $(DESTDIR)$(PREFIX)$(BINDIR)/ovm
	-rm -f $(DESTDIR)$(PREFIX)$(MANDIR)/man1/ol.1.gz
	-rm -f $(DESTDIR)$(PREFIX)$(MANDIR)/man1/ovm.1.gz

clean:
	-rm -f fasl/boot.fasl fasl/bootp.fasl fasl/ol.fasl
	-rm -f c/_vm.c c/vm.c c/ol.c
	-rm -f doc/*.gz manual.md
	-rm -f tmp/*
	-rm -f bin/ol bin/ol-old bin/vm bin/vm-simple

cross:
	$(MAKE) CC=$(CROSSCC) OS=win32 LDFLAGS='$(LDFLAGS) $(OL_LDFLAGS) $(CROSS_LDFLAGS) -lws2_32' BINVMRUN="`which wine` bin/vm.exe" BINVM=bin/vm.exe CFLAGS='$(CFLAGS) $(OL_CFLAGS) $(CROSS_CFLAGS)' bin/ol.exe

.PHONY: all documentation owl clean install uninstall random-test test fasltest OS cross
