#!/bin/sh
#  file kernel/caml/remake: compile rules for the libnumerix-caml library
#-----------------------------------------------------------------------+
#  Copyright 2005-2006, Michel Quercia (michel.quercia@prepas.org)      |
#                                                                       |
#  This file is part of Numerix. Numerix is free software; you can      |
#  redistribute it and/or modify it under the terms of the GNU Lesser   |
#  General Public License as published by the Free Software Foundation; |
#  either version 2.1 of the License, or (at your option) any later     |
#  version.                                                             |
#                                                                       |
#  The Numerix Library is distributed in the hope that it will be       |
#  useful, but WITHOUT ANY WARRANTY; without even the implied warranty  |
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  |
#  Lesser General Public License for more details.                      |
#                                                                       |
#  You should have received a copy of the GNU Lesser General Public     |
#  License along with the GNU MP Library; see the file COPYING. If not, |
#  write to the Free Software Foundation, Inc., 59 Temple Place -       |
#  Suite 330, Boston, MA 02111-1307, USA.                               |
#-----------------------------------------------------------------------+
#                                                                       |
#                 Rgles de construction de libnumerix-caml             |
#                                                                       |
#-----------------------------------------------------------------------+

# m_list    = liste des modes (c/d/s)
# b_list    = liste additionnelle pour Bignum (b)
# g_list    = liste additionnelle pour Gmp (g)
# mode_list = liste des noms complets (clong/dlong/slong/big/gmp)
# zo_list   = liste additionnelle des modules .zo (nums.zo)
# zi_list   = liste additionnelle des interfaces .zi (nums.zi)
# link = bibliothques additionnelles (nums/gmp)

m_list=
b_list=
g_list=
mode_list=
zo_list=
zi_list=
link=

if test "$USE_CLONG" = "1"; then
    m_list="${m_list} c"
    mode_list="${mode_list} clong"
fi
if test "$USE_DLONG" = "1"; then
    m_list="${m_list} d"
    mode_list="${mode_list} dlong"
fi
if test "$USE_SLONG" = "1"; then
    m_list="${m_list} s"
    mode_list="${mode_list} slong"
fi
if test "$USE_CAML_BIGNUM" = "1"; then
    b_list="${b_list} b"
    mode_list="${mode_list} big"
    zo_list="${zo_list} nums.zo"
    zi_list="${zi_list} kernel/caml/o/nums.zi"
    link="${link} -lnums"
fi
if test "$USE_GMP" = "1"; then
    g_list="${g_list} g"
    mode_list="${mode_list} gmp"
    link="${link} -lgmp"
fi

# On y va
cat <<EOF
# File kernel/caml/makefile: compile rules for the libnumerix-caml library
EOF
sed -n -e '3,/^$/p' $0 
cat <<EOF
# This file was generated by the kernel/caml/remake script
# switches:
#   USE_CLONG=$USE_CLONG
#   USE_DLONG=$USE_DLONG
#   USE_SLONG=$USE_SLONG
#   USE_CAML_BIGNUM=$USE_CAML_BIGNUM
#   USE_GMP=$USE_GMP
#   MAKE_CAML_LIB=$MAKE_CAML_LIB
#   SHARED=$SHARED
EOF

if test "$MAKE_CAML_LIB" = "0"; then exit; fi

cat <<EOF
#-------------------- config files
lib_caml_config = Makefile kernel/config.h kernel/caml/makefile

#-------------------- source files
lib_caml_c_src = \\
  kernel/caml/c/numerix.c \\
  kernel/x/c/add.c       \\
  kernel/x/c/cmp.c       \\
  kernel/x/c/convert.c   \\
  kernel/x/c/copy.c      \\
  kernel/x/c/div.c       \\
  kernel/x/c/dump.c      \\
  kernel/x/c/fact.c      \\
  kernel/x/c/gcd.c       \\
  kernel/x/c/mul.c       \\
  kernel/x/c/pow.c       \\
  kernel/x/c/powmod.c    \\
  kernel/x/c/prime.c     \\
  kernel/x/c/random.c    \\
  kernel/x/c/root.c      \\
  kernel/x/c/shift.c     \\
  kernel/x/c/sqrt.c      \\
  kernel/x/c/string.c

lib_caml_h_src = \\
  kernel/caml/h/numerix.h \\
  kernel/x/h/numerix.h   \\
  kernel/x/h/alloc.h     \\
  kernel/x/h/add.h       \\
  kernel/x/h/cmp.h       \\
  kernel/x/h/convert.h   \\
  kernel/x/h/copy.h      \\
  kernel/x/h/div.h       \\
  kernel/x/h/dump.h      \\
  kernel/x/h/fact.h      \\
  kernel/x/h/gcd.h       \\
  kernel/x/h/mul.h       \\
  kernel/x/h/pow.h       \\
  kernel/x/h/powmod.h    \\
  kernel/x/h/prime.h     \\
  kernel/x/h/random.h    \\
  kernel/x/h/root.h      \\
  kernel/x/h/shift.h     \\
  kernel/x/h/sqrt.h      \\
  kernel/x/h/string.h    \\
  kernel/x/h/chrono.h
EOF

cat <<EOF

#-------------------- library, C-part
lib_caml_obj = \\
EOF

echo -n "  kernel/caml/o/chrono.o "
for m in $m_list $g_list; do echo -n "\\
  kernel/caml/o/numerix-$m.o "
done
echo

cat <<EOF

kernel/caml/o/chrono.o: \$(lib_caml_config) kernel/x/c/chrono.c kernel/x/h/chrono.h
	\$(GCC) \$(PIC) -I\$(CAML_LIBDIR) -Dcaml_api -c -o \$@ kernel/x/c/chrono.c
EOF
for m in $m_list; do cat <<EOF
kernel/caml/o/numerix-$m.o: \$(lib_caml_config) \$(lib_caml_c_src) \$(lib_caml_h_src) \$(lib_n_obj)
	\$(GCC) \$(PIC) -I\$(CAML_LIBDIR) -Duse_${m}long -c -o \$@ kernel/caml/c/numerix.c
EOF
done
if test "$USE_GMP" = "1"; then cat <<EOF
kernel/caml/o/numerix-g.o: \$(lib_caml_config) kernel/caml/c/gmp.c kernel/x/c/gmp.c
	\$(GCC) \$(PIC) -I\$(CAML_LIBDIR) -c -o \$@ kernel/caml/c/gmp.c
EOF
fi

if test x$SHARED = x1; then
cat <<EOF
lib_caml_0 = libnumerix-caml.so
lib_caml_1 = \$(lib_caml_0).\$(NUMERIX_MAJOR)
lib_caml_2 = \$(lib_caml_1).\$(NUMERIX_MINOR)
lib_caml = kernel/caml/o/\$(lib_caml_2)
\$(lib_caml): \$(lib_caml_obj) \$(lib_n_obj)
	\$(GCC) -shared -Wl,-soname,\$(lib_caml_1) -o \$@ \$(lib_caml_obj) \$(lib_n_obj)
	ln -s \$(lib_caml_2) kernel/caml/o/\$(lib_caml_1)
	ln -s \$(lib_caml_1) kernel/caml/o/\$(lib_caml_0)
EOF

else cat <<EOF

lib_caml = kernel/caml/o/libnumerix-caml.a
\$(lib_caml): \$(lib_caml_obj) \$(lib_n_obj)
	rm -f \$@
	\$(AR) \$@ \$(lib_caml_obj) \$(lib_n_obj)
	\$(RANLIB) \$@

EOF
fi

# note: on my computer, libcaml.a generates a strange warning at the
# linking stage :
#
#  /usr/local/lib/caml-light/libcaml.a(sys.o)(.text+0x2a3): dans la fonction  error_message :
#  : warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead
#  /usr/local/lib/caml-light/libcaml.a(sys.o)(.text+0x292): dans la fonction  error_message :
#  : warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead
#
# I don't know how to fix it ... except by filtering out the warning
# with an adhoc sed command (In France we say: "break the thermometer
# so as to not have fever anymore").
cat <<EOF

#-------------------- link options when compiling with camlc/camlmktop
CAML_CCOPT = -ccopt -Lkernel/caml/o -lnumerix-caml$link \
 2>&1 | sed -e '/libcaml.a/d' -e '/deprecated/d'

EOF


cat <<EOF
#-------------------- library, Caml-part
EOF

for ext in ml mli zo zi; do
  echo -n "lib_caml_$ext = "
  for m in $mode_list; do echo -n "\\
  kernel/caml/o/$m.$ext    \\
  kernel/caml/o/inf$m.$ext "
  done
  echo
  echo
done

for m in $mode_list; do for i in "" inf; do
    if test "$m" = "big" && test "$i" = ""
    then source=big
    else source=xlong
    fi
    cat <<EOF
kernel/caml/o/${i}${m}.mli: kernel/caml/mli/${i}${source}.mli
	kernel/caml/numerix.sh \$@
kernel/caml/o/${i}${m}.zi: kernel/caml/o/${i}${m}.mli
	\$(CAMLC) -I kernel/caml/o -c kernel/caml/o/${i}${m}.mli
kernel/caml/o/${i}${m}.ml: kernel/caml/ml/${i}${source}.ml
	kernel/caml/numerix.sh \$@
kernel/caml/o/${i}${m}.zo: kernel/caml/o/${i}${m}.ml kernel/caml/o/${i}${m}.zi
	\$(CAMLC) -I kernel/caml/o -c kernel/caml/o/${i}${m}.ml
EOF
done; done
if test "$USE_CAML_BIGNUM" = "1"; then cat <<EOF
kernel/caml/o/nums.zi:
	: > kernel/caml/o/nums.mli
	\$(CAMLC) -I kernel/caml/o -c kernel/caml/o/nums.mli
EOF
fi

cat <<EOF

kernel/caml/o/numerix.zo: \$(lib_caml_zo)
	\$(CAMLLIBR) -o \$@ \$(lib_caml_zo)
EOF

l=
for m in $mode_list; do l="$l \"$m\" ::"; done
cat <<EOF

#-------------------- toplevel
kernel/caml/o/toplevelcfg.zo: kernel/caml/ml/toplevelcfg.ml \$(lib_caml_zo)
	sed -e 's/_mode_list_/$l/' \\
	    -e 's?_directory_?\$(CAML_INSTALL_LIB)?' \\
	    -e 's/_numerix_version_/\$(NUMERIX_MAJOR).\$(NUMERIX_MINOR)/' \\
	    kernel/caml/ml/toplevelcfg.ml >kernel/caml/o/toplevelcfg.ml
	\$(CAMLC) -I kernel/caml/o -o \$@ -c kernel/caml/o/toplevelcfg.ml

kernel/caml/o/camlnumx: \$(lib_caml_zo) kernel/caml/o/toplevelcfg.zo$zi_list \$(lib_caml)
	\$(CAMLMKTOP) -I kernel/caml/o -custom -o \$@$zo_list \$(lib_caml_zo) kernel/caml/o/toplevelcfg.zo \$(CAML_CCOPT)

EOF

cat <<EOF
#-------------------- installation
.PHONY: install_caml
lib_caml_lib = \$(lib_caml_zi) kernel/caml/o/numerix.zo kernel/caml/o/camlnumx
lib_caml_include = \$(lib_caml_ml) \$(lib_caml_mli)
install_caml: \$(lib_caml) \$(lib_caml_zlib) \$(lib_caml_include)
	mkdir -p \$(CAML_INSTALL_LIB) \$(CAML_INSTALL_INCLUDE)
	cp -p \$(lib_caml) \$(lib_caml_lib) \$(CAML_INSTALL_LIB)
	cp -p \$(lib_caml_include) \$(CAML_INSTALL_INCLUDE)
EOF
if test x$SHARED = x1; then cat <<EOF
	ln -s \$(lib_caml_2) \$(CAML_INSTALL_LIB)/\$(lib_caml_1)
	ln -s \$(lib_caml_1) \$(CAML_INSTALL_LIB)/\$(lib_caml_0)
EOF
else cat <<EOF
	\$(RANLIB) \$(CAML_INSTALL_LIB)/libnumerix-caml.a
EOF
fi

exemples="pi shanks simple"
cat <<EOF

#-------------------- examples
EOF
echo -n "ex_caml_obj = "
for m in $m_list $b_list $g_list; do for e in $exemples; do echo -n "\\
  exemples/caml/$e-$m "
done; done
echo
echo

for m in $mode_list; do
    s=`echo $m | sed -e 's/\(.\).*/\1/'`
    for e in $exemples; do cat <<EOF
exemples/caml/$e-$s: exemples/caml/$e.ml kernel/caml/o/numerix.zo \$(lib_caml)
	sed -e 's/_name_/$m/g' exemples/caml/$e.ml >\$@.ml
	\$(CAMLC) -I kernel/caml/o -custom -o \$@ $zo_list kernel/caml/o/numerix.zo \$@.ml \$(CAML_CCOPT)
	@rm exemples/caml/$e-$s.ml exemples/caml/$e-$s.zi exemples/caml/$e-$s.zo
EOF
done; done

cat <<EOF

.PHONY: test_caml
test_caml: \$(ex_caml_obj)
	@echo "-------------------- Testing the Caml interface"
	for i in $exemples; do for j in $m_list$b_list$g_list; do \\
	    LD_LIBRARY_PATH=kernel/caml/o:\$\$LD_LIBRARY_PATH exemples/caml/\$\$i-\$\$j -test; \\
	done; done

#-------------------- cleanup
.PHONY: clean_caml
clean_caml:
	rm -f kernel/caml/o/* exemples/caml/*{-b,-c,-d,-g,-s,.exe}
EOF

cat <<EOF

#-------------------- done
lib: \$(lib_caml)
lib: \$(lib_caml_ml)
lib: \$(lib_caml_mli)
lib: \$(lib_caml_zi)
lib: kernel/caml/o/numerix.zo
lib: kernel/caml/o/camlnumx

install:      install_caml
exemples:     \$(ex_caml_obj)
test:         test_caml
clean:        clean_caml
EOF
