#!/usr/bin/env bash

set -e

# This script adds a new crosscompiler target for MLton.
#
# It takes four arguments.
#
# 1. <crossTarget>, which is what MLton would pass via the -b flag to the GCC
#    cross-compiler tools.  You don't need to have installed these tools in order
#    to run this script, since it uses ssh and the native gcc on the target.
#    Examples of $crossTarget are i386-pc-cygwin and sparc-sun-solaris.
#
# 2. <crossArch> specifies the target architecture.
#
# 3. <crossOS> specifies the target OS.
#
# 4. <machine> specifies a remote machine of the target type.  This script
#    will ssh to $machine to compile the runtime and to compile and run the
#    program that will print the values of all the constants that the MLton
#    basis library needs.
#
# Here are some example uses of this script.
#
#   add-cross i386-pc-cygwin x86 cygwin cygwin
#   add-cross sparc-sun-solaris sparc solaris blade
#
# (Here cygwin happens to be the name of my Cygwin machine and blade
#  happens to be the name of my Sparc machine.)
#
# You also may need to set $libDir, which determines where the
# cross-compiler target will be installed.

die () {
        echo >&2 "$1"
        exit 1
}

usage () {
        die "usage: $name <crossTarget> <crossArch> <crossOS> <machine>"
}

case "$#" in
4)
        crossTarget="$1"
        crossArch="$2"
        crossOS="$3"
        machine="$4"
        ;;
*)
        usage
        ;;
esac

name=`basename "$0"`
original=`pwd`
dir=`dirname "$0"`
src=`cd "$dir/.." && pwd`

PATH="$dir":$PATH

# libDir is the mlton lib directory where you would like the
# cross-compiler information to be installed.  If you have installed
# from the rpms, this will usually be /usr/lib/mlton.  You must have
# write permission there.

lib="$src/build/lib"

# You shouldn't need to change anything below this line.

rm -rf "$lib/targets/$crossTarget"
mkdir -p "$lib/targets/$crossTarget" || die "Cannot write to $lib."

tmp='/tmp/mlton-add-cross'

( cd "$src" &&
        mmake TARGET=$crossTarget TARGET_ARCH=$crossArch TARGET_OS=$crossOS \
                dirs )

ssh $machine "rm -rf $tmp && mkdir $tmp"

echo "Copying files."
( cd "$src" && tar cf - --exclude '*.o' --exclude '*.a' Makefile basis-library bin include runtime ) |
        ssh $machine "cd $tmp && tar xf - &&
                if [ ! $crossArch == \`./bin/host-arch\` ]; then echo $machine is \`./bin/host-arch\`, not $crossArch; exit 1; fi &&
                if [ ! $crossOS == \`./bin/host-os\` ]; then echo $machine is \`./bin/host-os\`, not $crossOS; exit 1; fi"

echo "Making runtime on $machine."
ssh $machine "cd $tmp && ./bin/mmake CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\" COMPILE_FAST=yes OMIT_BYTECODE=yes clean dirs runtime"

ssh $machine "cd $tmp/build/lib/targets/self && tar cf - ." |
        ( cd "$lib/targets/$crossTarget" && tar xf - )
( cd "$src" &&
        mmake TARGET=$crossTarget TARGET_ARCH=$crossArch TARGET_OS=$crossOS \
                mlbpathmap )

case "$crossOS" in
mingw)
	suf='.exe'
;;
*)
	suf=''
;;
esac

# Copied from mlton-script
case "$crossArch" in
amd64)
        archOpts='-m64'
;;
hppa)
        archOpts=''
;;
ia64)
	archOpts='-mlp64'
;;
sparc)
        archOpts='-m32'
;;
x86)
        archOpts=''
;;
esac

case "$crossOS" in
aix)
        osOpts='-maix64'
;;
cygwin)
        osOpts=''
;;
darwin)
        osOpts='-I/usr/local/include -I/opt/local/include -I/sw/include -L/usr/local/lib -L/opt/local/lib -L/sw/lib'
;;
freebsd)
        osOpts='-I/usr/local/include -L/usr/local/lib/'
;;
hurd)
        osOpts=''
;;
hpux)
        osOpts=''
;;
linux)
        osOpts=''
;;
mingw)
	libs='-lws2_32 -lkernel32 -lpsapi -lnetapi32 -lwinmm'
;;
netbsd)
        osOpts='-I/usr/pkg/include -Wl,-R/usr/pkg/lib -L/usr/pkg/lib/'
;;
openbsd)
        osOpts='-I/usr/local/include -L/usr/local/lib/'
;;
solaris)
        osOpts='-lnsl -lsocket -lrt'
;;
esac

exe='print-constants'
echo "Compiling and running print-constants on $machine."
"$src/build/bin/mlton" -target $crossTarget -build-constants true |
        ssh $machine "cd $tmp/runtime &&
                        cat >$exe.c &&
                        gcc $archOpts $osOpts $CPPFLAGS -I. -o $exe $exe.c libmlton.a libgdtoa.a $LDFLAGS -lgmp -lm"
ssh $machine "$tmp/runtime/$exe$suf" >"$lib/targets/$crossTarget/constants"
ssh $machine "rm -rf $tmp"
