#! /bin/sh
# vim:sw=4:sts=4

# Setup script for lua-gtk
# by Wolfgang Oertl 2008
# tested with bash, dash, ksh, mksh, pdksh, posh.


# - default settings -
VERSION="0.8"
ARCH=
DEBUG=
SUMMARY=1
DEBUGFUNCS=1
HASHF=hsieh
USE_GTKHTML=1
USE_CMPH=1
DYNLINK=1
CFLAGS=
# This is the list of Debian supported CPUs.
ARCH_CPUS="alpha amd64 arm arml armel hppa i386 ia64 mk68k mips mipsel
powerpc s390 sparc"

# only works if cwd is correct
cd $(pwd)	# workaround for posh
cd $(dirname $0)

known_architectures () {
    S="Known architectures:"
    for file in script/config.*; do
	S="$S ${file#script/config.}"
    done
    echo "$S."
    echo "Known CPUs: $ARCH_CPUS"
}

show_help () {
    echo "Usage: $0 [args] [architecture]"
    echo "Configure lua-gtk for compilation."
    echo ""
    echo "  --debug            Compile with debugging information (-g)"
    echo "  --no-summary       Don't show configure results"
    echo "  --disable-debug    Omit debugging functions like dump_struct"
    echo "  --disable-gtkhtml  No support for libgtkhtml"
    echo "  --disable-dynlink  Build time instead of runtime linking"
    echo "  --disable-cmph     Don't use cmph even if it is available"
    echo "  --with-cmph DIR    Use cmph source tree at the given location"
    echo "  --host [ARCH]      Cross compile to another architecture, see below"
    echo ""
    known_architectures
    echo "If no architecture is given, a default is determined."
    echo "For more help, read the INSTALL file."
}

# - parse command line -
while test "$1"; do

    case "$1" in
	--debug) DEBUG=1 ;;
	--summary) SUMMARY=1 ;;
	--no-summary) SUMMARY= ;;
	--disable-debug) DEBUGFUNCS= ;;
	--enable-debug) DEBUGFUNCS=1 ;;
	--disable-gtkhtml) USE_GTKHTML= ;;
	--enable-gtkhtml) USE_GTKHTML=1 ;;
	--disable-dynlink) DYNLINK=0; DYNLINK_SET=1 ;;
	--enable-dynlink) DYNLINK=1; DYNLINK_SET=1 ;;
	--disable-cmph) USE_CMPH=0 ;;
	--enable-cmph) USE_CMPH=1 ;;
	--with-cmph) USE_CMPH=1; CMPH_DIR="$2"; shift ;;

	--host)
	    if test "$ARCH"; then
		echo "$0: unexpected option $1"
		echo "Try \`$0 --help' for more information."
		exit 1
	   fi
	   ARCH=$2
	   shift
	   ;;

	--help)
	    show_help
	    exit 1
	    ;;

	*)
	    echo "$0: unrecognized option $1"
	    echo "Try \`$0 --help' for more information."
	    exit 1
	    ;;
    esac

    shift

done

# what is the host architecture?
if which dpkg-architecture > /dev/null; then
    eval $(dpkg-architecture)
    HOST_ARCH=$DEB_BUILD_ARCH_OS-$DEB_BUILD_ARCH_CPU
else
    CPU=$(uname -m)
    case $CPU in
	# x86_64 might also refer to ia64??  maybe check /proc/cpuinfo?
	x86_64) CPU=amd64 ;;
	i686) CPU=i386 ;;
	# add more things here...
	*)
	    echo "Unsupported result $CPU from uname -m.  Please fix the "
	    echo "script $0 and send the patches to the author."
	    exit 1
	    ;;
    esac
    HOST_ARCH="linux-$CPU"
fi

if test ! "$HOST_ARCH"; then
    echo "Can't determine host architecture."
    exit 1
fi

# without target architecture, use the host architecture.
if test ! "$ARCH"; then
    ARCH=$HOST_ARCH
fi


# check for valid architecture

if test ! "$ARCH"; then
    show_help
    exit 1
fi

# Split into OS and CPU parts.  CPU part must be given.
ARCH_OS=${ARCH%-*}
ARCH_CPU=${ARCH#*-}
if test "$ARCH_CPU" = "$ARCH"; then
    echo "Please specify the CPU part of the architecture, e.g. $ARCH_OS-i386."
    echo "Known architectures: $ARCH_CPUS"
    exit 1
fi

# Check for valid CPU according to the list defined above.
ok=0
for CPU in $ARCH_CPUS; do
    if test $CPU = $ARCH_CPU; then ok=1; break; fi
done

if test $ok == 0; then
    echo "Unknown CPU $ARCH_CPU.  Add to configure script if desired.";
    exit 1
fi

# Either a OS/CPU specific config file is available, or just OS specific.
CONFIG_SCRIPT="script/config.$ARCH"
if test ! -r "$CONFIG_SCRIPT"; then
    if test ! "$ARCH_CPU"; then
	echo "Unknown architecture $ARCH; script/config.$ARCH not available."
	exit 1
    fi
    CONFIG_SCRIPT="script/config.$ARCH_OS"
    if test ! -r "$CONFIG_SCRIPT"; then
	echo "Unknown architecture $ARCH; neither script/config.$ARCH nor"
	echo "script/config.$ARCH_OS are available."
	exit 1
    fi
fi

# - general setup -

ODIR=build/$ARCH
CFG_H_REAL=$ODIR/config.h
CFG_M_REAL=$ODIR/config.make

ERR=0
CFG_H=$CFG_H_REAL.tmp
CFG_M=$CFG_M_REAL.tmp

# - pkg-config -
if which pkg-config > /dev/null; then
    PC=pkg-config
else
    echo "pkg-config not installed - required for setup."
    exit 1
fi


test -d build || mkdir build
test -d $ODIR || mkdir $ODIR
echo -n > $CFG_H
echo -n > $CFG_M

echo "ARCH        :=$ARCH" >> $CFG_M
echo "VERSION     :=$VERSION" >> $CFG_M
echo "ODIR        :=$ODIR/" >> $CFG_M

# extra Makefile?
FNAME=script/Makefile.$ARCH_OS
test -r $FNAME && echo "include $FNAME" >> $CFG_M

FNAME=script/Makefile.$ARCH
test -r $FNAME && echo "include $FNAME" >> $CFG_M

# - Gtk -

if $PC --exists gtk+-2.0; then
    GTK_CFLAGS=$($PC --cflags gtk+-2.0)
    GTK_VERSION=$($PC --modversion gtk+-2.0)
    CFLAGS="$CFLAGS $GTK_CFLAGS"
else
    echo "Gtk 2.0 with development headers not installed."
    ERR=1
fi


# - Lua -

if $PC --exists lua5.1; then
    LUA_CFLAGS=$($PC --cflags lua5.1)
    LUA_VERSION=$($PC --modversion lua5.1)
    CFLAGS="$CFLAGS $LUA_CFLAGS"
else
    echo "Lua 5.1 not installed."
    ERR=1
fi

LUA_BIN=$(which lua5.1)
if test $? -ne 0; then
    LUA_BIN=$(which lua)
    if test $? -ne 0; then
	echo "Lua 5.1 executable not found."
	ERR=1
    fi
fi

# check for required Lua packages

LUA_TEST="build/$ARCH/test.lua"
for lib in lxp bit lfs; do
    echo "require \"$lib\"" > $LUA_TEST
    $LUA_BIN $LUA_TEST 2> /dev/null
    if test $? -ne 0; then
	echo "Required Lua package $lib not found."
	ERR=1
    fi
done

# check for recommended Lua packages
for lib in lfs luadoc.lp; do
    echo "require \"$lib\"" > $LUA_TEST
    $LUA_BIN $LUA_TEST 2> /dev/null
    if test $? -ne 0; then
	echo "Lua package $lib not found, can't build documentation."
    fi
done
rm -f $LUA_TEST

# - cmph -
# architecture independent; it is required for build, not for runtime.

if test $USE_CMPH -eq 0; then
    CMPH_VERSION="disabled"
elif test "$CMPH_DIR"; then
    if test -d "$CMPH_DIR"; then
	CMPH_BIN=$CMPH_DIR/src/cmph
	if test -x $CMPH_BIN; then
	    HAVE_CMPH=1
	    CMPH_CFLAGS="-I $CMPH_DIR/src"
	    CMPH_INCDIR=$CMPH_DIR/src
	    CMPH_VERSION=$($CMPH_BIN -V)
	    CMPH_LIBS="$CMPH_DIR/src/.libs/libcmph.a -lm"
	else
	    echo "Cmph directory found, but no executable?"
	fi
    else
	echo "Cmph directory not found: $CMPH_DIR"
    fi
elif $PC --exists cmph; then
    HAVE_CMPH=1
    CMPH_CFLAGS="$($PC --cflags cmph)"
    CMPH_BIN=cmph

    # if CMPH_FLAGS is empty, then the includes are in the default include
    # path, which is not necessarily used - e.g. MingW or when cross compiling.
    # Therfore copy the required include file.
    set -- $CMPH_FLAGS
    if test -z "$1"; then
	for dir in /usr/include /usr/local/include; do
	    if test -r $dir/cmph_types.h; then
		cp $dir/cmph_types.h $ODIR
		break
	    fi
	done
    fi

    # now what about the private include files?
    for dir in /usr/local/include/cmph/private /usr/include/cmph/private; do
	if test -d $dir; then
	    CMPH_CFLAGS="$CMPH_CFLAGS -I $dir"
	    CMPH_INCDIR=$dir
	    break
	fi
    done

    CMPH_VERSION=$($PC --modversion cmph)
    CMPH_LIBS=$($PC --libs cmph)
else
    CMPH_VERSION="not available"
fi

if test "$HAVE_CMPH"; then
    if test "$CMPH_VERSION" = "wads07"; then
	CMPH_ALGO=bdz
	CMPH_BIN="$CMPH_BIN -e 1"
    else
	CMPH_ALGO=fch
	CMPH_BIN="$CMPH_BIN -c 2.0"
    fi
    echo "CMPH_ALGO   :=$CMPH_ALGO" >> $CFG_M
    echo "#define CMPH_ALGORITHM ${CMPH_ALGO}_search" >> $CFG_H
    echo "#define CMPH_USE_$CMPH_ALGO" >> $CFG_H
    echo "HAVE_CMPH   :=1" >> $CFG_M
    echo "CMPH_CFLAGS :=$CMPH_CFLAGS" >> $CFG_M
    echo "CMPH_BIN    :=$CMPH_BIN" >> $CFG_M
    echo "CMPH_LIBS   :=$CMPH_LIBS" >> $CFG_M
fi

# - libgtkhtml -
if test "$USE_GTKHTML"; then
    if $PC --exists libgtkhtml-2.0; then
	HTML_VERSION=$($PC --modversion libgtkhtml-2.0)
	echo "HAVE_HTML   :=1" >> $CFG_M
	echo "#define HAVE_LIBGTKHTML" >> $CFG_H
    else
	HTML_VERSION="not available"
    fi
else
    HTML_VERSION="disabled"
fi

# C compiler

if which gcc > /dev/null; then
    HOSTCC=gcc
    CC=gcc
else
    echo "GCC not found."
    ERR=1
fi

# detect speedblue.org cross compilation
F=/usr/$ARCH_CPU/bin/$ARCH_CPU-linux-gcc
if test -x $F; then
    CC=$F
fi

# how to run cross-compiled test scripts?
if test $ARCH != $HOST_ARCH; then
    case "$ARCH_CPU" in
	powerpc) QEMU=qemu-ppc ;;
	*) QEMU="qemu-$ARCH_CPU" ;;
    esac

    if which $QEMU > /dev/null; then
	CROSS_RUN="$QEMU"
    fi
fi

# - architecture specific config -

. $CONFIG_SCRIPT

# - Determine correct libffi usage -
CMD="$CC -o $ODIR/test-ffi -I $ODIR $LIBFFI_INC src/test-ffi.c $LIBFFI_LIB"
while true; do
    $CMD -D LUAGTK_FFI_CODE
    if test $? -ne 0; then
	echo "Failed to compile test-ffi (code)"
	break
    fi

    $CROSS_RUN $ODIR/test-ffi
    if test $? -eq 0; then
	LIBFFI_CALL="code"
	echo "#define LUAGTK_FFI_CODE" >> $CFG_H
	break
    fi

    $CMD -D LUAGTK_FFI_CLOSURE
    if test $? -ne 0; then
	echo "Failed to compile test-ffi (closure)"
	break
    fi

    $CROSS_RUN $ODIR/test-ffi
    if test $? -eq 0; then
	LIBFFI_CALL="closure"
	echo "#define LUAGTK_FFI_CLOSURE" >> $CFG_H
	break
    fi

    echo "Libffi closure calling failed."
    ERR=1
    break
done


# get versions of C compiler (just for information)
if test "$HOSTCC"; then
    HOSTCC_VERSION=`$HOSTCC --version | head -1`
fi

if test "$CC" -a "$CC" != "$HOSTCC"; then
    CC_VERSION=`$CC --version | head -1`
fi

# common makefile settings from above
echo "CC          :=$CC" >> $CFG_M
echo "HOSTCC      :=$HOSTCC" >> $CFG_M
echo "DYNLINK     :=$DYNLINK" >> $CFG_M
echo "GTK_LIBS    :=$GTK_LIBS" >> $CFG_M
echo "LIBFFI_LIB  :=$LIBFFI_LIB" >> $CFG_M
echo "CROSS_RUN   :=$CROSS_RUN" >> $CFG_M
CFLAGS="$CFLAGS $LIBFFI_INC"

if test $DYNLINK -ne 0; then
    echo "#define RUNTIME_LINKING" >> $CFG_H
    DYNLINK_INFO="enabled"
else
    DYNLINK_INFO="disabled"
fi


# - general configuration -

CFLAGS="$CFLAGS -Wall -I $ODIR -I src"
echo "HASHF       :=$HASHF" >> $CFG_M
echo "HASH        :=hash-\$(HASHF)" >> $CFG_M

if test "$DEBUG"; then
    CFLAGS="$CFLAGS -g"
    echo "LDFLAGS     +=-g" >> $CFG_M
    DEBUG_INFO="on"
else
    CFLAGS="$CFLAGS -Os -fomit-frame-pointer"
    DEBUG_INFO="off"
fi

echo "CFLAGS      :=$CFLAGS" >> $CFG_M

# - output config.h -

echo "#define LUAGTK_VERSION \"$VERSION\"" >> $CFG_H
echo "#define LUAGTK_${ARCH_OS}_$ARCH_CPU" >> $CFG_H
echo "#define LUAGTK_$ARCH_OS" >> $CFG_H
echo "#define LUAGTK_$ARCH_CPU" >> $CFG_H
echo "#define LUAGTK_ARCH_OS \"$ARCH_OS\"" >> $CFG_H
echo "#define LUAGTK_ARCH_CPU \"$ARCH_CPU\"" >> $CFG_H
echo "#define HASHFUNC hash_$HASHF" >> $CFG_H
if test "$DEBUGFUNCS"; then
    echo "#define LUAGTK_DEBUG_FUNCS" >> $CFG_H
    DEBUG_FUNCS_INFO="enabled"
else
    DEBUG_FUNCS_INFO="disabled"
fi


# - check for errors -

if test $ERR -gt 0; then
    echo "Errors during configuration."
    rm -f $CFG_H $CFG_M
    exit 1
fi


# Replace real config files with new ones if they have changed.  This preserves
# the timestamp and avoids complete rebuilds after reconfiguration.
if test -f $CFG_H_REAL; then
    if diff -q $CFG_H_REAL $CFG_H > /dev/null; then
	rm $CFG_H
    fi
fi

if test -f $CFG_H; then
    mv -f $CFG_H $CFG_H_REAL
fi

# no need to check for differences here.
mv -f $CFG_M $CFG_M_REAL

# set the default architecture for make.
echo $ARCH > build/make.state

if test "$SUMMARY"; then
    echo ""
    echo "lua-gtk configured successfully.  Settings:"
    echo ""
    echo "   Version:              $VERSION"
    echo "   Build architecture:   $ARCH"
    echo "   C compiler:           $HOSTCC_VERSION"
    if test "$CC_VERSION"; then
    echo "   Cross compiler:       $CC_VERSION"
    fi
    if test "$CROSS_RUN"; then
    echo "   Cross run:            $CROSS_RUN"
    fi
    echo "   Runtime linking:      $DYNLINK_INFO"
    echo "   Lua version:          $LUA_VERSION"
    echo "   Gtk version:          $GTK_VERSION"
    echo "   libffi:               $LIBFFI_VERSION"
    echo "   libffi calling:       $LIBFFI_CALL"
    echo "   Cmph library:         $CMPH_VERSION"
    if test "$CMPH_INCDIR"; then
    echo "   Cmph extra includes:  $CMPH_INCDIR"
    fi
    echo "   Libgtkhtml-2.0:       $HTML_VERSION"
    echo "   Debugging symbols:    $DEBUG_INFO"
    echo "   Debugging functions:  $DEBUG_FUNCS_INFO"
    echo "   CFLAGS:               $CFLAGS"
    echo ""
    echo "Type make to build."
    echo ""
fi

# - success -
exit 0

