#!/bin/sh
set -e
cd $(dirname "$0")

# There are two ways that Gerbil may get version information:
# 1. a version MANIFEST file, for git-less tarballs and builds (e.g. Nix, Guix)
# 2. git, for regular development
#
# The format of the version MANIFEST file is as generated by ./manifest.sh
# with quote-less shell definitions var=value for the following variables:
# gerbil_stamp_version gambit_stamp_version gambit_stamp_ymd gambit_stamp_hms

die() {
  echo "configuration failed"
  exit 1
}

usage() {
    local gambit_config_help="$(cd src/gambit && ./configure --help | tail -n +63)"

    cat <<EOF
This script configures the Gerbil and integrated Gambit build.

Usage: $0 [option] ... [var=value]...

Options controlling integrated Gambit configuration:
${gambit_config_help}

Options understood and processed by Gerbil:
  --prefix=PREFIX       where to install Gerbil; default prefix is /opt/gerbil
  --with-gambit=TAG     integrated gambit git tag to check out for the build;
                        defaults to ${default_gambit_tag}
  --enable-march=ARCH   specify the machine architecture; it can be empty.
                        defaults to native
  --enable-shared[=no]  do (not) use shared libraries for libgerbil and libgambit
  --disable-shared      default is to enable shared libraries

Gerbil Standard Library features:
  --enable-deprecated   Enable building of deprecated packages; disabled by default
  --enable-zlib         Enable or disable zlib support; enabled by default
  --disable-zlib
  --enable-sqlite       Enable or disable sqlite support; enabled by default
  --disable-sqlite

Default integrated Gambit configuration: ${default_gambit_config}
EOF
}


std_patch_feature() {
    sed -i -e "$1" src/std/build-features.ss
}

std_enable_feature() {
    std_patch_feature "s/$1 #f/$1 #t/"
}

std_disable_feature() {
    std_patch_feature "s/$1 #t/$1 #f/"
}

package_out_of_tree() {
    local pkg="$1"
    echo "*** ERROR package ${pkg} has been moved out of the master Gerbil tree"
    echo "It is now available as an external package: github.com/mighty-gerbils/gerbil-${pkg}"
}

if [ -f MANIFEST ] ; then
  . ./MANIFEST
  readonly gerbil_version="$gerbil_stamp_version"
else
  readonly gerbil_version="$(git describe --tags --always)"
fi
readonly gerbil_targets=""
readonly default_gambit_tag=8b18ab69504c2d41301f7fec16a5350db717a20e
readonly default_gambit_config="--enable-targets=${gerbil_targets} --enable-single-host --enable-dynamic-clib --enable-default-runtime-options=tE8,f8,-8 --enable-trust-c-tco"
prefix="/opt/gerbil"
readonly cflags_opt="-foptimize-sibling-calls"
readonly ldflags_rpath="-Wl,-rpath"

if [ $(uname) = "Darwin" ];
then
    readonly rpath_sep=","
else
    readonly rpath_sep="="
fi

case $(uname) in
    OpenBSD)
        gambit_march=""
        ;;
    *)
        gambit_march="native"
        ;;
esac

gerbil_shared=t
gambit_tag="${default_gambit_tag}"
gambit_config="${default_gambit_config}"
gambit_shared="--enable-shared"

while [ $# -gt 0 ]; do
    case "$1" in
        --help)
            usage
            exit 0
            ;;

        --prefix=*)
            prefix=$(echo "$1" | cut -d = -f 2-)
            shift
            ;;

        --with-gambit=*)
            gambit_tag=$(echo "$1" | cut -d = -f 2-)
            shift
            ;;

        --enable-march=*)
            gambit_march=$(echo "$1" | cut -d = -f 2-)
            shift
            ;;

        --enable-shared)
            gerbil_shared=t
            gambit_shared="--enable-shared"
            shift
            ;;

        --disable-shared|--enable-shared=no)
            gerbil_shared=f
            unset gambit_shared
            shift
            ;;

        --enable-deprecated)
            std_enable_feature deprecated
            shift
            ;;

        --enable-zlib)
            std_enable_feature zlib
            shift
            ;;

        --disable-zlib)
            std_disable_feature zlib
            shift
            ;;

        --enable-sqlite)
            std_enable_feature sqlite
            shift
            ;;

        --disable-sqlite)
            std_disable_feature sqlite
            shift
            ;;

        --*-libxml)
            package_out_of_tree libxml
            exit 42
            ;;

        --*-libyaml)
            package_out_of_tree libyaml
            exit 42
            ;;

        --*-mysql)
            package_out_of_tree mysql
            exit 42
            ;;

        --*-lmdb)
            package_out_of_tree lmdb
            exit 42
            ;;

        --*-leveldb)
            package_out_of_tree leveldb
            exit 42
            ;;

        CFLAGS=*)
            flags=$(echo "$1" | cut -d = -f 2-)
            if [ -z "$CFLAGS" ]; then
                CFLAGS="$flags"
            else
                CFLAGS="$CFLAGS $flags"
            fi
            shift
            ;;

        LDFLAGS=*)
            flags=$(echo "$1" | cut -d = -f 2-)
            if [ -z "${LDFLAGS}" ]; then
                LDFLAGS="${flags}"
            else
                LDFLAGS="${LDFLAGS} ${flags}"
            fi
            shift
            ;;
        *)
            gambit_config="${gambit_config} $1"
            shift
        ;;
    esac
done

gerbil_prefix="${prefix}/${gerbil_version}"

if [ -z "${CFLAGS}" ]; then
    CFLAGS="${cflags_opt}"
else
    CFLAGS="${CFLAGS} ${cflags_opt}"
fi
if [ -z "${LDFLAGS}" ]; then
    if [ "${gerbil_shared}" = "t" ]; then
	LDFLAGS="${ldflags_rpath}$rpath_sep${gerbil_prefix}/lib"
    fi
else
    if [ "${gerbil_shared}" = "t" ]; then
	LDFLAGS="${LDFLAGS} ${ldflags_rpath}$rpath_sep${gerbil_prefix}/lib"
    fi
fi

if [ ! -f MANIFEST -o ! -f src/gambit/configure ] ; then
  git submodule init || die
  git submodule update --force || die
  (cd src/gambit && git fetch origin && git checkout "${gambit_tag}" && touch configure config.status) || die
  unset gambit_stamp_version
fi

gambit_config="--prefix=${gerbil_prefix} --enable-march=${gambit_march} ${gambit_shared} ${gambit_config}"
(export LDFLAGS="$LDFLAGS"; export CFLAGS="$CFLAGS"; cd src/gambit && ./configure $gambit_config ) || die

if [ -n "$gambit_stamp_version" ] ; then
  sed -i -e "s/^stamp:/stamp-orig:/" src/gambit/include/makefile
  echo stamp: >> src/gambit/include/makefile
  cat >> src/gambit/include/stamp.h <<EOF
#ifndef ___STAMP_VERSION
#define ___STAMP_VERSION "${gambit_stamp_version}"
#endif

#ifndef ___STAMP_YMD
#define ___STAMP_YMD ${gambit_stamp_ymd}
#endif

#ifndef ___STAMP_HMS
#define ___STAMP_HMS ${gambit_stamp_hms}
#endif
EOF
fi

rm -f build-env.sh
cat > build-env.sh <<EOF
GERBIL_PREFIX=${gerbil_prefix}
GERBIL_VERSION=${gerbil_version}
export GERBIL_PREFIX GERBIL_VERSION
EOF

exit 0
