# Makefile
#
# APRON Library / Octagonal Domain
#
# Copyright (C) Antoine Mine' 2006

# This file is part of the APRON Library, released under LGPL license.
# Please read the COPYING file packaged in the distribution.

include ../Makefile.config

PREFIX = $(APRON_PREFIX)

# C include and lib directories
INCDIR = $(PREFIX)/include
LIBDIR = $(PREFIX)/lib
BINDIR = $(PREFIX)/bin

SRCDIR = $(shell pwd)

#---------------------------------------
# Programs
#---------------------------------------

# Library creation
SHARED = gcc -shared

#---------------------------------------
# Flags
#---------------------------------------

# Use ICFLAGS to specify machine-independent compilation flags.
ICFLAGS = \
-I$(MLGMPIDL_PREFIX)/include \
-I../newpolka \
-I../apron \
-I../mlapronidl \
-I../num \
-I../itv \
-I$(MPFR_PREFIX)/include -I$(GMP_PREFIX)/include \
-I$(CAML_PREFIX)/lib/ocaml -I$(CAMLIDL_PREFIX)/lib/ocaml

# Caml
OCAMLINC = -I $(MLGMPIDL_PREFIX)/lib -I ../mlapronidl

#---------------------------------------
# Files
#---------------------------------------

CCSOURCES = oct_hmat.c oct_print.c oct_transfer.c oct_closure.c oct_nary.c \
	    oct_representation.c oct_predicate.c oct_resize.c

CCINC = oct_internal.h oct_fun.h

# trigers a whole recompilation
#DEPS = $(APRON_PREFIX)/include/ap_abstract0.h

#---------------------------------------
# Rules
#---------------------------------------

root:
	@echo
	@echo "Please choose a target from:"
	@echo
	@echo " Il Ill MPZ Rl Rll MPQ D Dl MPFR: single C library"
	@echo " all                     : all C libraries"
	@echo " ml                      : OCaml library"
	@echo " mlIl mlIll ...          : OCaml toplevel & byte-code"
	@echo " allml                   : everything"
	@echo " install                 : to install what has been compiled"
	@echo " clean                   : remove objects"
	@echo " distclean               : clean & uninstall"
	@echo " mostyleclean            : remove objects & autogenerated"
	@echo " rebuild                 : rebuild autogenerated "
	@echo

all: Il Ill MPZ Ri Rll MPQ D Dl MPFR
allml: allIl allIll allMPZ allRi allRll allMPQ allD allDl allMPFR

allIl: Il mlIl
allIll: Ill mlIll
allMPZ: MPZ mlMPZ
allRi: Ri mlRi
allRll: Rll mlRll
allMPQ: MPQ mlMPQ
allD: D mlD
allDl: Dl mlDl
allMPFR: MPFR mlMPFR

Il: liboctIl.a liboctIl_debug.a octtestIl
Ill: liboctIll.a liboctIll_debug.a octtestIll
MPZ: liboctMPZ.a liboctMPZ_debug.a octtestMPZ
Ri: liboctRi.a liboctRi_debug.a octtestRi
Rll: liboctRll.a liboctRll_debug.a octtestRll
MPQ: liboctMPQ.a liboctMPQ_debug.a octtestMPQ
D: liboctD.a liboctD_debug.a octtestD
Dl: liboctDl.a liboctDl_debug.a octtestDl
MPFR: liboctMPFR.a liboctMPFR_debug.a octtestMPFR
ifneq ($(HAS_SHARED),)
Il: liboctIl.so liboctIl_debug.so
Ill: liboctIll.so liboctIll_debug.so
MPZ: liboctMPZ.so liboctMPZ_debug.so
Ri: liboctRi.so liboctRi_debug.so
Rll: liboctRll.so liboctRll_debug.so
MPQ: liboctMPQ.so liboctMPQ_debug.so
D: liboctD.so liboctD_debug.so
Dl: liboctDl.so liboctDl_debug.so
MPFR: liboctMPFR.so liboctMPFR_debug.so
endif

mlexample%.byte: mlexample.ml oct%.cma
	$(OCAMLC) $(OCAMLFLAGS) -I $(MLGMPIDL_INSTALL)/lib -I $(APRON_PREFIX)/lib -o $@ bigarray.cma gmp.cma apron.cma oct$*.cma $<

mlexample%.opt: mlexample.ml oct%.cmxa
	$(OCAMLOPT) $(OCAMLOPTFLAGS) -I $(MLGMPIDL_INSTALL)/lib -I $(APRON_PREFIX)/lib -o $@ bigarray.cmxa gmp.cmxa apron.cmxa oct$*.cmxa $<

clean:
	/bin/rm -f *.[ao] *.so octtest*
	/bin/rm -f *.?.tex *.log *.aux *.bbl *.blg *.toc *.dvi *.ps *.pstex*
	/bin/rm -fr *.cm[ioax] *.cmxa
	/bin/rm -fr octtop* octrun* tmp
	/bin/rm -fr *~ \#*\#

mostlyclean: clean
	/bin/rm -fr oct_caml.c oct.ml oct.mli

install:
	$(INSTALLd) $(INCDIR) $(INCDIR)/oct $(LIBDIR) $(BINDIR)
	$(INSTALL) oct.h $(INCDIR)
	$(INSTALL) $(CCINC) $(INCDIR)/oct
	for i in liboct*.* liboct*_debug.* liboct*_caml.* oct.idl; do \
		if test -f $$i; then $(INSTALL) $$i $(LIBDIR); fi; \
	done
	for i in dlloct*_caml.so; do \
		cp -f -d $$i $(LIBDIR); \
	done
	for i in octtest?? octtop?? octrun??; do \
		if test -f $$i; then $(INSTALL) $$i $(BINDIR); fi; \
	done
	for i in oct.mli oct.cmi oct.cmx oct*.cma oct*.cmxa oct.a; do \
		if test -f $$i; then $(INSTALL) $$i $(LIBDIR); fi; \
	done

uninstall:
	/bin/rm -fr $(INCDIR)/oct.h
	/bin/rm -f $(BINDIR)/octtest?? $(BINDIR)/octtop?? $(BINDIR)/octrun??
	/bin/rm -f $(LIBDIR)/liboct*.* $(LIBDIR)/liboct*_debug.*
	/bin/rm -f $(LIBDIR)/dlloct*.so $(LIBDIR)/dlloct*_debug.so
	/bin/rm -f $(LIBDIR)/oct.mli $(LIBDIR)/oct.cm[ix] $(LIBDIR)/oct.idl $(LIBDIR)/oct*.cma $(LIBDIR)/oct*.cmxa $(LIBDIR)/oct*.a

distclean: uninstall
	/bin/rm -f Makefile.depend

dist: Makefile COPYING README oct_doc.html sedscript_caml sedscript_c $(CCSOURCES) $(CCINC) oct.h oct_test.c oct.idl oct.mli oct.ml oct_caml.c
	(cd ..; tar zcvf octagons.tgz $(^:%=octagons/%))

#---------------------------------------
# IMPLICIT RULES AND DEPENDENCIES
#---------------------------------------

.SUFFIXES: .tex .c .h .a .o .so

#-----------------------------------
# C part
#-----------------------------------

liboct%.a: $(subst .c,%.o,$(CCSOURCES))
	$(AR) rcs $@ $^
	$(RANLIB) $@

liboct%_debug.a: $(subst .c,%_debug.o,$(CCSOURCES))
	$(AR) rcs $@ $^
	$(RANLIB) $@

liboct%.so: $(subst .c,%.o,$(CCSOURCES))
	$(SHARED) -o $@ $^

octtest%: liboct%_debug.a oct_test%.o
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -o $@ oct_test$*.o \
	-L. -loct$*_debug \
	-L../newpolka -lpolkaMPQ_debug \
	-L../apron -lapron_debug \
	-L$(MPFR_PREFIX)/lib -lmpfr \
	-L$(GMP_PREFIX)/lib -lgmp \
	-lm

%_caml.o: %_caml.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -c -o $@ $<

%_caml_debug.o: %_caml.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -c -o $@ $<

%Il.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGINT -c -o $@ $<
%Il_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_LONGINT -c -o $@ $<
%Ill.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGLONGINT -c -o $@ $<
%Ill_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_LONGLONGINT -c -o $@ $<
%MPZ.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_MPZ -I$(GMP_PREFIX)/include -c -o $@ $<
%MPZ_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_MPZ -I$(GMP_PREFIX)/include -c -o $@ $<

%Ri.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGRAT -c -o $@ $<
%Ri_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_LONGRAT -c -o $@ $<
%Rll.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGLONGRAT -c -o $@ $<
%Rll_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_LONGLONGRAT -c -o $@ $<
%MPQ.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_MPQ -I$(GMP_PREFIX)/include -c -o $@ $<
%MPQ_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS_DEBUG) $(ICFLAGS) -DNUM_MPQ -I$(GMP_PREFIX)/include -c -o $@ $<

%D.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_DOUBLE -c -o $@ $<
%D_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_DOUBLE -c -o $@ $<
%Dl.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGDOUBLE -c -o $@ $<
%Dl_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_LONGDOUBLE -c -o $@ $<
%MPFR.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_MPFR -c -o $@ $<
%MPFR_debug.o: %.c $(CCINC) $(DEPS)
	$(CC) $(CFLAGS) $(ICFLAGS) -DNUM_MPFR -c -o $@ $<

# TODO: mpfr ?

.PRECIOUS: liboct%.a liboct%_debug.a liboct%.so liboct%_debug.so
.PRECIOUS: liboct%_caml.a liboct%_caml_debug.a liboct%_caml.so liboct%_caml_debug.so
.PRECIOUS: %Il.o %Ill.o %MPZ.o %Ri.o %Rll.o %MPQ.o %D.o %Dl.o %MPFR.o
.PRECIOUS: %Il_debug.o %Ill_debug.o %MPZ_debug.o %Ri_debug.o %Rll_debug.o %MPQ_debug.o %D_debug.o %Dl_debug.o %MPFR_debug.o

#-----------------------------------
# Caml part
#-----------------------------------

.INTERMEDIATE: mlIl

ml: oct.mli oct.cmi oct.cmx oct.cma oct.cmxa oct.a
mlIl: ml octIl.cma octIl.cmxa liboctIl_caml.a liboctIl_caml_debug.a
mlIll: ml octIll.cma octIll.cmxa liboctIll_caml.a liboctIll_caml_debug.a 
mlMPZ: ml octMPZ.cma octMPZ.cmxa liboctMPZ_caml.a liboctMPZ_caml_debug.a
mlRll: ml octRll.cma octRll.cmxa liboctRll_caml.a liboctRll_caml_debug.a
mlMPQ: ml octMPQ.cma octMPQ.cmxa liboctMPQ_caml.a liboctMPQ_caml_debug.a 
mlD: ml octD.cma octD.cmxa liboctD_caml.a liboctD_caml_debug.a
mlDl: ml octDl.cma octDl.cmxa liboctDl_caml.a liboctDl_caml_debug.a
mlMPFR: ml octMPFR.cma octMPFR.cmxa liboctMPFR_caml.a liboctMPFR_caml_debug.a
ifneq ($(HAS_SHARED),)
mlIl: liboctIl_caml.so liboctIl_caml_debug.so dlloctIl_caml.so dlloctIl_caml_debug.so 
mlIll:liboctIll_caml.so liboctIll_caml_debug.so dlloctIll_caml.so dlloctIll_caml_debug.so 
mlMPZ:liboctMPZ_caml.so liboctMPZ_caml_debug.so dlloctMPZ_caml.so dlloctMPZ_caml_debug.so 
mlRll:liboctRll_caml.so liboctRll_caml_debug.so dlloctRll_caml.so dlloctRll_caml_debug.so 
mlMPQ:liboctMPQ_caml.so liboctMPQ_caml_debug.so dlloctMPQ_caml.so dlloctMPQ_caml_debug.so 
mlD:liboctD_caml.so liboctD_caml_debug.so dlloctD_caml.so dlloctD_caml_debug.so 
mlDl:liboctDl_caml.so liboctDl_caml_debug.so dlloctDl_caml.so dlloctDl_caml_debug.so 
mlMPFR:liboctMPFR_caml.so liboctMPFR_caml_debug.so dlloctMPFR_caml.so dlloctMPFR_caml_debug.so 
endif

#octtop%: oct.cma liboct_caml.a liboct%.a
#	$(OCAMLMKTOP) -noautolink $(OCAMLFLAGS) $(OCAMLINC) -o $@ -custom bigarray.cma gmp.cma apron.cma oct.cma -ccopt "-L. -L$(MLGMPIDL_PREFIX)/lib -L../mlapronidl -L../apron -L../itv -L$(MPFR_PREFIX)/lib -L$(GMP_PREFIX)/lib -L$(CAMLIDL_PREFIX)/lib/ocaml" -cclib "-loct_caml -loct$* -lapron_caml -lapron -lgmp_caml -lmpfr -lgmp -lbigarray -lcamlidl"

#octrun%: oct.cma liboct_caml.a
#	$(OCAMLC) -noautolink $(OCAMLFLAGS) $(OCAMLINC) -o $@ -make-runtime bigarray.cma gmp.cma apron.cma oct.cma -ccopt "-L. -L$(MLGMPIDL_PREFIX)/lib -L../mlapronidl -L../apron -L../itv -L$(MPFR_PREFIX)/lib -L$(GMP_PREFIX)/lib -L$(CAMLIDL_PREFIX)/lib/ocaml" -cclib "-loct_caml -loct$* -lapron_caml -lapron -lgmp_caml -lmpfr -lgmp -lbigarray -lcamlidl"

oct.cma: octMPQ.cma
	ln -s -f $^ $@
oct.cmxa: octMPQ.cmxa
	ln -s -f $^ $@
oct.a: octMPQ.a
	ln -s -f $^ $@

oct%.cma: oct.cmi oct.cmo liboct%_caml.a liboct%.a
	$(OCAMLMKLIB) -ocamlc "$(OCAMLC)" -verbose -o oct$* -oc oct$*_caml oct.cmo -loct$* -L$(APRON_PREFIX)/lib -Wl,-rpath,$(APRON_PREFIX)/lib

oct%.cmxa oct%.a: oct.cmi oct.cmx liboct%_caml.a liboct%.a
	$(OCAMLMKLIB) -ocamlopt "$(OCAMLOPT)" -verbose -o oct$* -oc oct$*_caml oct.cmx -loct$* -L$(APRON_PREFIX)/lib -Wl,-rpath,$(APRON_PREFIX)/lib

liboct%_caml.a: oct_caml.o liboct%.a
	$(AR) rcs $@ $<
	$(RANLIB) $@
liboct%_caml_debug.a: oct_caml_debug.o liboct%_debug.a
	$(AR) rcs $@ $<
	$(RANLIB) $@
liboct%_caml.so: oct_caml.o liboct%.so
	$(SHARED) -o $@ oct_caml.o -L. -loct$* -Wl,-rpath,$(APRON_PREFIX)/lib
liboct%_caml_debug.so: oct_caml_debug.o liboct%_debug.so
	$(SHARED) -o $@ oct_caml_debug.o -L. -loct$*_debug -Wl,-rpath,$(APRON_PREFIX)/lib
dlloct%_caml.so: liboct%_caml.so
	ln -s -f $^ $@
dlloct%_caml_debug.so: liboct%_caml_debug.so
	ln -s -f $^ $@

rebuild: oct.idl
	mkdir -p tmp
	cp ../mlapronidl/*.idl tmp
	cp oct.idl tmp/
	cd tmp && $(CAMLIDL) -no-include -nocpp -I . oct.idl
	$(SED) -f sedscript_c tmp/oct_stubs.c >oct_caml.c
	$(SED) -f sedscript_caml tmp/oct.ml >oct.ml
	$(SED) -f sedscript_caml tmp/oct.mli >oct.mli

.PRECIOUS: %_caml.c %.ml %.mli %.cmi liboct%_caml.a liboct%_caml.so oct.cmx oct.cmo

#---------------------------------------
# ML generic rules
#---------------------------------------

%.cmi: %.mli  $(DEPS)
	$(OCAMLC) $(OCAMLFLAGS) $(OCAMLINC) -c $<

%.cmo: %.ml %.cmi  $(DEPS)
	$(OCAMLC) $(OCAMLFLAGS) $(OCAMLINC) -c $<

%.cmx: %.ml %.cmi  $(DEPS)
	$(OCAMLOPT) $(OCAMLOPTFLAGS) $(OCAMLINC) -c $<



#-----------------------------------
# DEPENDENCIES
#-----------------------------------
