# FILE     Makefile
#
# Copyright (c) 2003-2006, James H. Woodyatt
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#   Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#
#   Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in
#   the documentation and/or other materials provided with the
#   distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
# OF THE POSSIBILITY OF SUCH DAMAGE. 

REQUIRE = unix
PREDICATES =

###############################################################################

.PHONY: default opt test test.opt clean install uninstall depend doc

default::

#OCAMLFINDOPT = -pp camlp4o -package "$(REQUIRE)" -predicates "$(PREDICATES)"
#OCAMLDEP = ocamldep -pp camlp4o

OCAMLFINDOPT = -package "$(REQUIRE)" -predicates "$(PREDICATES)"

OCAMLC       = ocamlfind ocamlc $(OCAMLFINDOPT)
OCAMLOPT     = ocamlfind ocamlopt $(OCAMLFINDOPT)
OCAMLMKLIB   = ocamlmklib
OCAMLMKTOP   = ocamlfind ocamlmktop $(OCAMLFINDOPT)
OCAMLDEP     = ocamldep
OCAMLLEX     = ocamllex
OCAMLYACC    = ocamlyacc
OCAMLDOC     = ocamlfind ocamldoc $(OCAMLFINDOPT)

DEBUG_OPT    = -g
WARN_ERROR   = -passopt -w -passopt Ae # -warn-error A
PRINCIPLE    = -principal
UNSAFE       = -unsafe -noassert

ALL_OCAML_OPT = $(WARN_ERROR) $(PRINCIPLE)

CC_OPT  = -ccopt -fPIC -ccopt -O2 -ccopt -Wall -ccopt -Wno-unused-variable
CMI_OPT = $(ALL_OCAML_OPT) $(DEBUG_OPT)
CMO_OPT = $(ALL_OCAML_OPT) $(DEBUG_OPT)
CMX_OPT = $(ALL_OCAML_OPT) $(UNSAFE) -inline 9

.SUFFIXES: .ml .mli .mll .mly .cmo .cmi .cma .cmx .cmxa

%.ml : %.mll
	$(OCAMLLEX) $<

%.ml %.mli : %.mly
	$(OCAMLYACC) -b$* $<

%.cmi : %.mli
	$(OCAMLC) $(CMI_OPT) -o $@ -c $<

%.cmi %.cmo : %.ml
	$(OCAMLC) $(CMO_OPT) -o $@ -c $<

%.cmi %.cmx %.o : %.ml
	$(OCAMLOPT) $(CMX_OPT) -o $@ -c $<

%.o : %.c
	$(OCAMLC) $(CC_OPT) -o $@ -c $<

clean::
	rm -f *.cmi *.cmo *.cma
	rm -f *.cmx *.cmxa *.o *.a dll*.so

###############################################################################

default:: cf.cma

opt:: cf.cmxa

CF_LEXYACC_MODULES =

CF_YACC_MODULES = $(CF_LEXYACC_MODULES:%=cf_yacc_%)
CF_LEX_MODULES = $(CF_LEXYACC_MODULES:%=cf_lex_%)

#clean::
#	rm -rf $(CF_LEX_ML_FILES)
#	rm -rf $(CF_YACC_ML_FILES)
#	rm -rf $(CF_YACC_MLI_FILES)

cf_lex_%.cmo : cf_yacc_%.cmi cf_lex_%.cmi
cf_lex_%.cmx : cf_yacc_%.cmi cf_lex_%.cmi

#manual dependencies

#cf_yacc_foo.cmi: cf_foo_bar.cmi
#cf_lex_foo.cmi: cf_foo_bar.cmi

CF_LEX_ML_FILES = $(CF_LEX_MODULES:%=%.ml)
CF_YACC_ML_FILES = $(CF_YACC_MODULES:%=%.ml)
CF_YACC_MLI_FILES = $(CF_YACC_MODULES:%=%.mli)

CF_ADDR_MODULES = ip4 ip6
CF_PROTO_MODULES = ip4 ip6

CF_MODULES = \
    ordered either exnopt smonad cmonad scmonad tai64 tai64n gregorian \
	stdtime journal seq deque flow heap pqueue map set sbheap rbtree \
	gadget state_gadget machine unicode parser message dfa regex lex \
	scan_parser socket netif nameinfo sock_common sock_dgram sock_stream \
	ip_common $(CF_ADDR_MODULES:%=%_addr) $(CF_PROTO_MODULES:%=%_proto) \
    tcp4_socket tcp6_socket udp4_socket udp6_socket poll uri

CF_PRIMITIVES = \
    common tai64 tai64n socket netif nameinfo sock_dgram sock_stream \
	ip_common $(CF_ADDR_MODULES:%=%_addr) $(CF_PROTO_MODULES:%=%_proto)

CF_ML_FILES = $(CF_MODULES:%=cf_%.ml)
CF_MLI_FILES = $(CF_MODULES:%=cf_%.mli)
CF_CMI_FILES = $(CF_MODULES:%=cf_%.cmi)
CF_CMO_FILES = $(CF_MODULES:%=cf_%.cmo)
CF_CMX_FILES = $(CF_MODULES:%=cf_%.cmx)
CF_O_FILES = $(CF_MODULES:%=cf_%.o)

CF_P_C_FILES = $(CF_PRIMITIVES:%=cf_%_p.c)
CF_P_H_FILES = $(CF_PRIMITIVES:%=cf_%_p.h)
CF_P_O_FILES = $(CF_PRIMITIVES:%=cf_%_p.o)

libcf.a dllcf.so : $(CF_P_O_FILES) # $(CF_CMI_FILES) $(CF_CMO_FILES)
	$(OCAMLMKLIB) -o cf $(CF_P_O_FILES)

cf.cma : libcf.a dllcf.so $(CF_CMI_FILES) $(CF_CMO_FILES)
	$(OCAMLMKLIB) -o cf $(CF_CMO_FILES) -lcf

cf.cmxa cf.a : libcf.a dllcf.so $(CF_CMI_FILES) $(CF_CMX_FILES) $(CF_O_FILES)
	$(OCAMLMKLIB) -o cf $(CF_CMX_FILES) -lcf

install:: libcf.a dllcf.so cf.cma
	{ test ! -f cf.cmxa || extra="cf.cmxa cf.a"; }; \
	ocamlfind install cf \
	  $(CF_MLI_FILES) $(CF_CMI_FILES) $(CF_P_H_FILES) \
          cf.cma libcf.a dllcf.so META $$extra

uninstall::
	ocamlfind remove cf

###############################################################################

TEST_MODULES = cf # setbench deq

TEST_PROGRAMS = $(TEST_MODULES:%=t.%)
TEST_OPT_PROGRAMS = $(TEST_MODULES:%=t-opt.%)

TEST_ML_FILES = $(TEST_MODULES:%=t/t_%.ml)

TEST_LINKOPT = -cclib -L. -linkpkg
TEST_LIBS = cf

default:: $(TEST_PROGRAMS)

opt:: $(TEST_OPT_PROGRAMS)

t.% : t/t_%.ml $(TEST_LIBS:%=%.cma)
	$(OCAMLC) -o $@ $(CMO_OPT) $(DEBUG_OPT) $(TEST_LINKOPT) \
        $(TEST_LIBS:%=%.cma) $<

t-opt.% : t/t_%.ml $(TEST_LIBS:%=%.cmxa)
	$(OCAMLOPT) -o $@ $(CMX_OPT) $(TEST_LINKOPT) $(TEST_LIBS:%=%.cmxa) $<

test:: $(TEST_PROGRAMS)
	@for i in $(TEST_PROGRAMS); do \
	    echo; \
	    echo $$i; \
	    CAML_LD_LIBRARY_PATH=. ./$$i; \
	done

test.opt:: $(TEST_OPT_PROGRAMS)
	@for i in $(TEST_OPT_PROGRAMS); do \
	    echo; \
	    echo $$i; \
	    CAML_LD_LIBRARY_PATH=. ./$$i; \
	done

clean::
	rm -f t/*.cmi t/*.cmo
	rm -f t/*.cmx t/*.o
	rm -f t.* t-opt.*

###############################################################################

default:: ocamltop

ocamltop: $(TEST_LIBS:%=%.cma)
	$(OCAMLMKTOP) -o $@ $(CMO_OPT) $(TEST_LINKOPT) $(TEST_LIBS:%=%.cma)

clean::
	rm -f ocamltop

###############################################################################

DOC_SOURCES = $(CF_MLI_FILES) $(CF_ML_FILES)

doc::
	@mkdir -p doc
	$(OCAMLDOC) -v -d doc -html -colorize-code -m A $(DOC_SOURCES)

###############################################################################

DEPEND_FILE=.depend

$(DEPEND_FILE) ::
	$(OCAMLC) -c -ccopt -MM $(CF_P_C_FILES) > .depend
	$(OCAMLDEP) $(CF_MLI_FILES) $(CF_ML_FILES) $(TEST_ML_FILES) >> .depend

depend:: $(DEPEND_FILE)

include $(DEPEND_FILE)

# End of file [ Makefile ]
