#!/bin/sh
#
# configure script for ghdl (c) 2014 Tristan Gingold
#

backend=mcode
CC=${CC:-gcc}
CFLAGS=${CFLAGS:--g}
GNATMAKE=${GNATMAKE:-gnatmake}
LDFLAGS=
prefix=/usr/local
libdirsuffix=lib/ghdl
libdirreverse=../..
gcc_src_dir=
gcc_version=unknown
llvm_config=
backtrace_lib=
llvm_be=llvm
build=
build_mode=
EXEEXT=
SOEXT=.so
PIC_FLAGS=-fPIC

show_help=no
progname=$0

subst_vars="CC GNATMAKE CFLAGS LDFLAGS build srcdir prefix backend libdirsuffix libdirreverse gcc_src_dir llvm_config llvm_be llvm_be_ver backtrace_lib build_mode EXEEXT SOEXT PIC_FLAGS"

# Find srcdir
srcdir=`dirname $progname`
if test x$srcdir = x; then
    srcdir=.
fi

# Check echo -n / echo \c
if test x`echo -n` = x"-n" ; then
  echon=
  echoc="\c"
else
  echon="-n"
  echoc=
fi

# Read required gcc version from BUILD.txt file
gcc_version=`grep '^gcc version' $srcdir/BUILD.txt |
 sed -e 's/gcc version \([0-9.]*\) \[.*\]\.$/\1/'`

# Check $1 is a prefix of $2
check_version()
{
  exp_ver=`echo $1 | sed 's/\./v/g'`
  tool_ver=`echo $2 | sed 's/\./v/g'`
  if echo $tool_ver | grep -q "^$exp_ver"; then
      return 0
  else
      return 1
  fi
}

# Decode options
for opt do
  optarg=`expr x"$opt" : 'x[^=]*=\(.*\)'`
  case "$opt" in
      CC=*|CFLAGS=*|GNATMAKE=*)
        optvar=`expr x"$opt" : 'x\([^=]*\)=.*'`
	eval $optvar=\"$optarg\"
	;;
      --prefix=*) prefix="$optarg";;
      --srcdir=*) srcdir="$optarg";;
      --with-gcc=*) gcc_src_dir="$optarg"; backend=gcc;;
      --with-llvm=*) echo "--with-llvm is deprecated, use --with-llvm-config";
		     llvm_config="$optarg/bin/llvm-config"; backend=llvm;;
      --with-llvm-config) llvm_config="llvm-config"; backend=llvm;;
      --with-llvm-config=*) llvm_config="$optarg"; backend=llvm;;
      --with-backtrace-lib=*) backtrace_lib="$optarg";;
      --enable-coverage) build_mode="coverage";;
      -h|-help|--help) show_help=yes;;
      *) echo "$0: unknown option $opt; try $0 --help"
	  exit 1
	  ;;
  esac
done

# Help
if test $show_help != no; then
cat <<EOF
Usage: configure [options]

Options [defaults in brackets]:
  --prefix=PREFIX             install in PREFIX [$prefix]
  --srcdir=SRCDIR             source code path [$srcdir]
  --with-gcc=DIR              use gcc backend from DIR (needs gcc $gcc_version)
  --with-llvm-config=PATH     use llvm from PATH (needs llvm 3.5 - 3.9)
  --with-backtrace-lib=LIB.a  link with libbacktrace LIB.a to display a
                              backtrace on errors (only for llvm).
EOF
exit 0
fi

# Sanity checks
# Check that gnatmake exists
if ! $GNATMAKE --version >/dev/null 2>&1; then
    echo "Sorry, you need GNAT to build GHDL.  See the README"
    echo "(gnatmake executable is: $GNATMAKE)"
    exit 1
fi

# Check that compiler exists
if ! $CC -v 2> /dev/null; then
    echo "Sorry, you need a C compiler to build GHDL.  See the README"
    exit 1
fi

# Compute build machine
if test x$build = x; then
    build=`$CC $CFLAGS -dumpmachine`
fi
echo "Build machine is: $build"

# For mcode, check that gcc emits i386
if test $backend = mcode; then
    gcc_machine=`$CC $CFLAGS -dumpmachine`
    case "$gcc_machine" in
	i[3-6]86*) mcode64="" ;;
	x86_64*) mcode64="64" ;;
	*)
	  mcode64=""
	  echo "WARNING: GHDL for mcode is supported only on x86"
	  echo "continuing, but build failure expected (See the README)"
	  ;;
    esac
    if test "x$backtrace_lib" != x ; then
	echo "WARNING: --with-backtrace-lib= ignored with mcode"
	backtrace_lib=
    fi
fi

# For gcc backend, check version
if test $backend = gcc; then
    if ! test -f $gcc_src_dir/gcc/BASE-VER; then
	echo "cannot find gcc/BASE-VER in $gcc_src_dir"
	exit 1
    fi
    base_ver=`cat $gcc_src_dir/gcc/BASE-VER`
    if ! check_version $gcc_version $base_ver; then
	echo "Mismatch gcc version from $gcc_src_dir"
	echo "Need gcc version $gcc_version"
	exit 1
    fi
    if test "x$backtrace_lib" = x ; then
	# Automatically use libbacktrace from gcc.
	backtrace_lib="$prefix/$libdirsuffix/libbacktrace.a"
    fi
fi

# For llvm backend, check llvm-config
if test $backend = llvm; then
    llvm_version=`"$llvm_config" --version 2>/dev/null`
    if [ $? != 0 ]; then
	echo "cannot run $llvm_config"
	exit 1
    fi
    if check_version 3.5 $llvm_version; then
	llvm_be=llvm
    elif check_version 3.6 $llvm_version || 
	 check_version 3.7 $llvm_version ||
         check_version 3.8 $llvm_version;
    then
	echo "Debugging is not enabled with llvm $llvm_version"
	llvm_be=llvm-nodebug
	# Tested with llvm 3.5, so assume 3.6, 3.7 and 3.8
	llvm_be_ver=35
    elif check_version 3.9 $llvm_version; then
	echo "Debugging is not enabled with llvm $llvm_version"
	llvm_be=llvm-nodebug
	llvm_be_ver=39
    else
	echo "Unhandled version llvm $llvm_version"
	exit 1
    fi
    # For llvm, the c++ compiler is used for linking so that the standard c++
    # library is included.  However, the linker needs the no_compact_unwind
    # flag because code generated by gcc is not compatible with compact unwind.
    case "$build" in
	*darwin*) LDFLAGS="$LDFLAGS -Wl,-no_compact_unwind" ;;
    esac
fi

# Define default file extensions for Windows or Linux-like systems and
# use -fPIC or not.
case "$build" in
    *mingw*)  SOEXT=".dll";   EXEEXT=".exe"; PIC_FLAGS="";;
    *darwin*) SOEXT=".dylib"; EXEEXT="";     PIC_FLAGS="";;
    *)        SOEXT=".so";    EXEEXT="";     PIC_FLAGS="-fPIC";;
esac

# Generate config.status
rm -f config.status
{
echo "#! /bin/sh"
echo "# Generated by configure."
echo "# Run this file to recreate the current configuration."
echo
echo "# Generated by:"
echo $echon "# $progname"$echoc
for opt do
  echo $echon \ \"$opt\"$echoc
done
echo
echo
echo subst_vars=\"$subst_vars\"
for v in $subst_vars; do
    eval vval=\$$v
    echo $v=\"$vval\"
done
sed_opts=`echo $subst_vars | sed -e "s/\\([a-zA-Z_]*\\)/ -e \"s%@\1@%\$\1%g\"/g"`
echo 'echo "Creating ghdl.gpr"'
echo sed $sed_opts '< $srcdir/ghdl.gpr.in > ghdl.gpr'
echo 'echo "Creating Makefile"'
echo sed $sed_opts '< $srcdir/Makefile.in > Makefile'
} > config.status || \
{
  echo "$progname: cannot create config.status"
  exit 1
}

chmod +x ./config.status

# Run config.status to generate files
if ! sh ./config.status; then
    echo "$progname: cannot execute config.status"
    exit 1
fi

# Generate ortho_code-x86-flags
if test $backend = mcode; then
    case "$build" in
	*darwin*) ortho_flags="Flags_Macosx${mcode64}" ;;
	*mingw32*) ortho_flags="Flags_Windows${mcode64}" ;;
	*linux*) ortho_flags="Flags_Linux${mcode64}" ;;
	*) echo "Unsupported $build build for mcode"; exit 1;;
    esac
    echo "Generate ortho_code-x86-flags.ads"
    {
     echo "with Ortho_Code.X86.$ortho_flags;"
     echo "package Ortho_Code.X86.Flags renames Ortho_Code.X86.$ortho_flags;"
    } > ortho_code-x86-flags.ads
    echo "Generate elf_arch.ads"
    {
	echo "with Elf_Arch${mcode64:-32};"
	echo "package Elf_Arch renames Elf_Arch${mcode64:-32};"
    } > elf_arch.ads
fi

# Generate default_pathes.ads
# Also update dist/mcode/windows/default_pathes.ads if you change this
# template.
echo "Generate default_pathes.ads"
curdir=`pwd`
sed -e "s%@COMPILER_GCC@%ghdl1-gcc$EXEEXT%" \
    -e "s%@COMPILER_DEBUG@%ghdl1-debug$EXEEXT%" \
    -e "s%@COMPILER_MCODE@%ghdl1-mcode$EXEEXT%" \
    -e "s%@COMPILER_LLVM@%bin/ghdl1-llvm$EXEEXT%" \
    -e "s%@POST_PROCESSOR@%oread-$backend%" \
    -e "s%@INSTALL_PREFIX@%$prefix%" \
    -e "s%@LIB_PREFIX@%$libdirsuffix%" \
    -e "s%@SOEXT@%$SOEXT%" \
    < $srcdir/src/ghdldrv/default_pathes.ads.in > default_pathes.ads

exit 0