#!/bin/bash
#configure script adapted from Aquarius software (https://github.cxxom/devinamatthews/aquarius)
function usage
{
echo -e 'Usage: configure [options]'
echo
echo -e '\t--build-dir=dir Specify where to build object files, library, and executable (default is .)'
echo
echo -e '\t--blas=libs Specify the linker options and/or libraries needed to link'
echo -e '\t the BLAS. If not specified, common BLAS libraries will be searched for.'
echo
echo -e '\t--scalapack=libs Specify the linker options and/or libraries needed to link'
echo -e '\t the ScaLAPACK libraries. Necessary only for a couple of non-critical tests.'
echo
echo -e 'Additionally, the variables CXX, CXXFLAGS, INCLUDES, AR, NVCC, NVCCFLAGS, LDFLAGS, and WARNFLAGS'
echo -e 'can be set on the command line, e.g. ./configure CXX=g++ CXXFLAGS="-fopenmp -O2 -g".'
echo
}
PARAMS=$0
for PARAM in "$@"
do
PARAMS="${PARAMS} '${PARAM}'"
done
#Usage: 'testlink $1 $2 $3' where
# $1 - library link line
# $2 - symbol (function)
# $3 - 0 if no printouts, 1 if verbose
function testlink
{
status=1
cat > .test.cxx <<EOF
#if __cplusplus
extern "C"
#endif
void $2();
int main(){ $2(); return 0; }
EOF
if [ $3 -eq 1 ]; then
( set -x; $CXX $DEFS $WARNFLAGS $CXXFLAGS $INCLUDES .test.cxx $1 $LDFLAGS 2>&1 )
else
$CXX $DEFS $WARNFLAGS $CXXFLAGS $INCLUDES .test.cxx $1 $LDFLAGS > /dev/null 2>&1
fi
if [ -x a.out ]; then
status=0
fi
rm -f .test.cxx a.out
return $status
}
#Usage: 'testcompiler $1' where
# $1 - 0 if no printouts, 1 if verbose
function testcompiler
{
status=1
cat > .test.cxx <<EOF
int main(){ return 0; }
EOF
if [ $1 -eq 1 ]; then
( set -x; $CXX $DEFS $WARNFLAGS $INCLUDES .test.cxx 2>&1 )
else
$CXX $DEFS $WARNFLAGS $INCLUDES .test.cxx > /dev/null 2>&1
fi
if [ -x a.out ]; then
status=0
fi
rm -f .test.cxx a.out
return $status
}
#Usage: 'testcpp11 $1' where
# $1 - 0 if no printouts, 1 if verbose
function testcpp11
{
status=1
cat > .test.cxx <<EOF
#include <type_traits>
template <typename a>
class b {
public:
a s;
b(a s_){ s=s_; }
};
template <typename a>
using tb = b<a>;
int f(int k){
tb<int> r = b<int>(k);
return r.s;
}
template <typename a, bool b>
inline typename std::enable_if<b, a>::type testmin(a x, a y){
return x>y ? y : x;
}
template <typename a, bool b>
inline typename std::enable_if<!b, a>::type testmin(a x, a y){
return x;
}
int main(){ return testmin<int,1>(f(7),3)-testmin<int,0>(3,4); }
EOF
if [ $1 -eq 1 ]; then
( set -x; $CXX $DEFS $WARNFLAGS $INCLUDES .test.cxx $LDFLAGS 2>&1 )
else
$CXX $DEFS $WARNFLAGS $INCLUDES .test.cxx $LDFLAGS > /dev/null 2>&1
fi
if [ -x a.out ]; then
status=0
fi
rm -f .test.cxx a.out
return $status
}
function testopenmp
{
status=1
cat > .test.cxx <<EOF
#include "omp.h"
int main(){
int i;
int j = 0;
omp_set_num_threads(1);
#pragma omp for
for (i=0; i<10; i++){
j+=i;
}
return j;
}
EOF
$CXX $DEFS $WARNFLAGS $INCLUDES .test.cxx $LDFLAGS > /dev/null 2>&1
if [ -x a.out ]; then
status=0
fi
rm -f .test.cxx a.out
return $status
}
function realcompiler
{
echo -n 'Checking compiler type/version... '
if $CXX --version > /dev/null 2>&1; then
version=`$CXX --version 2>&1 | tr '\n' ' '`
elif $CXX -V > /dev/null 2>&1; then
version=`$CXX -V 2>&1 | tr '\n' ' '`
else
$CXX --version
$CXX -V
echo 'Could not determine underlying C/C++ compilers.'
exit 1
fi
case $version in
*Intel*)
echo 'Using Intel compilers.'
compiler=intel
;;
*Portland*)
echo 'Portland Group compilers are not supported.'
exit 1
compiler=pgi
;;
*Free\ Software*)
echo 'Using GNU compilers.'
compiler=gnu
;;
*Cray*)
echo 'Cray compilers are not supported.'
exit 1
compiler=cray
;;
*clang*)
echo 'Using Clang/LLVM compiler.'
compiler=clang
;;
*)
echo 'Could not determine underlying C/C++ compilers.'
exit 1
;;
esac
}
function defaultflags
{
#
# Set default compiler flags
#
case $compiler in
intel)
if [ "x$AR" = "x" ]; then AR='xiar'; fi
if [ "x$CXXFLAGS" = "x" ]; then CXXFLAGS='-openmp -O3 -ipo'; fi
if [ "x$NVCCFLAGS" = "x" ]; then NVCCLAGS=''; fi
if [ "x$DEFS" = "x" ]; then DEFS='-D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS'; fi
if [ "x$WARNFLAGS" = "x" ]; then WARNFLAGS='-Wall'; fi
PASS_TO_LINKER='-Wl,'
;;
gnu | clang)
if [ "x$AR" = "x" ]; then AR='ar'; fi
if [ "x$CXXFLAGS" = "x" ]; then CXXFLAGS='-fopenmp -O3'; fi
if [ "x$NVCCFLAGS" = "x" ]; then NVCCLAGS=''; fi
if [ "x$DEFS" = "x" ]; then DEFS='-D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS'; fi
if [ "x$WARNFLAGS" = "x" ]; then WARNFLAGS='-Wall'; fi
PASS_TO_LINKER='-Wl,'
;;
*)
echo 'No default flags known for given compilers. Make sure that you have set the'
echo 'appropriate compiler flags manually.'
if [ "x$AR" = "x" ]; then AR='ar'; fi
if [ "x$CXXFLAGS" = "x" ]; then CXXFLAGS='-fopenmp -O3'; fi
if [ "x$NVCCFLAGS" = "x" ]; then NVCCLAGS=''; fi
if [ "x$DEFS" = "x" ]; then DEFS='-D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS'; fi
if [ "x$WARNFLAGS" = "x" ]; then WARNFLAGS='-Wall'; fi
PASS_TO_LINKER='-Wl,'
;;
esac
}
function check_if_apple
{
status=1
cat > .test.cxx <<EOF
#if defined(__APPLE__)
#error
#endif
int main(){ return 0; }
EOF
$CXX $DEFS $WARNFLAGS $CXXFLAGS $INCLUDES .test.cxx $LDFLAGS > /dev/null 2>&1
if [ -x a.out ]; then
status=0
fi
rm -f .test.cxx a.out
return $status
}
#
# Parse command-line arguments
#
depstype=normal
while [ "x$1" != "x" ]; do
case $1 in
--build-dir=*)
eval BUILDDIR="$(printf "%q" "${1#--build-dir=}")"
;;
--blas=*)
BLASLIBS="${1#--blas=}"
;;
--scalapack=*)
SCALAPACKLIBS="${1#--scalapack=}"
;;
--help)
usage
exit 0
;;
CXX=*|\
NVCC=*|\
AR=*|\
CXXFLAGS=*|\
NVCCFLAGS=*|\
LDFLAGS=*|\
WARNFLAGS=*|\
INCLUDES=*)
eval "${1%%=*}=\"${1#*=}\""
;;
*)
echo "WARNING: Unknown option \"$1\"."
usage
exit 1
;;
esac
shift
done
CTFDIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
if [ "x$BUILDDIR" = "x" ]; then
if [ "x$CTFDIR" = `pwd` ]; then
BUILDDIR='.'
else
BUILDDIR=`pwd`
fi
fi
echo $PARAMS > $BUILDDIR/how-did-i-configure
#
# Check for known supercomputer host names
#
echo -n 'Checking hostname... '
if [ "$NERSC_HOST" = "carver" ]; then
echo 'Hostname recognized as a NERSC machine.'
host=nersc
if [ "x$BLASLIBS" = "x" ]; then
if [ "x$MKL" = "x" -o "x$MKL_ILP64" = "x" ]; then
echo 'MKL module not loaded and no alternative specified.'
echo 'Do "module load mkl" or use the --blas option.'
exit 1
fi
fi
CXX="mpiCC -std=c++0x"
realcompiler
defaultflags
DEFS="$DEFS -DCARVER"
elif [ "$NERSC_HOST" = "hopper" -o "$NERSC_HOST" = "edison" ]; then
echo 'Hostname recognized as a NERSC machine.'
host=nersc
BLASLIBS="-mkl=parallel"
CXX="CC -std=c++0x"
LDFGLAGS="-lpthread"
realcompiler
defaultflags
DEFS="$DEFS -DUSE_SP_MKL=1 -D`echo $NERSC_HOST | tr a-z A-Z`"
elif (hostname | grep 'surveyor\|intrepid\|challenger\|udawn'); then
echo 'Hostname recognized as a BG/P machine. (PLEASE USE CTF v1.1: git checkout v1.1)'
host=bgp
BLASLIBS='-lesslsmpbg -lmass -lxlfmath -lxlf90_r -lxlsmp -lxlomp_ser -lpthread'
BGP_ESSL='/soft/apps/ESSL-4.4.1-0'
LDFLAGS="-L$BGP_ESSL/lib \
-L/bgsys/ibm_compilers/sles10/prod/opt/ibmcmp/xlf/bg/11.1/bglib/ \
-L/soft/apps/ibmcmp/xlsmp/bg/1.7/bglib \
-L/soft/apps/ibmcmp/xlf/bg/11.1/bglib"
INCLUDES="-I$BGP_ESSL/include -I/bgsys/drivers/ppcfloor/arch/include"
AR='ar'
CXX=mpixlcxx_r
CXXFLAGS='-qsmp=omp -qnoipa -g -O3'
DEFS='-DBGP -D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS'
WARNFLAGS='-Wall'
elif (hostname | grep 'vesta\|mira\|cetus\|seq'); then
echo 'Hostname recognized as a BG/Q machine (note: requires +mpiwrapper-bgclang in ~/.soft).'
echo 'FOR XLC SUPPORT, WHICH PERMITS THE USE OF THREADED ESSL AND IMPROVES PERFORMANCE BY UP TO 10X, PLEASE USE CTF v1.1: git checkout v1.1).'
host=bgq
BGQ_ESSL='/soft/libraries/essl/current'
SCALAPACKLIBS=""
BLASLIBS="-L${BGQ_ESSL}/lib64 -lesslbg -L${IBM_MAIN_DIR}/xlf/bg/14.1/lib64 -lxlopt -lxlf90_r -lxlfmath -lxl -Wl,--allow-multiple-definition"
LDFLAGS=""
INCLUDES="-I$BGQ_ESSL/include"
AR='ar'
CXX=mpic++11
CXXFLAGS='-O3 -std=c++11 -DOMP_OFF'
DEFS='-DBGQ -D_POSIX_C_SOURCE=200112L -D__STDC_LIMIT_MACROS'
WARNFLAGS=''
elif (hostname | grep 'titan'); then
host=titan
CXX="CC -std=c++0x"
realcompiler
defaultflags
NVCC='nvcc -ccbin gcc -m64'
LDFLAGS='$(LDFLAGS) -lcuda -lcudart -lcublas'
else
#
# Check for other common architectures (just Linux for now)
#
host=linux
echo 'Hostname not recognized, assuming generic Linux host.'
#
# Check for compiler used by MPI
#
if [ "x$CXX" = "x" ]; then
CXX=mpicxx
fi
realcompiler
defaultflags
fi
echo -n 'Checking whether __APPLE__ is defined... '
check_if_apple;
status=$?
if [ $status = 1 ]; then
echo -n 'yes, tacking on -D_DARWIN_C_SOURCE to CXXFLAGS.'
echo
DEFS="$DEFS -D_DARWIN_C_SOURCE"
else
echo -n 'no.'
echo
fi
#
# Check that compiler works without error
#
echo -n 'Checking compiler (CXX)... '
if testcompiler 0; then
echo 'successful.'
else
echo 'FAILED! error below:'
echo
testcompiler 1
echo
exit 1
fi
#
# Check that compiler works without error
#
echo -n 'Checking availability of C++11... '
if testcpp11 0; then
echo 'successful.'
else
if [ "$NERSC_HOST" = "edison" ]; then
echo 'FAILED! error below, try using module load gcc/4.8.2:'
echo
testcpp11 1
echo
exit 1
else
CXX="$CXX -std=c++0x"
if testcpp11 0; then
echo 'successful (tacking on -std=c++0x).'
else
echo 'FAILED! error below:'
echo
testcpp11 1
echo
exit 1
fi
fi
fi
#
# Check that compiler works without error
#
echo -n 'Checking flags (CXXFLAGS)... '
ODEFS=$DEFS
DEFS="$DEFS $CXXFLAGS"
if testcompiler 0; then
echo 'successful.'
else
echo 'FAILED! error below:'
echo
testcompiler 1
echo
exit 1
fi
#
# Check if OpenMP is provided
#
echo -n 'Checking if OpenMP is provided... '
if testopenmp; then
echo 'OpenMP works.'
else
echo 'Unable to compile OpenMP test program, will build without OpenMP, to enable OpenMP please provide e.g. CXXFLAGS=-fopenmp.'
DEFS="$DEFS -DOMP_OFF"
fi
DEFS=$ODEFS
#
# Determine BLAS/LAPACK naming convention
#
echo -n 'Checking whether BLAS works... '
if testlink "$BLASLIBS" dgemm_ 0; then
UNDERSCORE=1
echo 'BLAS works, with underscores.'
else
if testlink "$BLASLIBS" dgemm 0; then
UNDERSCORE= 0
echo 'BLAS works, without underscores.'
else
if [ "x$BLASLIBS" = "x" ]; then
if [ "$compiler" = "intel" ] && testlink -mkl dgemm_ 0 ; then
UNDERSCORE=1
echo 'BLAS library was not specified, using -mkl.'
BLASLIBS=-mkl
DEFS="$DEFS -DUSE_SP_MKL=1"
elif testlink -lblas dgemm_ 0; then
UNDERSCORE=1
echo 'BLAS library was not specified, using -lblas (with underscores).'
BLASLIBS=-lblas
elif testlink -lblas dgemm 0; then
UNDERSCORE=0
echo 'BLAS library was not specified, using -lblas (without underscores).'
BLASLIBS=-lblas
else
UNDERSCORE=1
echo
echo ' WARNING: BLAS libirary was not specified, executables will not build,'
echo ' please specify correct --blas and/or LDFLAGS (run ./configure --help to see all options),'
echo ' CTF library can still build (via make).'
fi
else
UNDERSCORE=1
echo
echo ' WARNING: Unable to link with specified BLAS library, build error below:'
echo
testlink "$BLASLIBS" dgemm_ 1
echo
echo ' please specify correct --blas and/or LDFLAGS (run ./configure --help to see all options),'
echo ' CTF library can still build (via 'make'), but none of the executables will.'
fi
fi
fi
DEFS="$DEFS -DFTN_UNDERSCORE=$UNDERSCORE"
if [ $UNDERSCORE = 1 ] ; then
DGEMM=dgemm_
PDGEMM=pdgemm_
else
DGEMM=dgemm
PDGEMM=pdgemm
fi
#echo -n 'Checking whether ScaLAPACK is provided... '
#if testlink "$SCALAPACKLIBS $BLASLIBS" $PDGEMM 0; then
# echo 'SCALAPACK found.'
# DEFS="$DEFS -DUSE_SCALAPACK"
#else
# echo
# echo ' ScaLAPACK not found, a couple of the tests/benchmarks will not build, build error below:'
# echo
# testlink "$SCALAPACKLIBS $BLASLIBS" $PDGEMM 1
# echo
#fi
echo -n 'Checking whether NVCC (cuda) is provided... '
if [ "x$NVCC" = "x" ]; then
NVCC="$CXX -x c -c"
echo 'NVCC is not provided, cuda will not be used.'
else
DEFS="$DEFS -DOFFLOAD -DUSE_CUDA"
echo 'NVCC provided and cuda will be used.'
fi
mkdir -p $BUILDDIR
mkdir -p $BUILDDIR/lib
mkdir -p $BUILDDIR/obj
mkdir -p $BUILDDIR/bin
cat > $BUILDDIR/config.mk <<EOF
BLAS_LIBS = $SCALAPACKLIBS $BLASLIBS
LDFLAGS = $LDFLAGS
INCLUDES = $INCLUDES
DEFS = $DEFS
#uncomment below to enable performance profiling
#DEFS += -DPROFILE -DPMPI
#uncomment below to enable verbosity (1 for basic contraction information)
#DEFS += -DVERBOSE=1
#uncomment to set debug level and dump information about mapping and internal CTF actions
#DEFS += -DDEBUG=1
AR = $AR
CXX = $CXX
CXXFLAGS = $CXXFLAGS $WARNFLAGS
FCXX = \$(CXX) \$(CXXFLAGS) \$(DEFS) \$(INCLUDES)
LIBS = \$(BLAS_LIBS) \$(LDFLAGS)
OFFLOAD_CXX = $NVCC $NVCCFLAGS \$(DEFS) \$(INCLUDES)
EOF
if [ ! -f $BUILDDIR/include/ctf.hpp ] ; then
mkdir -p $BUILDDIR/include
echo "#include \"$CTFDIR/include/ctf.hpp\"" > $BUILDDIR/include/ctf.hpp
fi
if [ ! -e $BUILDDIR/Makefile ] ; then
cat > $BUILDDIR/Makefile <<EOF
CTFDIR=$CTFDIR
all: ctf
%:
export CTF_BUILD_DIR=$BUILDDIR; cd \$(CTFDIR); make \$@;
EOF
fi
echo 'Configure was successful.'