#!/bin/sh

#set -o errexit
#set -v

#wwwHome=openmx.ssri.psu.edu/software
wwwHome=vipbg.vcu.edu/vipbg/OpenMx2/software

isdef() {
    tmp1=/tmp/openmx.$$.cpp
    tmp2=/tmp/openmx.$$.out
    trap 'rm -f $tmp1 $tmp2' EXIT
    cat >$tmp1 <<EOF
int main()
{
#ifndef $1
crash me
#endif
	; return 0;
}
EOF
    $CXX -c $tmp1 -o $tmp2 > /dev/null 2>&1
}

# in case sort doesn't know about -V
if test "$(echo 1 | sort -V 2>/dev/null)" = 1; then
  version_gt() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }
  version_le() { test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" = "$1"; }
  version_lt() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" != "$1"; }
  version_ge() { test "$(echo "$@" | tr " " "\n" | sort -rV | head -n 1)" = "$1"; }
else
  version_gt() { false; }
  version_le() { false; }
  version_lt() { false; }
  version_ge() { false; }
fi

: ${R_HOME:=`R RHOME`}
if test -z "${R_HOME}"; then
   echo "could not determine R_HOME"
   exit 1
fi

devmode=0
if [ -f .devmode ]; then
    echo "NOTE: ./.devmode exists; will enable extra compiler diagnostics"
    devmode=1
fi

REXEC=${R_HOME}/bin/R

echo 'NOTE: ./configure is not an autoconf generated script.'
echo 'Change default C/C++ compiler and default compile flags by editing ~/.R/Makevars'

CXX=`$REXEC CMD config CXX`

if isdef __clang__; then
    cxx_type=clang
elif isdef __llvm__; then
    cxx_type=llvm
elif isdef __GNUC__; then
    cxx_type=gcc
else
    echo "Compiler '$CXX' unrecognized; using defaults"
fi

min_gcc_version=4.9.3
if [ "$cxx_type" = gcc ]; then
    cxx_version=`$CXX -dumpfullversion -dumpversion | awk -F '.' '{print $1 "." $2}'`
		#echo "gcc -> $cxx_version"
    if version_lt $cxx_version $min_gcc_version; then
	echo "Your version of gcc ($cxx_version) is too old to compile OpenMx. You need at least version $min_gcc_version"
	exit 1
    fi
    if [ $devmode = 1 ]; then
	COMPILER_CXXFLAGS="-Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-local-typedefs -Wno-deprecated-declarations -Wno-unused-function -Wno-unused-variable"

	if version_ge $cxx_version 5.0; then
	    COMPILER_CXXFLAGS="$COMPILER_CXXFLAGS -fdiagnostics-color=auto -DEXTRA_GCC_DIAG -Wno-misleading-indentation -Wno-pragmas -Wno-ignored-attributes"
	    COMPILER_LDFLAGS="$COMPILER_LDFLAGS"
	    xcheck_CXXFLAGS="-fsanitize=undefined"
	    xcheck_LDFLAGS="-fsanitize=undefined"
	fi
	if version_ge $cxx_version 6.0; then
    # cannot -Wsuggest-override until Rcpp is cleaned up TODO
	    COMPILER_CXXFLAGS="$COMPILER_CXXFLAGS -Wno-misleading-indentation -Wreorder"
	fi
	if version_ge $cxx_version 7.0; then
	    COMPILER_CXXFLAGS="$COMPILER_CXXFLAGS -Wno-int-in-bool-context"
	fi
	if version_ge $cxx_version 8.0; then
	    COMPILER_CXXFLAGS="$COMPILER_CXXFLAGS -Wclass-memaccess"
	fi
	if version_ge $cxx_version 9.0; then
	    # As of RcppEigen 0.3.3.5.0, there is some problem with the
	    # definition of Eigen::Ref. Try to re-enable this warning
	    # in a year.
	    COMPILER_CXXFLAGS="$COMPILER_CXXFLAGS -Wno-deprecated-copy"
	    :
	fi
    fi
fi

if [ ! -f inst/no-npsol ] && [ -r inst/npsol/checksum ]; then
    host_cpu=`uname -p`
    if [ "x$host_cpu" = xunknown ]; then
	# tanglu 1 has the machine architecture here
	host_cpu=`uname -m`
    fi
    case "$host_cpu" in
	*86_64) omx_arch=x86_64 ;;
	*86) omx_arch=x86 ;;
	*arm) omx_arch=arm64 ;;
	*)
	    echo "Host arch is not recognized: ${host_cpu}"
	    exit 1
	    ;;
    esac

    os=`uname -s`
    case "$os" in
	*Linux)
	    omx_os=linux
	    pick="linux/${omx_arch}/gcc${cxx_version}"
	    want=`grep "$pick" inst/npsol/checksum | cut -f1 -d' ' | head -1`
	    npsol_url1="http://$wwwHome/packages/npsol/linux/${omx_arch}/$want"
	    npsol_url2="http://$wwwHome/packages/npsol/$pick/libnpsol.a"
	    if [ ! -f src/libnpsol.a ]; then
		wget -O src/libnpsol.a "$npsol_url1" || true
		if grep -s 'HTML document' src/libnpsol.a; then
		    wget -O src/libnpsol.a "$npsol_url2" || true
		fi
	    fi
	    got=`sha1sum src/libnpsol.a | cut -f1 -d' '`
	    if [ "x$want" = x ]; then
		echo "************ ************"
		echo "WARNING: Cannot verify correct libnpsol.a version"
		echo "sha1sum libnpsol.a => $got"
		echo "************ ************"
		npsol_library="src"
	    elif [ "x$got" != "x$want" ]; then
		echo "************ ************"
		echo "Remove src/libnpsol.a with sha1sum $got"
		echo "Please download $npsol_url1 and rename it to src/libnpsol.a"
		echo "************ ************"
		npsol_library="src" # comment next line if testing
		exit 1
	    else
		echo "sha1sum libnpsol.a => $got   # GOOD"
		npsol_library="src"
	    fi
	    ;;
	*Darwin)
	    omx_os=osx
	    npsol_library="inst/npsol/osx/x86_64"
	    if [ $omx_arch = "arm64" ]; then
		npsol_library="inst/npsol/osx/arm64"
	    fi
	    ;;
	*)
	    echo "Host os is not recognized: $os"
	    exit 1
	    ;;
    esac
fi

echo "### Generated from Makevars.in" > src/Makevars.new
echo >> src/Makevars.new

if [ ! -f inst/no-npsol ] && [ -n "${npsol_library+1}" ]; then
    npsol_file="${npsol_library}/libnpsol.a"
    if [ ! -f "$npsol_file" ]; then
	echo "$npsol_file not found"
	exit 1
    else
	echo "NPSOL_LDFLAGS=-L../${npsol_library} -lnpsol" >> src/Makevars.new
    fi
fi

# if [ `$REXEC --slave --vanilla -e 'cat(suppressWarnings(require("nloptr", quietly=TRUE)) && packageVersion("nloptr") >= "1.0.5")'` = TRUE ]; then
#   echo "
# NLOPT_CXXFLAGS=`$REXEC --slave --vanilla -e 'suppressPackageStartupMessages(require(nloptr)); cat("-DHAS_NLOPT", nloptr:::CFlags())'`
# NLOPT_LDFLAGS=`$REXEC  --slave --vanilla -e 'suppressPackageStartupMessages(require(nloptr)); cat(nloptr:::LdFlags())'`
# " >> src/Makevars.new
# fi

if [ "${OPENMP-yes}" = yes ]; then
    OPENMP_CXXFLAGS='$(SHLIB_OPENMP_CXXFLAGS)'
fi

echo "ARCH_SPECIFIC_LINKER_FLAGS=$arch_LDFLAGS" >> src/Makevars.new
echo "ARCH_SPECIFIC_COMPILER_FLAGS=$arch_CXXFLAGS" >> src/Makevars.new
echo "COMPILER_CXXFLAGS=$COMPILER_CXXFLAGS" >> src/Makevars.new
echo "COMPILER_LDFLAGS=$COMPILER_LDFLAGS" >> src/Makevars.new
echo "OPENMP_CXXFLAGS=$OPENMP_CXXFLAGS" >> src/Makevars.new
echo "xcheck_CXXFLAGS=$xcheck_CXXFLAGS" >> src/Makevars.new
echo "xcheck_LDFLAGS=$xcheck_LDFLAGS" >> src/Makevars.new

# check for special environment variables
if [ "x$IMX_SAFE" = x1 ]; then
    echo 'DEBUG_CXXFLAGS=$(xcheck_CXXFLAGS) -UNDEBUG -DOMX_BOUNDS_CHECK -D_GLIBCXX_DEBUG' >> src/Makevars.new
    echo 'DEBUG_LDFLAGS=$(xcheck_LDFLAGS)' >> src/Makevars.new
elif [ "x$IMX_GCOV" = x1 ]; then
    # To collect gcov statistics (gcc only)
    echo 'DEBUG_CXXFLAGS=--coverage' >> src/Makevars.new
    echo 'DEBUG_LDFLAGS=--coverage' >> src/Makevars.new
fi

echo >> src/Makevars.new
echo "# ---- appending Makevars.in ----" >> src/Makevars.new
echo >> src/Makevars.new
cat src/Makevars.in >> src/Makevars.new

if [ -f src/Makevars ] && cmp -s src/Makevars src/Makevars.new; then
    echo "src/Makevars unchanged"
    rm -f src/Makevars.new
else
    mv src/Makevars.new src/Makevars
fi
