#!/usr/bin/env bash

set -e

#
# parameters
#

source $(dirname $0)/openblas.rc

declare product=openblas
declare version=${openblas_ver}
if [[ -n "$builddir" ]]
then
    declare topdir="$builddir/build-openblas"
else
    declare topdir="/dev/shm/build-openblas"
fi

[[ -e ${topdir} ]] || mkdir -p ${topdir}
cd ${topdir}

#
# build binutils
#
# To build OpenBLAS, we need the latest binutils.
# We don't have to prepare the binutils before GCC.
# If we just prepend the binutils' path to PATH, it gets effective.

[[ -e binutils-${binutils_ver} ]] ||
    curl -A \
        "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.2; rv:11.0) like Gecko" \
    -L \
        http://ftp.gnu.org/gnu/binutils/binutils-${binutils_ver}.tar.bz2 \
    | tar -xjf -


mkdir -p build
cd build
../binutils-${binutils_ver}/configure \
    --prefix="${topdir}/binutils"
make -j MAKEINFO=echo
make MAKEINFO=echo install

cd "${topdir}"
export PATH="${topdir}/binutils/bin:$PATH"

#
# build OpenBLAS
#

#
# Download source
#
[[ -e "$(dirname */cblas.h)" ]] ||
    curl -A \
        "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.2; rv:11.0) like Gecko" \
    -L \
        http://github.com/xianyi/OpenBLAS/tarball/v${version} \
    | tar xzvf -

product_dir=$(eups path 0)/$(eups flavor)/${product}/${version}
cd "$(dirname */cblas.h)"

#
# build
#

# NUM_THREADS means max.number of threads that will be created by OpenBLAS.
# The number can be large: actual number of threads created will also be
# limited by the number of cores available. You might fancy that NUM_THREADS
# should be infinity: that is impossible. In thread-creating functions,
# OpenBLAS stores thread information in arrays of length NUM_THREADS. The
# arrays are on the stack. The functions consume about 300 bytes of the stack
# per thread. If you set NUM_THREADS=16777216, for example, the library
# probably stops working because of stack exhaustion.
#
# If you need MKL_ILP64 compatible library, use INTERFACE64=1
#
make -j PREFIX=$product_dir NO_STATIC=1 DYNAMIC_ARCH=1 NO_AFFINITY=1 NUM_THREADS=64 BINARY=64 CC=gcc FC=gfortran
make    PREFIX=$product_dir NO_STATIC=1 DYNAMIC_ARCH=1 NO_AFFINITY=1 NUM_THREADS=64 BINARY=64 CC=gcc FC=gfortran install

mkdir -p $product_dir/ups

#
# Put config file
#

cat > $product_dir/ups/${product}.cfg << "EOF"
import lsst.sconsUtils
dependencies = {
    "required": [],
}
config = lsst.sconsUtils.ExternalConfiguration(
    __file__,
    headers=["cblas.h"],
    libs=["openblas"],
)
EOF

#
# Put table file
#

cat > $product_dir/ups/${product}.table << "EOF"
setupOptional(gcc)
envPrepend(LD_LIBRARY_PATH, ${PRODUCT_DIR}/lib)
EOF

eups declare -r $product_dir ${product} ${version}

cd ~
rm -rf ${topdir}
