#**************************************************************************
#*                                                                        *
#*                                 OCaml                                  *
#*                                                                        *
#*            Xavier Leroy, projet Cristal, INRIA Rocquencourt            *
#*                                                                        *
#*   Copyright 1999 Institut National de Recherche en Informatique et     *
#*     en Automatique.                                                    *
#*                                                                        *
#*   All rights reserved.  This file is distributed under the terms of    *
#*   the GNU Lesser General Public License version 2.1, with the          *
#*   special exception on linking described in the file LICENSE.          *
#*                                                                        *
#**************************************************************************

# Common Makefile for otherlibs

ROOTDIR=../..
include $(ROOTDIR)/Makefile.common
include $(ROOTDIR)/Makefile.best_binaries

CAMLC := $(BEST_OCAMLC) $(STDLIBFLAGS)
CAMLOPT := $(BEST_OCAMLOPT) $(STDLIBFLAGS)

ifneq "$(CCOMPTYPE)" "msvc"
OC_CFLAGS += -g
endif

OC_CFLAGS += $(SHAREDLIB_CFLAGS)

# Compilation options
COMPFLAGS=-absname -w +a-4-9-41-42-44-45-48 -warn-error +A -bin-annot -g \
          -strict-sequence -strict-formats $(EXTRACAMLFLAGS)
ifeq "$(FLAMBDA)" "true"
OPTCOMPFLAGS += -O3
endif
MKLIB=$(OCAMLRUN) $(ROOTDIR)/tools/ocamlmklib$(EXE)

# Variables that must be defined by individual libraries:
# LIBNAME
# CAMLOBJS

# Variables that can be defined by individual libraries,
# but have sensible default values:
C_SOURCES ?=
EXTRACAMLFLAGS ?=
LINKOPTS ?=
LDOPTS ?=
HEADERS ?=
CMIFILES ?= $(CAMLOBJS:.cmo=.cmi)
CAMLOBJS_NAT ?= $(CAMLOBJS:.cmo=.cmx)
CLIBNAME ?= $(LIBNAME)

ifeq "$(C_SOURCES)" ""
STUBSLIB=
else
COBJS_BYTECODE = $(C_SOURCES:.c=.b.$(O))
COBJS_NATIVE = $(C_SOURCES:.c=.n.$(O))
COBJS = $(COBJS_BYTECODE) $(COBJS_NATIVE)

CLIBNAME_BYTECODE=$(CLIBNAME)byt
CLIBNAME_NATIVE=$(CLIBNAME)nat
STUBSLIB_BYTECODE=lib$(CLIBNAME_BYTECODE).$(A)
STUBSLIB_NATIVE=lib$(CLIBNAME_NATIVE).$(A)
endif

.PHONY: all allopt opt.opt # allopt and opt.opt are synonyms
all: $(STUBSLIB_BYTECODE) $(LIBNAME).cma $(CMIFILES)

allopt: $(STUBSLIB_NATIVE) $(LIBNAME).cmxa $(LIBNAME).$(CMXS) $(CMIFILES)
opt.opt: allopt

$(LIBNAME).cma: $(CAMLOBJS)
ifeq "$(COBJS)" ""
	$(V_LINKC)$(CAMLC) -o $@ -a -linkall $(CAMLOBJS) $(LINKOPTS)
else
	$(V_OCAMLMKLIB)$(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME_BYTECODE) -ocamlc '$(CAMLC)' \
                -linkall $(CAMLOBJS) $(LINKOPTS)
endif

$(LIBNAME).cmxa: $(CAMLOBJS_NAT)
ifeq "$(COBJS)" ""
	$(V_OCAMLOPT)$(CAMLOPT) -o $@ -a -linkall $(CAMLOBJS_NAT) $(LINKOPTS)
else
	$(V_OCAMLMKLIB)$(MKLIB) -o $(LIBNAME) -oc $(CLIBNAME_NATIVE) -ocamlopt '$(CAMLOPT)' \
                -linkall $(CAMLOBJS_NAT) $(LINKOPTS)
endif

$(LIBNAME).cmxs: $(LIBNAME).cmxa $(STUBSLIB_NATIVE)
	$(V_OCAMLOPT)$(CAMLOPT) -shared -o $(LIBNAME).cmxs -I . $(LIBNAME).cmxa

lib$(CLIBNAME_BYTECODE).$(A): $(COBJS)
	$(V_OCAMLMKLIB)$(MKLIB) -oc $(CLIBNAME_BYTECODE) $(COBJS_BYTECODE) $(LDOPTS)

lib$(CLIBNAME_NATIVE).$(A): $(COBJS)
	$(V_OCAMLMKLIB)$(MKLIB) -oc $(CLIBNAME_NATIVE) $(COBJS_NATIVE) $(LDOPTS)

INSTALL_LIBDIR_LIBNAME = $(INSTALL_LIBDIR)/$(LIBNAME)

install::
	if test -f dll$(CLIBNAME_BYTECODE)$(EXT_DLL); then \
	  $(INSTALL_PROG) \
	    dll$(CLIBNAME_BYTECODE)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)"; \
	fi
ifneq "$(STUBSLIB_BYTECODE)" ""
	$(INSTALL_DATA) $(STUBSLIB_BYTECODE) "$(INSTALL_LIBDIR)/"
endif
# If installing over a previous OCaml version, ensure the library is removed
# from the previous installation.
	rm -f $(addprefix "$(INSTALL_LIBDIR)"/, \
          $(LIBNAME).cma $(CMIFILES) \
          $(CMIFILES:.cmi=.mli) $(CMIFILES:.cmi=.cmti) \
          $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).cmxs $(LIBNAME).$(A))
	$(MKDIR) "$(INSTALL_LIBDIR_LIBNAME)"
	$(INSTALL_DATA) \
	  $(LIBNAME).cma $(CMIFILES) META \
	  "$(INSTALL_LIBDIR_LIBNAME)/"
ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
	$(INSTALL_DATA) \
	  $(CMIFILES:.cmi=.mli) \
          $(CMIFILES:.cmi=.cmti) \
	  "$(INSTALL_LIBDIR_LIBNAME)/"
endif
	if test -n "$(HEADERS)"; then \
	  $(INSTALL_DATA) $(HEADERS) "$(INSTALL_INCDIR)/"; \
	fi

installopt:
	$(INSTALL_DATA) \
	   $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) \
	   "$(INSTALL_LIBDIR_LIBNAME)/"
	if test -f $(LIBNAME).cmxs; then \
	  $(INSTALL_PROG) $(LIBNAME).cmxs "$(INSTALL_LIBDIR_LIBNAME)"; \
	fi
	if test -f dll$(CLIBNAME_NATIVE)$(EXT_DLL); then \
	  $(INSTALL_PROG) \
	    dll$(CLIBNAME_NATIVE)$(EXT_DLL) "$(INSTALL_STUBLIBDIR)"; \
	fi
ifneq "$(STUBSLIB_NATIVE)" ""
	$(INSTALL_DATA) $(STUBSLIB_NATIVE) "$(INSTALL_LIBDIR)/"
endif

partialclean:
	rm -f *.cm*

clean:: partialclean
	rm -f *.dll *.so *.a *.lib *.o *.obj
	rm -rf $(DEPDIR)

.PHONY: distclean
distclean:: clean
	rm -f META

%.cmi: %.mli
	$(V_OCAMLC)$(CAMLC) -c $(COMPFLAGS) $<

%.cmo: %.ml
	$(V_OCAMLC)$(CAMLC) -c $(COMPFLAGS) $<

%.cmx: %.ml
	$(V_OCAMLOPT)$(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $<

%.b.$(O): %.c $(REQUIRED_HEADERS)
	$(V_CC)$(CC) $(OC_CFLAGS) $(CFLAGS) $(OC_CPPFLAGS) $(CPPFLAGS) \
	  $(OUTPUTOBJ)$@ -c $<

%.n.$(O): OC_CFLAGS += $(OC_NATIVE_CFLAGS)

%.n.$(O): %.c $(REQUIRED_HEADERS)
	$(V_CC)$(CC) $(OC_CFLAGS) $(CFLAGS) \
	  $(OC_CPPFLAGS) $(CPPFLAGS) $(OUTPUTOBJ)$@ -c $<

ifeq "$(COMPUTE_DEPS)" "true"
ifneq "$(COBJS_BYTECODE)" ""
include $(addprefix $(DEPDIR)/, $(COBJS_BYTECODE:.b.$(O)=.$(D)))
endif
endif

$(DEPDIR)/%.$(D): %.c | $(DEPDIR)
	$(V_CCDEPS)$(DEP_CC) $(OC_CPPFLAGS) $(CPPFLAGS) $< -MT '$*.$(O)' -MF $@
