###########################################################################
#                              OCamlMakefile
#                  Copyright (C) 1999-2004  Markus Mottl
#
#                             For updates see:
#                http://www.oefai.at/~markus/ocaml_sources
#
#        $Id$
#
###########################################################################

# Modified by damien for .glade.ml compilation

# 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

export LIB_PACK_NAME

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 VMTHREADS
export ANNOTATE
export USE_CAMLP4

export INCDIRS
export LIBDIRS
export EXTLIBDIRS
export RESULTDEPS
export OCAML_DEFAULT_DIRS

export LIBS
export CLIBS

export OCAMLFLAGS
export OCAMLNCFLAGS
export OCAMLBCFLAGS

export OCAMLLDFLAGS
export OCAMLNLDFLAGS
export OCAMLBLDFLAGS

ifndef OCAMLCPFLAGS
  OCAMLCPFLAGS := a
endif

export OCAMLCPFLAGS

export PPFLAGS

export YFLAGS
export IDLFLAGS

export OCAMLDOCFLAGS

export OCAMLFIND_INSTFLAGS

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
  CFLAGS_WIN32 := -mno-cygwin
endif
ifdef MSVC
  export MSVC
  WIN32   := 1
  ifndef STATIC
    CPPFLAGS_WIN32 := -DCAML_DLL
  endif
  CFLAGS_WIN32 += -nologo
  EXT_OBJ := obj
  EXT_LIB := lib
  ifeq ($(CC),gcc)
    # work around GNU Make default value
    ifdef THREADS
      CC := cl -MT
    else
      CC := cl
    endif
  endif
  ifeq ($(CXX),g++)
    # work around GNU Make default value
    CXX := $(CC)
  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
export CPPFLAGS

ifndef RPATH_FLAG
  RPATH_FLAG := -R
endif
export RPATH_FLAG

ifndef MSVC
ifndef PIC_CFLAGS
  PIC_CFLAGS := -fPIC
endif
ifndef PIC_CPPFLAGS
  PIC_CPPFLAGS := -DPIC
endif
endif

export PIC_CFLAGS
export PIC_CPPFLAGS

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

ifndef OCAMLFIND
  OCAMLFIND := ocamlfind
endif
export OCAMLFIND

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 OCAMLMKLIB
  OCAMLMKLIB := ocamlmklib
endif
export OCAMLMKLIB

ifndef OCAML_GLADECC
  OCAML_GLADECC := lablgladecc2
endif
export OCAML_GLADECC

ifndef OCAML_GLADECC_FLAGS
  OCAML_GLADECC_FLAGS :=
endif
export OCAML_GLADECC_FLAGS

ifndef CAMELEON_REPORT
  CAMELEON_REPORT := report
endif
export CAMELEON_REPORT

ifndef CAMELEON_REPORT_FLAGS
  CAMELEON_REPORT_FLAGS :=
endif
export CAMELEON_REPORT_FLAGS

ifndef CAMELEON_ZOGGY
  CAMELEON_ZOGGY := camlp4o pa_zog.cma pr_o.cmo
endif
export CAMELEON_ZOGGY

ifndef CAMELEON_ZOGGY_FLAGS
  CAMELEON_ZOGGY_FLAGS :=
endif
export CAMELEON_ZOGGY_FLAGS

ifndef OXRIDL
  OXRIDL := oxridl
endif
export OXRIDL

ifndef CAMLIDL
  CAMLIDL := camlidl
endif
export CAMLIDL

ifndef CAMLIDLDLL
  CAMLIDLDLL := camlidldll
endif
export CAMLIDLDLL

ifndef NOIDLHEADER
  MAYBE_IDL_HEADER := -header
endif
export NOIDLHEADER

export NO_CUSTOM

ifndef CAMLP4
  CAMLP4 := camlp4
endif
export CAMLP4

ifndef REAL_OCAMLFIND
  ifdef PACKS
    ifndef CREATE_LIB
      ifdef THREADS
	PACKS += threads
      endif
    endif
    empty :=
    space := $(empty) $(empty)
    comma := ,
    ifdef PREDS
      PRE_OCAML_FIND_PREDICATES := $(subst $(space),$(comma),$(PREDS))
      PRE_OCAML_FIND_PACKAGES := $(subst $(space),$(comma),$(PACKS))
      OCAML_FIND_PREDICATES := -predicates $(PRE_OCAML_FIND_PREDICATES)
  #    OCAML_DEP_PREDICATES := -syntax $(PRE_OCAML_FIND_PREDICATES)
      OCAML_FIND_PACKAGES := $(OCAML_FIND_PREDICATES) -package $(PRE_OCAML_FIND_PACKAGES)
      OCAML_DEP_PACKAGES := $(OCAML_DEP_PREDICATES) -package $(PRE_OCAML_FIND_PACKAGES)
    else
      OCAML_FIND_PACKAGES := -package $(subst $(space),$(comma),$(PACKS))
      OCAML_DEP_PACKAGES :=
    endif
    OCAML_FIND_LINKPKG := -linkpkg
    REAL_OCAMLFIND := $(OCAMLFIND)
  endif
endif

export OCAML_FIND_PACKAGES
export OCAML_DEP_PACKAGES
export OCAML_FIND_LINKPKG
export REAL_OCAMLFIND

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/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!

# delete target files when a build command fails
.PHONY: .DELETE_ON_ERROR
.DELETE_ON_ERROR:

# for pedants using "--warn-undefined-variables"
export MAYBE_IDL
export REAL_RESULT
export CAMLIDLFLAGS
export THREAD_FLAG
export RES_CLIB
export MAKEDLL
export ANNOT_FLAG
export C_OXRIDL
export SUBPROJS
export CFLAGS_WIN32
export CPPFLAGS_WIN32

INCFLAGS :=

SHELL := /bin/sh

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

FILTER_EXTNS := %.mli %.ml %.mll %.mly %.idl %.oxridl %.c %.$(EXT_CXX) %.rep %.zog %.glade

FILTERED     := $(filter $(FILTER_EXTNS), $(SOURCES))
SOURCE_DIRS  := $(filter-out ./, $(sort $(dir $(FILTERED))))

FILTERED_REP := $(filter %.rep, $(FILTERED))
DEP_REP      := $(FILTERED_REP:%.rep=$(MLDEPDIR)/%.d)
AUTO_REP     := $(FILTERED_REP:.rep=.ml)

FILTERED_ZOG := $(filter %.zog, $(FILTERED))
DEP_ZOG      := $(FILTERED_ZOG:%.zog=$(MLDEPDIR)/%.d)
AUTO_ZOG     := $(FILTERED_ZOG:.zog=.ml)

FILTERED_GLADE := $(filter %.glade, $(FILTERED))
DEP_GLADE      := $(FILTERED_GLADE:%.glade=$(MLDEPDIR)/%.d)
AUTO_GLADE     := $(FILTERED_GLADE:.glade=.ml)

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)
ifndef NOIDLHEADER
 C_IDL += $(FILTERED_IDL:.idl=.h)
endif
OBJ_C_IDL    := $(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ))
AUTO_IDL     := $(FILTERED_IDL:.idl=.mli) $(FILTERED_IDL:.idl=.ml) $(C_IDL)

FILTERED_OXRIDL := $(filter %.oxridl, $(FILTERED))
DEP_OXRIDL      := $(FILTERED_OXRIDL:%.oxridl=$(MLDEPDIR)/%.d) $(FILTERED_OXRIDL:.oxridl=.di)
AUTO_OXRIDL     := $(FILTERED_OXRIDL:.oxridl=.mli) $(FILTERED_OXRIDL:.oxridl=.ml) $(C_OXRIDL)

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) $(AUTO_OXRIDL) $(AUTO_ZOG) $(AUTO_REP) $(AUTO_GLADE)

ALL_DEPS     := $(DEP_ML) $(DEP_MLI) $(DEP_MLL) $(DEP_MLY) $(DEP_IDL) $(DEP_OXRIDL) $(DEP_ZOG) $(DEP_REP) $(DEP_GLADE)

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 %.oxridl %.rep %.zog %.glade, $(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)
IMPL_ASM     := $(IMPL_CMO:.cmo=.asm)
IMPL_S       := $(IMPL_CMO:.cmo=.s)

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

ifdef WIN32
DLLSONAME := $(CLIB_BASE).dll
else
DLLSONAME := dll$(CLIB_BASE).so
endif

NONEXECS     := $(INTF) $(IMPL_CMO) $(IMPL_CMX) $(IMPL_ASM) $(IMPL_S) \
		$(OBJ_FILES) $(PRE_TARGETS) $(BCRESULT).cma $(NCRESULT).cmxa \
		$(NCRESULT).$(EXT_LIB) $(BCRESULT).cmi $(BCRESULT).cmo \
		$(NCRESULT).cmi $(NCRESULT).cmx $(NCRESULT).o \
		$(RES_CLIB) $(IMPL_CMO:.cmo=.annot) \
		$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo $(LIB_PACK_NAME).cmx $(LIB_PACK_NAME).o

ifndef STATIC
  NONEXECS += $(DLLSONAME)
endif

ifndef LIBINSTALL_FILES
  LIBINSTALL_FILES := $(RESULT).mli $(RESULT).cmi $(RESULT).cma \
		      $(RESULT).cmxa $(RESULT).$(EXT_LIB) $(RES_CLIB)
  ifndef STATIC
    ifneq ($(strip $(OBJ_LINK)),)
      LIBINSTALL_FILES += $(DLLSONAME)
    endif
  endif
endif

export LIBINSTALL_FILES

ifdef WIN32
  # some extra stuff is created while linking DLLs
  NONEXECS   += $(BCRESULT).$(EXT_LIB) $(BCRESULT).exp $(NCRESULT).exp $(CLIB_BASE).exp $(CLIB_BASE).lib
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/lib/camlp4)
  INCFLAGS := -I $(CAMLP4PATH)
  CINCFLAGS := -I$(CAMLP4PATH)
endif

DINCFLAGS := $(INCFLAGS) $(SOURCE_DIRS:%=-I %) $(OCAML_DEFAULT_DIRS:%=-I %)
INCFLAGS := $(DINCFLAGS) $(INCDIRS:%=-I %)
CINCFLAGS += $(SOURCE_DIRS:%=-I%) $(INCDIRS:%=-I%) $(OCAML_DEFAULT_DIRS:%=-I%)

ifndef MSVC
CLIBFLAGS += $(SOURCE_DIRS:%=-L%) $(LIBDIRS:%=-L%) \
             $(EXTLIBDIRS:%=-L%) $(EXTLIBDIRS:%=-Wl,$(RPATH_FLAG)%) \
             $(OCAML_DEFAULT_DIRS:%=-L%)
endif

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
    INTF_OCAMLC := $(OCAMLC)
  endif
endif

ifndef MSVC
COMMON_LDFLAGS := $(LDFLAGS:%=-ccopt %) $(SOURCE_DIRS:%=-ccopt -L%) \
		  $(LIBDIRS:%=-ccopt -L%) $(EXTLIBDIRS:%=-ccopt -L%) \
		  $(EXTLIBDIRS:%=-ccopt -Wl,$(RPATH_FLAG)%) \
		  $(OCAML_DEFAULT_DIRS:%=-ccopt -L%)
else
COMMON_LDFLAGS := -ccopt "/link -NODEFAULTLIB:LIBC $(LDFLAGS:%=%) $(SOURCE_DIRS:%=-LIBPATH:%) \
		  $(LIBDIRS:%=-LIBPATH:%) $(EXTLIBDIRS:%=-LIBPATH:%) \
		  $(OCAML_DEFAULT_DIRS:%=-LIBPATH:%) "
endif

CLIBS_OPTS := $(CLIBS:%=-cclib -l%)
ifdef MSVC
  ifndef STATIC
  # MSVC libraries do not have 'lib' prefix
  CLIBS_OPTS := $(CLIBS:%=-cclib %.lib)
  endif
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
  BYTE_OCAML := y

  # EXTRADEPS is added dependencies we have to insert for all
  # executable files we generate.  Ideally it should be all of the
  # libraries we use, but it's hard to find the ones that get searched on
  # the path since I don't know the paths built into the compiler, so
  # just include the ones with slashes in their names.
  EXTRADEPS := $(addsuffix .cma,$(foreach i,$(LIBS),$(if $(findstring /,$(i)),$(i))))
  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
    CFLAGS := $(PIC_CFLAGS) $(CFLAGS)
    CPPFLAGS := $(PIC_CPPFLAGS) $(CPPFLAGS)
    ifndef STATIC
      ifneq ($(strip $(OBJ_LINK)),)
	MAKEDLL := $(DLLSONAME)
	ALL_LDFLAGS := -dllib $(DLLSONAME)
      endif
    endif
  endif

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

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

  ifdef THREADS
    ifdef VMTHREADS
      THREAD_FLAG := -vmthread
    else
      THREAD_FLAG := -thread
    endif
    ALL_LDFLAGS := $(THREAD_FLAG) $(ALL_LDFLAGS)
    ifndef CREATE_LIB
      ifndef REAL_OCAMLFIND
        ALL_LDFLAGS := unix.cma threads.cma $(ALL_LDFLAGS)
      endif
    endif
  endif

# we have to make native-code
else
  EXTRADEPS := $(addsuffix .cmxa,$(foreach i,$(LIBS),$(if $(findstring /,$(i)),$(i))))
  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

  CPPFLAGS := -DNATIVE_CODE $(CPPFLAGS)

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

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

  ifndef CREATE_LIB
    ALL_LDFLAGS += $(LIBS:%=%.cmxa)
  else
    CFLAGS := $(PIC_CFLAGS) $(CFLAGS)
    CPPFLAGS := $(PIC_CPPFLAGS) $(CPPFLAGS)
  endif

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

export MAKE_DEPS

ifdef ANNOTATE
  ANNOT_FLAG := -dtypes
else
endif

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

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

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

# Call "OCamlMakefile QUIET=" to get rid of all of the @'s.
QUIET=@

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

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

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

# generates native-code

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

native-code-nolink:	$(PRE_TARGETS)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT) \
				REAL_RESULT="$(BCRESULT)" make_deps=yes \
				OCAMLFLAGS="-g $(OCAMLFLAGS)" \
				OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)"
dc:	debug-code

debug-code-nolink:	$(PRE_TARGETS)
			$(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) nolink \
				REAL_RESULT="$(BCRESULT)" make_deps=yes \
				OCAMLFLAGS="-g $(OCAMLFLAGS)" \
				OCAMLLDFLAGS="-g $(OCAMLLDFLAGS)"
dcnl:	debug-code-nolink

# generates byte-code libraries with debugging information
debug-code-library:	$(PRE_TARGETS)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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)
			$(QUIET)$(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

# packs byte-code objects
pack-byte-code:			$(PRE_TARGETS)
			$(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) $(BCRESULT).cmo \
				REAL_RESULT="$(BCRESULT)" \
				PACK_LIB=yes make_deps=yes
pabc:	pack-byte-code

# packs native-code objects
pack-native-code:		$(PRE_TARGETS)
			$(QUIET)$(MAKE) -r -f $(OCAMLMAKEFILE) \
				$(NCRESULT).cmx $(NCRESULT).o \
				REAL_RESULT="$(NCRESULT)" \
				REAL_OCAMLC="$(OCAMLOPT)" \
				PACK_LIB=yes make_deps=yes
panc:	pack-native-code

# generates HTML-documentation
htdoc:	doc/$(RESULT)/html

# generates Latex-documentation
ladoc:	doc/$(RESULT)/latex

# generates PostScript-documentation
psdoc:	doc/$(RESULT)/latex/doc.ps

# generates PDF-documentation
pdfdoc:	doc/$(RESULT)/latex/doc.pdf

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

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

$(REAL_RESULT):		$(REAL_IMPL_INTF) $(OBJ_LINK) $(EXTRADEPS) $(RESULTDEPS)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) \
				$(OCAML_FIND_PACKAGES) $(OCAML_FIND_LINKPKG) \
				$(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \
				$(REAL_IMPL)

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) $(EXTRADEPS)
			$(REAL_OCAMLFIND) $(OCAMLMKTOP) \
				$(OCAML_FIND_PACKAGES) $(OCAML_FIND_LINKPKG) \
				$(ALL_LDFLAGS) $(OBJS_LIBS) -o $@$(EXE) \
				$(REAL_IMPL)

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

ifndef STATIC
ifdef MINGW
$(DLLSONAME):		$(OBJ_LINK)
			$(CC) $(CFLAGS) $(CFLAGS_WIN32) $(OBJ_LINK) -shared -o $@ \
			-Wl,--whole-archive $(wildcard $(foreach dir,$(LIBDIRS),$(CLIBS:%=$(dir)/lib%.a))) \
			 $(OCAMLLIBPATH)/ocamlrun.a \
			-Wl,--export-all-symbols \
			-Wl,--no-whole-archive
else
ifdef MSVC
$(DLLSONAME):		$(OBJ_LINK)
			link /NOLOGO /DLL /OUT:$@ $(OBJ_LINK) \
			 $(wildcard $(foreach dir,$(LIBDIRS),$(CLIBS:%=$(dir)/%.lib))) \
			 $(OCAMLLIBPATH)/ocamlrun.lib

else
$(DLLSONAME):		$(OBJ_LINK)
			$(OCAMLMKLIB) $(INCFLAGS) $(CLIBFLAGS) \
				-o $(CLIB_BASE) $(OBJ_LINK) $(CLIBS:%=-l%) \
				$(OCAMLMKLIB_FLAGS)
endif
endif
endif

ifndef LIB_PACK_NAME
$(RESULT).cma:		$(REAL_IMPL_INTF) $(MAKEDLL) $(EXTRADEPS) $(RESULTDEPS)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) -a $(ALL_LDFLAGS) \
				$(OBJS_LIBS) -o $@ $(OCAMLBLDFLAGS) $(REAL_IMPL)

$(RESULT).cmxa $(RESULT).$(EXT_LIB):	$(REAL_IMPL_INTF) $(EXTRADEPS) $(RESULTDEPS)
			$(REAL_OCAMLFIND) $(OCAMLOPT) -a $(ALL_LDFLAGS) $(OBJS_LIBS) \
				$(OCAMLNLDFLAGS) -o $@ $(REAL_IMPL)
else
ifdef BYTE_OCAML
$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo: $(REAL_IMPL_INTF)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack -o $(LIB_PACK_NAME).cmo $(REAL_IMPL)
else
$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmx: $(REAL_IMPL_INTF)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack -o $(LIB_PACK_NAME).cmx $(REAL_IMPL)
endif

$(RESULT).cma:		$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmo $(MAKEDLL) $(EXTRADEPS) $(RESULTDEPS)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) -a $(ALL_LDFLAGS) \
				$(OBJS_LIBS) -o $@ $(OCAMLBLDFLAGS) $(LIB_PACK_NAME).cmo

$(RESULT).cmxa $(RESULT).$(EXT_LIB):	$(LIB_PACK_NAME).cmi $(LIB_PACK_NAME).cmx $(EXTRADEPS) $(RESULTDEPS)
			$(REAL_OCAMLFIND) $(OCAMLOPT) -a $(ALL_LDFLAGS) $(OBJS_LIBS) \
				$(OCAMLNLDFLAGS) -o $@ $(LIB_PACK_NAME).cmx
endif

$(RES_CLIB): 		$(OBJ_LINK)
ifndef MSVC
  ifneq ($(strip $(OBJ_LINK)),)
		      $(AR) rcs $@ $(OBJ_LINK)
  endif
else
  ifneq ($(strip $(OBJ_LINK)),)
			lib -nologo -debugtype:cv -out:$(RES_CLIB) $(OBJ_LINK)
  endif
endif

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

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

ifdef PACK_LIB
$(REAL_RESULT).cmo $(REAL_RESULT).cmx $(REAL_RESULT).o: $(REAL_IMPL_INTF) $(OBJ_LINK) $(EXTRADEPS)
			$(REAL_OCAMLFIND) $(REAL_OCAMLC) -pack $(ALL_LDFLAGS) \
				$(OBJS_LIBS) -o $@ $(REAL_IMPL)
endif

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

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

.PRECIOUS:		%.ml
%.ml:			%.rep
			$(CAMELEON_REPORT) $(CAMELEON_REPORT_FLAGS) -gen $<

.PRECIOUS:		%.ml
%.ml:			%.zog
			$(CAMELEON_ZOGGY)  $(CAMELEON_ZOGGY_FLAGS) -impl $< > $@

.PRECIOUS:		%.ml
%.ml:			%.glade
			$(OCAML_GLADECC)  $(OCAML_GLADECC_FLAGS) $< > $@

.PRECIOUS:		%.ml %.mli
%.ml %.mli:		%.oxridl
			$(OXRIDL) $<

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

.c.$(EXT_OBJ):
			$(OCAMLC) -c -cc "$(CC)" -ccopt "$(CFLAGS) \
				$(CPPFLAGS) $(CPPFLAGS_WIN32) \
				$(CFLAGS_WIN32) $(CINCFLAGS) $(CFLAG_O)$@ " $< 

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

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

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

doc/$(RESULT)/html: $(DOC_FILES)
	rm -rf $@
	mkdir -p $@
	$(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
	if [ -z "$$pp" ]; then \
	  echo $(OCAMLDOC) -html -d $@ $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES); \
	  $(OCAMLDOC) -html -d $@ $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES); \
	else \
	  echo $(OCAMLDOC) -pp \"$$pp $(PPFLAGS)\" -html -d $@ $(OCAMLDOCFLAGS) \
	  	$(INCFLAGS) $(DOC_FILES); \
	  $(OCAMLDOC) -pp "$$pp $(PPFLAGS)" -html -d $@ $(OCAMLDOCFLAGS) \
	  	$(INCFLAGS) $(DOC_FILES); \
	fi

doc/$(RESULT)/latex: $(DOC_FILES)
	rm -rf $@
	mkdir -p $@
	$(QUIET)pp=`sed -n -e '/^#/d' -e 's/(\*pp \([^*]*\) \*)/\1/p;q' $<`; \
	if [ -z "$$pp" ]; then \
	  echo $(OCAMLDOC) -latex $(OCAMLDOCFLAGS) $(INCFLAGS) \
	  	$(DOC_FILES) -o $@/doc.tex; \
	  $(OCAMLDOC) -latex $(OCAMLDOCFLAGS) $(INCFLAGS) $(DOC_FILES) \
	  	-o $@/doc.tex; \
	else \
	  echo $(OCAMLDOC) -pp \"$$pp $(PPFLAGS)\" -latex $(OCAMLDOCFLAGS) \
	  	$(INCFLAGS) $(DOC_FILES) -o $@/doc.tex; \
	  $(OCAMLDOC) -pp "$$pp $(PPFLAGS)" -latex $(OCAMLDOCFLAGS) \
	  	$(INCFLAGS) $(DOC_FILES) -o $@/doc.tex; \
	fi

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

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

define make_subproj
.PHONY:
subproj_$(1):
	$$(eval $$(call PROJ_$(1)))
	$(QUIET)if [ "$(SUBTARGET)" != "all" ]; then \
	  $(MAKE) -f $(OCAMLMAKEFILE) $(SUBTARGET); \
	fi
endef

$(foreach subproj,$(SUBPROJS),$(eval $(call make_subproj,$(subproj))))

.PHONY:
subprojs: $(SUBPROJS:%=subproj_%)

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

.PHONY: libinstall
libinstall:	all
	$(QUIET)printf "\nInstalling library with ocamlfind\n"
	$(OCAMLFIND) install $(OCAMLFIND_INSTFLAGS) $(RESULT) META $(LIBINSTALL_FILES)
	$(QUIET)printf "\nInstallation successful.\n"

.PHONY: libuninstall
libuninstall:
	$(QUIET)printf "\nUninstalling library with ocamlfind\n"
	$(OCAMLFIND) remove $(OCAMLFIND_INSTFLAGS) $(RESULT)
	$(QUIET)printf "\nUninstallation successful.\n"

.PHONY: rawinstall
rawinstall:	all
	$(QUIET)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
	$(QUIET)printf "\nInstallation successful.\n"

.PHONY: rawuninstall
rawuninstall:
	$(QUIET)printf "\nUninstalling library from: $(OCAML_LIB_INSTALL)\n"
	cd $(OCAML_LIB_INSTALL); rm $(notdir $(LIBINSTALL_FILES))
	$(QUIET)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
