###########################################################################
#                              OCamlMakefile
#                  Copyright (C) 1999-2002  Markus Mottl
#
#                             For updates see:
#                http://www.oefai.at/~markus/ocaml_sources
#
#        $Id: OCamlMakefile,v 1.1 2003/09/25 13:54:01 raffalli Exp $
#
###########################################################################

# Set these variables to the names of the sources to be processed and
# the result variable. Order matters during linkage!

ifndef SOURCES
  SOURCES := foo.ml
endif
export SOURCES

ifndef RES_CLIB_SUF
  RES_CLIB_SUF := _stubs
endif
export RES_CLIB_SUF

ifndef RESULT
  RESULT := foo
endif
export RESULT

ifndef DOC_FILES
  DOC_FILES := $(filter %.mli, $(SOURCES))
endif
export DOC_FILES

export BCSUFFIX
export NCSUFFIX

ifndef TOPSUFFIX
  TOPSUFFIX := .top
endif

export TOPSUFFIX

# Eventually set include- and library-paths, libraries to link,
# additional compilation-, link- and ocamlyacc-flags
# Path- and library information needs not be written with "-I" and such...
# Define THREADS if you need it, otherwise leave it unset (same for
# USE_CAMLP4)!

export THREADS
export USE_CAMLP4

export INCDIRS
export LIBDIRS
export OCAML_DEFAULT_DIRS
export OCAML_LIB_INSTALL

export LIBS
export CLIBS

export OCAMLFLAGS
export OCAMLNCFLAGS
export OCAMLBCFLAGS

export OCAMLLDFLAGS
export OCAMLNLDFLAGS
export OCAMLBLDFLAGS

ifndef OCAMLCPFLAGS
  OCAMLCPFLAGS := a
endif

export OCAMLCPFLAGS

export YFLAGS
export IDLFLAGS

export OCAMLDOCFLAGS

export DVIPSFLAGS

export STATIC

# Add a list of optional trash files that should be deleted by "make clean"
export TRASH

####################  variables depending on your OCaml-installation

ifdef MINGW
  export MINGW
  WIN32   := 1
endif
ifdef MSVC
  export MSVC
  WIN32   := 1
  EXT_OBJ := obj
  EXT_LIB := lib
  ifeq ($(CC),gcc)
    # work around GNU Make default value
    CC := cl
  endif
  ifeq ($(CXX),g++)
    # work around GNU Make default value
    CXX := cl
  endif
  CFLAG_O := -Fo
endif
ifdef WIN32
  EXT_CXX := cpp
  EXE     := .exe
endif

ifndef EXT_OBJ
  EXT_OBJ := o
endif
ifndef EXT_LIB
  EXT_LIB := a
endif
ifndef EXT_CXX
  EXT_CXX := cc
endif
ifndef EXE
  EXE := # empty
endif
ifndef CFLAG_O
  CFLAG_O := -o # do not delete this comment (preserves trailing whitespace)!
endif

export CC
export CXX
export CFLAGS
export CXXFLAGS
export LDFLAGS

BCRESULT  := $(addsuffix $(BCSUFFIX), $(RESULT))
NCRESULT  := $(addsuffix $(NCSUFFIX), $(RESULT))
TOPRESULT := $(addsuffix $(TOPSUFFIX), $(RESULT))

ifndef OCAMLC
  OCAMLC := ocamlc
endif

export OCAMLC

ifndef OCAMLOPT
  OCAMLOPT := ocamlopt
endif

export OCAMLOPT

ifndef OCAMLMKTOP
  OCAMLMKTOP := ocamlmktop
endif

export OCAMLMKTOP

ifndef OCAMLCP
  OCAMLCP := ocamlcp
endif

export OCAMLCP

ifndef OCAMLDEP
  OCAMLDEP := ocamldep
endif

export OCAMLDEP

ifndef OCAMLLEX
  OCAMLLEX := ocamllex
endif

export OCAMLLEX

ifndef OCAMLYACC
  OCAMLYACC := ocamlyacc
endif

export OCAMLYACC

ifndef CAMLIDL
  CAMLIDL := camlidl
endif

export CAMLIDL

ifndef CAMLIDLDLL
  CAMLIDLDLL := camlidldll
endif

export CAMLIDLDLL

ifndef NOIDLHEADER
  MAYBE_IDL_HEADER := -header
endif

export NOIDLHEADER

ifndef CAMLP4
  CAMLP4 := camlp4
endif

export CAMLP4

ifndef OCAMLDOC
  OCAMLDOC := ocamldoc
endif

export OCAMLDOC

ifndef LATEX
  LATEX := latex
endif

export LATEX

ifndef DVIPS
  DVIPS := dvips
endif

export DVIPS

ifndef PS2PDF
  PS2PDF := ps2pdf
endif

export PS2PDF

ifndef OCAMLMAKEFILE
  OCAMLMAKEFILE := OCamlMakefile
endif

export OCAMLMAKEFILE

ifndef OCAMLLIBPATH
  OCAMLLIBPATH := \
    $(shell $(OCAMLC) 2>/dev/null -where || echo /usr/local/lib/ocaml)
endif

export OCAMLLIBPATH

ifndef OCAML_LIB_INSTALL
  OCAML_LIB_INSTALL := $(OCAMLLIBPATH)/contrib
endif

export OCAML_LIB_INSTALL

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

####################  change following sections only if
####################    you know what you are doing!

# for pedants using "--warn-undefined-variables"
export MAYBE_IDL
export REAL_RESULT
export CAMLIDLFLAGS
export THREAD_FLAG
export RES_CLIB
export MAKEDLL

SHELL := /bin/sh

MLDEPDIR := ._d
BCDIDIR  := ._bcdi
NCDIDIR  := ._ncdi

FILTERED     := $(filter %.mli %.ml %.mll %.mly %.idl %.c %.$(EXT_CXX), \
                         $(SOURCES))
SOURCE_DIRS  := $(filter-out ./, $(sort $(dir $(FILTERED))))

FILTERED_ML  := $(filter %.ml, $(FILTERED))
DEP_ML       := $(FILTERED_ML:%.ml=$(MLDEPDIR)/%.d)

FILTERED_MLI := $(filter %.mli, $(FILTERED))
DEP_MLI      := $(FILTERED_MLI:.mli=.di)

FILTERED_MLL := $(filter %.mll, $(FILTERED))
DEP_MLL      := $(FILTERED_MLL:%.mll=$(MLDEPDIR)/%.d)
AUTO_MLL     := $(FILTERED_MLL:.mll=.ml)

FILTERED_MLY := $(filter %.mly, $(FILTERED))
DEP_MLY      := $(FILTERED_MLY:%.mly=$(MLDEPDIR)/%.d) $(FILTERED_MLY:.mly=.di)
AUTO_MLY     := $(FILTERED_MLY:.mly=.mli) $(FILTERED_MLY:.mly=.ml)

FILTERED_IDL := $(filter %.idl, $(FILTERED))
DEP_IDL      := $(FILTERED_IDL:%.idl=$(MLDEPDIR)/%.d) $(FILTERED_IDL:.idl=.di)
C_IDL        := $(FILTERED_IDL:%.idl=%_stubs.c) $(FILTERED_IDL:.idl=.h)
OBJ_C_IDL    := $(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ))
AUTO_IDL     := $(FILTERED_IDL:.idl=.mli) $(FILTERED_IDL:.idl=.ml) $(C_IDL)

FILTERED_C_CXX := $(filter %.c %.$(EXT_CXX), $(FILTERED))
OBJ_C_CXX      := $(FILTERED_C_CXX:.c=.$(EXT_OBJ))
OBJ_C_CXX      := $(OBJ_C_CXX:.$(EXT_CXX)=.$(EXT_OBJ))

PRE_TARGETS  += $(AUTO_MLL) $(AUTO_MLY) $(AUTO_IDL)

ALL_DEPS     := $(DEP_ML) $(DEP_MLI) $(DEP_MLL) $(DEP_MLY) $(DEP_IDL)
MLDEPS       := $(filter %.d, $(ALL_DEPS))
MLIDEPS      := $(filter %.di, $(ALL_DEPS))
BCDEPIS      := $(MLIDEPS:%.di=$(BCDIDIR)/%.di)
NCDEPIS      := $(MLIDEPS:%.di=$(NCDIDIR)/%.di)

ALLML        := $(filter %.mli %.ml %.mll %.mly %.idl, $(FILTERED))

IMPLO_INTF   := $(ALLML:%.mli=%.mli.__)
IMPLO_INTF   := $(foreach file, $(IMPLO_INTF), \
                  $(basename $(file)).cmi $(basename $(file)).cmo)
IMPLO_INTF   := $(filter-out %.mli.cmo, $(IMPLO_INTF))
IMPLO_INTF   := $(IMPLO_INTF:%.mli.cmi=%.cmi)

IMPLX_INTF   := $(IMPLO_INTF:.cmo=.cmx)

INTF         := $(filter %.cmi, $(IMPLO_INTF))
IMPL_CMO     := $(filter %.cmo, $(IMPLO_INTF))
IMPL_CMX     := $(IMPL_CMO:.cmo=.cmx)

OBJ_LINK     := $(OBJ_C_IDL) $(OBJ_C_CXX)
OBJ_FILES    := $(IMPL_CMO:.cmo=.$(EXT_OBJ)) $(OBJ_LINK)

EXECS        := $(addsuffix $(EXE), \
                            $(sort $(TOPRESULT) $(BCRESULT) $(NCRESULT)))
ifdef WIN32
  EXECS      += $(BCRESULT).dll $(NCRESULT).dll
endif

CLIB_BASE    := $(RESULT)$(RES_CLIB_SUF)
ifneq ($(strip $(OBJ_LINK)),)
  RES_CLIB     := lib$(CLIB_BASE).$(EXT_LIB)
endif
DLLSONAME    := dll$(CLIB_BASE).so
NONEXECS     := $(INTF) $(IMPL_CMO) $(IMPL_CMX) $(OBJ_FILES) $(PRE_TARGETS) \
                $(BCRESULT).cma $(NCRESULT).cmxa $(NCRESULT).$(EXT_LIB) \
		$(RES_CLIB) $(DLLSONAME)

ifndef LIBINSTALL_FILES
  LIBINSTALL_FILES := $(RESULT).mli $(RESULT).cmi $(RESULT).cma \
		      $(RESULT).cmxa $(RESULT).a $(RES_CLIB) $(DLLSONAME)
endif
export LIBINSTALL_FILES

ifdef WIN32
  # some extra stuff is created while linking DLLs
  NONEXECS   += $(BCRESULT).$(EXT_LIB) $(BCRESULT).exp $(NCRESULT).exp
endif

TARGETS      := $(EXECS) $(NONEXECS)

# If there are IDL-files
ifneq ($(strip $(FILTERED_IDL)),)
  MAYBE_IDL := -cclib -lcamlidl
endif

ifdef USE_CAMLP4
  CAMLP4PATH := \
    $(shell $(CAMLP4) -where 2>/dev/null || echo /usr/local/lib/camlp4)
  INCFLAGS := -I $(CAMLP4PATH)
  CINCFLAGS := -I$(CAMLP4PATH)
endif

INCFLAGS += $(SOURCE_DIRS:%=-I %) $(INCDIRS:%=-I %) $(OCAML_DEFAULT_DIRS:%=-I %)
CINCFLAGS += $(SOURCE_DIRS:%=-I%) $(INCDIRS:%=-I%) $(OCAML_DEFAULT_DIRS:%=-I%)
CLIBFLAGS += $(SOURCE_DIRS:%=-L%) $(LIBDIRS:%=-L%) $(OCAML_DEFAULT_DIRS:%=-L%)

ifndef PROFILING
  INTF_OCAMLC := $(OCAMLC)
else
  ifndef THREADS
    INTF_OCAMLC := $(OCAMLCP) -p $(OCAMLCPFLAGS)
  else
    # OCaml does not support profiling byte code
    # with threads (yet), therefore we force an error.
    ifndef REAL_OCAMLC
      $(error Profiling of multithreaded byte code not yet supported by OCaml)
    endif
  endif
endif

ifndef MSVC
  COMMON_LDFLAGS := $(LDFLAGS:%=-ccopt %) $(SOURCE_DIRS:%=-ccopt -L%) \
                    $(LIBDIRS:%=-ccopt -L%) $(OCAML_DEFAULT_DIRS:%=-ccopt -L%)
else
  # currenly MSVC-build ocamlc/ocamlopt cannot pass any option to C linker :-(
  COMMON_LDFLAGS :=
endif

ifndef MSVC
  CLIBS_OPTS := $(CLIBS:%=-cclib -l%)
else
  # MSVC libraries do not have 'lib' prefix
  CLIBS_OPTS := $(CLIBS:%=-ccopt %)
endif
ifneq ($(strip $(OBJ_LINK)),)
  ifdef CREATE_LIB
    OBJS_LIBS := -cclib -l$(CLIB_BASE) $(CLIBS_OPTS) $(MAYBE_IDL)
  else
    OBJS_LIBS := $(OBJ_LINK) $(CLIBS_OPTS) $(MAYBE_IDL)
  endif
else
  OBJS_LIBS := $(CLIBS_OPTS) $(MAYBE_IDL)
endif

# If we have to make byte-code
ifndef REAL_OCAMLC
  SPECIAL_OCAMLFLAGS := $(OCAMLBCFLAGS)

  REAL_OCAMLC := $(INTF_OCAMLC)

  REAL_IMPL := $(IMPL_CMO)
  REAL_IMPL_INTF := $(IMPLO_INTF)
  IMPL_SUF := .cmo

  DEPFLAGS  :=
  MAKE_DEPS := $(MLDEPS) $(BCDEPIS)

  ifdef CREATE_LIB
    ifndef STATIC
      ifneq ($(strip $(OBJ_LINK)),)
	MAKEDLL := $(DLLSONAME)
	ALL_LDFLAGS := -dllib $(DLLSONAME)
      endif
    endif
  endif

  ifneq "$(strip $(OBJ_LINK) $(THREADS) $(MAYBE_IDL) $(CLIBS))" ""
    ALL_LDFLAGS += -custom
  endif

  ALL_LDFLAGS += $(INCFLAGS) $(OCAMLLDFLAGS) $(OCAMLBLDFLAGS) \
                 $(COMMON_LDFLAGS) $(LIBS:%=%.cma)
  CAMLIDLDLLFLAGS :=

  ifdef THREADS
    ALL_LDFLAGS += -thread unix.cma threads.cma
    THREAD_FLAG := -thread
  endif

# we have to make native-code
else
  ifndef PROFILING
    SPECIAL_OCAMLFLAGS := $(OCAMLNCFLAGS)
    PLDFLAGS :=
  else
    SPECIAL_OCAMLFLAGS := -p $(OCAMLNCFLAGS)
    PLDFLAGS := -p
  endif

  REAL_IMPL := $(IMPL_CMX)
  REAL_IMPL_INTF := $(IMPLX_INTF)
  IMPL_SUF := .cmx

  CFLAGS := -DNATIVE_CODE $(CFLAGS)

  DEPFLAGS  := -native
  MAKE_DEPS := $(MLDEPS) $(NCDEPIS)

  ALL_LDFLAGS := $(PLDFLAGS) $(INCFLAGS) $(OCAMLLDFLAGS) \
                 $(OCAMLNLDFLAGS) $(COMMON_LDFLAGS)
  CAMLIDLDLLFLAGS := -opt

  ifndef CREATE_LIB
    ALL_LDFLAGS += $(LIBS:%=%.cmxa)
  endif

  ifdef THREADS
    ALL_LDFLAGS := -thread $(ALL_LDFLAGS)
    ifndef CREATE_LIB
      ALL_LDFLAGS += unix.cmxa threads.cmxa
    endif
    THREAD_FLAG := -thread
  endif
endif

ALL_OCAMLCFLAGS := $(THREAD_FLAG) $(OCAMLFLAGS) \
                   $(INCFLAGS) $(SPECIAL_OCAMLFLAGS)

ifdef make_deps
  -include $(MAKE_DEPS)
  PRE_TARGETS :=
endif

###########################################################################
# USER RULES

# generates byte-code (default)
byte-code:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \
				REAL_RESULT="$(BCRESULT)" make_deps=yes
bc:	byte-code

byte-code-nolink:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \
				REAL_RESULT="$(BCRESULT)" make_deps=yes
bcnl:	byte-code-nolink

top:			$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(TOPRESULT) \
				REAL_RESULT="$(BCRESULT)" make_deps=yes

# generates native-code

native-code:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(NCRESULT) \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				make_deps=yes
nc:	native-code

native-code-nolink:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				make_deps=yes
ncnl:	native-code-nolink

# generates byte-code libraries
byte-code-library:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(BCRESULT).cma \
				REAL_RESULT="$(BCRESULT)" \
				CREATE_LIB=yes \
				make_deps=yes
bcl:	byte-code-library

# generates native-code libraries
native-code-library:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(NCRESULT).cmxa \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				CREATE_LIB=yes \
				make_deps=yes
ncl:	native-code-library

ifdef WIN32
# generates byte-code dll
byte-code-dll:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(BCRESULT).dll \
				REAL_RESULT="$(BCRESULT)" \
				make_deps=yes
bcd:	byte-code-dll

# generates native-code dll
native-code-dll:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(NCRESULT).dll \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				make_deps=yes
ncd:	native-code-dll
endif

# generates byte-code with debugging information
debug-code:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \
				REAL_RESULT="$(BCRESULT)" make_deps=yes \
				OCAMLFLAGS="-g $(OCAMLFLAGS)" \
				OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)"
dc:	debug-code

# generates byte-code libraries with debugging information
debug-code-library:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(BCRESULT).cma \
				REAL_RESULT="$(BCRESULT)" make_deps=yes \
				CREATE_LIB=yes \
				OCAMLFLAGS="-g $(OCAMLFLAGS)" \
				OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)"
dcl:	debug-code-library

# generates byte-code for profiling
profiling-byte-code:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \
				REAL_RESULT="$(BCRESULT)" PROFILING="y" \
				make_deps=yes
pbc:	profiling-byte-code

# generates native-code

profiling-native-code:		$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) $(NCRESULT) \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				PROFILING="y" \
				make_deps=yes
pnc:	profiling-native-code

# generates byte-code libraries
profiling-byte-code-library:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(BCRESULT).cma \
				REAL_RESULT="$(BCRESULT)" PROFILING="y" \
				CREATE_LIB=yes \
				make_deps=yes
pbcl:	profiling-byte-code-library

# generates native-code libraries
profiling-native-code-library:	$(PRE_TARGETS)
			@$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(RES_CLIB) $(NCRESULT).cmxa \
				REAL_RESULT="$(NCRESULT)" PROFILING="y" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				CREATE_LIB=yes \
				make_deps=yes
pncl:	profiling-native-code-library

# generates HTML-documentation
htdoc:	doc/html

# generates Latex-documentation
ladoc:	doc/latex

# generates PostScript-documentation
psdoc:	doc/latex/doc.ps

# generates PDF-documentation
pdfdoc:	doc/latex/doc.pdf

# generates all supported forms of documentation
doc: htdoc ladoc psdoc pdfdoc

###########################################################################
# LOW LEVEL RULES

$(REAL_RESULT):		$(REAL_IMPL_INTF) $(OBJ_LINK)
			$(REAL_OCAMLC) $(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \
				$(REAL_IMPL)
ifdef MSVC
# work around the bug in ocamlc -- it should delete this file itself
			rm -f camlprim?.$(EXT_OBJ)
endif

nolink:			$(REAL_IMPL_INTF) $(OBJ_LINK)

ifdef WIN32
$(REAL_RESULT).dll:	$(REAL_IMPL_INTF) $(OBJ_LINK)
			$(CAMLIDLDLL) $(CAMLIDLDLLFLAGS) $(OBJ_LINK) $(CLIBS) \
				-o $@ $(REAL_IMPL)
endif

%$(TOPSUFFIX):		$(REAL_IMPL_INTF) $(OBJ_LINK)
			$(OCAMLMKTOP) $(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \
				$(REAL_IMPL)
ifdef MSVC
# work around the bug in ocamltop -- it should delete this file itself
			rm -f camlprim?.$(EXT_OBJ)
endif

.SUFFIXES:		.mli .ml .cmi .cmo .cmx .cma .cmxa .$(EXT_OBJ) \
                        .mly .di .d .$(EXT_LIB) .idl .c .$(EXT_CXX) .h .so

$(DLLSONAME):		$(OBJ_LINK)
			$(CC) -shared $(CINCFLAGS) $(CLIBFLAGS) \
				-o $@ $(OBJ_LINK) $(CLIBS:%=-l%)

$(RESULT).cma:		$(REAL_IMPL_INTF) $(MAKEDLL)
			$(REAL_OCAMLC) -a $(ALL_LDFLAGS) \
				$(OBJS_LIBS) -o $@ $(OCAMLBLDFLAGS) $(REAL_IMPL)

$(RESULT).cmxa $(RESULT).$(EXT_LIB):	$(REAL_IMPL_INTF)
			$(OCAMLOPT) -a $(ALL_LDFLAGS) $(OBJS_LIBS) \
				$(OCAMLNLDFLAGS) -o $@ $(REAL_IMPL)

$(RES_CLIB): 		$(OBJ_LINK)
ifndef MSVC
  ifneq ($(strip $(OBJ_LINK)),)
		      ar rc $@ $(OBJ_LINK)
		      ranlib $@
  endif
else
  ifneq ($(strip $(OBJ_LINK)),)
			lib /nologo /debugtype:cv /out:$(RES_CLIB) $(OBJ_LINK)
  endif
endif

.mli.cmi:
			@pp=`sed -n -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
			if [ -z "$$pp" ]; then \
			  echo $(INTF_OCAMLC) -c $(THREAD_FLAG) \
			    $(OCAMLFLAGS) $(INCFLAGS) $<; \
			  $(INTF_OCAMLC) -c $(THREAD_FLAG) $(OCAMLFLAGS) \
			    $(INCFLAGS) $<; \
			else \
			    echo $(INTF_OCAMLC) -c -pp \"$$pp\" $(THREAD_FLAG) \
			      $(OCAMLFLAGS) $(INCFLAGS) $<; \
			    $(INTF_OCAMLC) -c -pp "$$pp" $(THREAD_FLAG) \
				 $(OCAMLFLAGS) $(INCFLAGS) $<; \
			fi

.ml.cmi .ml.$(EXT_OBJ) .ml.cmx .ml.cmo:
			@pp=`sed -n -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
			if [ -z "$$pp" ]; then \
			  echo $(REAL_OCAMLC) -c $(ALL_OCAMLCFLAGS) $<; \
			  $(REAL_OCAMLC) -c $(ALL_OCAMLCFLAGS) $<; \
			else \
			  echo $(REAL_OCAMLC) -c -pp \"$$pp\" \
			    $(ALL_OCAMLCFLAGS) $<; \
			  $(REAL_OCAMLC) -c -pp "$$pp" $(ALL_OCAMLCFLAGS) $<; \
			fi

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

.PRECIOUS:		%.ml %.mli
%.ml %.mli:		%.mly
			$(OCAMLYACC) $(YFLAGS) $<

.PRECIOUS:		%.ml %.mli %_stubs.c %.h
%.ml %.mli %_stubs.c %.h:		%.idl
			$(CAMLIDL) $(MAYBE_IDL_HEADER) $(IDLFLAGS) \
				$(CAMLIDLFLAGS) $<
			@if [ $(NOIDLHEADER) ]; then touch $*.h; fi

.c.$(EXT_OBJ):
			$(CC) -c $(CFLAGS) $(CINCFLAGS) -I$(OCAMLLIBPATH) \
				$< $(CFLAG_O)$@

.$(EXT_CXX).$(EXT_OBJ):
			$(CXX) -c $(CXXFLAGS) $(CINCFLAGS) -I$(OCAMLLIBPATH) \
				$< $(CFLAG_O)$@

$(MLDEPDIR)/%.d:	%.ml
			@echo making $@ from $<
			@if [ ! -d $(@D) ]; then mkdir -p $(@D); fi
			@pp=`sed -n -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
			if [ -z "$$pp" ]; then \
			  $(OCAMLDEP) $(INCFLAGS) $< > $@; \
			else \
			  $(OCAMLDEP) -pp "$$pp" $(INCFLAGS) $< > $@; \
			fi

$(BCDIDIR)/%.di $(NCDIDIR)/%.di:	%.mli
			@echo making $@ from $<
			@if [ ! -d $(@D) ]; then mkdir -p $(@D); fi
			@pp=`sed -n -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
			if [ -z "$$pp" ]; then \
			  $(OCAMLDEP) $(DEPFLAGS) $(INCFLAGS) $< > $@; \
			else \
			  $(OCAMLDEP) $(DEPFLAGS) \
			    -pp "$$pp" $(INCFLAGS) $< > $@; \
			fi

doc/html: $(DOC_FILES)
	rm -rf $@
	mkdir -p $@
	$(OCAMLDOC) -html -d $@ $(OCAMLDOCFLAGS) $(DOC_FILES)

doc/latex: $(DOC_FILES)
	rm -rf $@
	mkdir -p $@
	$(OCAMLDOC) -latex -d $@ $(OCAMLDOCFLAGS) $(DOC_FILES) -o doc.tex

doc/latex/doc.ps: doc/latex
	cd doc/latex && \
	  $(LATEX) doc.tex && \
	  $(LATEX) doc.tex && \
	  $(DVIPS) $(DVIPSFLAGS) doc.dvi -o $(@F)

doc/latex/doc.pdf: doc/latex/doc.ps
	cd doc/latex && $(PS2PDF) $(<F)

###########################################################################
# (UN)INSTALL RULES FOR LIBRARIES

.PHONY: libinstall
libinstall:	all
	@printf "\nInstalling library to: $(OCAML_LIB_INSTALL)\n"
	-install -d $(OCAML_LIB_INSTALL)
	for i in $(LIBINSTALL_FILES); do \
	  if [ -f $$i ]; then \
	    install -c -m 0644 $$i $(OCAML_LIB_INSTALL); \
	  fi; \
	done
	@printf "\nInstallation successful.\n"

.PHONY: libuninstall
libuninstall:
	@printf "\nUninstalling library from: $(OCAML_LIB_INSTALL)\n"
	cd $(OCAML_LIB_INSTALL); rm $(notdir $(LIBINSTALL_FILES))
	@printf "\nUninstallation successful.\n"

###########################################################################
# MAINTAINANCE RULES

.PHONY:	clean
clean:
	rm -f $(TARGETS) $(TRASH)
	rm -rf $(BCDIDIR) $(NCDIDIR) $(MLDEPDIR)

.PHONY:	cleanup
cleanup:
	rm -f $(NONEXECS) $(TRASH)
	rm -rf $(BCDIDIR) $(NCDIDIR) $(MLDEPDIR)

.PHONY: clean-doc
clean-doc:
	rm -rf doc

.PHONY: nobackup
nobackup:
	rm -f *.bak *~ *.dup
