#! /bin/sh
# Build and Test HDF5 using cmake.
# Author: Allen Byrne
#         Albert Cheng
# Creation Date: Nov 2012
# Modified:
#	Changed to use the quick steps described in INSTALL_CMake.txt. (AKC 2014/1/1)

# Copyright: The HDF Group, 2012-14

# Debug Print: remove the comment hash if you want DPRINT to do echo
DPRINT=:
#DPRINT=echo

# variable names
# The "extra" number is the step number and easier to see all logfiles in
# the sorted order of steps
progname=`basename $0`	# program name
configlog="#${progname}_1config.log"
makelog="#${progname}_2build.log"
testlog="#${progname}_3test.log"
packlog="#${progname}_4pack.log"
installlog="#${progname}_5install.log"
vflag=1		# verbose flag default to on.
config_summary=libhdf5.settings
exit_code=0

# This command should be in the source directory's bin/
# and should have invoked as "$srcdir/bin/$progname" or
# "bin/$progname". So, by striping bin/$program from $0,
# we can find $srcdir.
if [ "$0" = "bin/${progname}" ]; then
    srcdir="."		# current directory
else
    # $0 is $srdir/bin/$progname
    srcdir=`echo $0 | sed -e s%/bin/$progname\$%%`
fi
# Sanity check
if [ ! -r $srcdir/bin/$progname ]; then
    echo "encountered error while trying to find srcdir($srdir)"
    exit 1
fi

# Cmake build options
cacheinit=$srcdir/config/cmake/cacheinit.cmake
build_cpp_lib=-DHDF5_BUILD_CPP_LIB:BOOL=OFF	# C++ interface default off
build_fortran=-DHDF5_BUILD_FORTRAN:BOOL=OFF	# Fortran interface default off
build_hl_lib=-DHDF5_BUILD_HL_LIB:BOOL=ON	# High Level interface default on
build_threadsafe=-DHDF5_ENABLE_THREADSAFE:BOOL=OFF	# Threadsafe feature default off
build_testing=-DBUILD_TESTING:BOOL=ON		# Build tests default on
build_tools=-DHDF5_BUILD_TOOLS:BOOL=ON		# Build tools default on
with_zlib=-DHDF5_ENABLE_Z_LIB_SUPPORT=ON	# enable zlib filter default on
with_szlib=-DHDF5_ENABLE_SZIP_SUPPORT=OFF	# enables szip filter default off
szlib_path=""					# szip lib path default off
shared_lib=-DBUILD_SHARED_LIBS:BOOL=ON		# enables shared lib; default on
njobs=""					# number of jobs (commands) to
						# run simultaneously; default is
						# value from $MAKE if defined,
						# otherwise none (1)

#=============
# Function definitions
#=============

# Show user brief help page
HELP_BRIEF()
{
cat << EOF
Usage: $progname [options]
  --help: shows details help page
EOF
}

# Show user detail help page
HELP()
{
cat << EOF
Usage: $progname [<options>]
  where options are:
  --enable-fortran | --disable-fortran:
    enable or disable fortran API. Default is off.
  --enable-cxx | --disable-cxx:
    enable or disable c++ API. Default is off.
  --enable-hl | --disable-hl:
    enable or disable high level API. Default is on.
  --enable-threadsafe | --disable-threadsafe:
    enable or disable threadsafe feature. Default is off
  --enable-shared | --disable-shared:
    enable or disable shared lib. Default is on.
  --enable-tools | --disable-tools:
    enable or disable building tools. Default is on.
  --enable-testing | --disable-testing:
    enable or disable building tests. Default is on.
  --with-zlib | --with-zlib=<libpath> | --without-zlib:
    Use zlib library for external deflate I/O filter. Default is on.
  --with-szlib | --with-szlib=<libpath> | --without-szlib:
    Use szlib library for external deflate I/O filter. Default is on.
  --njobs=<-j N>:
    number of jobs (commands) to run simultaneously; default is value from
    $MAKE if defined, otherwise none
  --enable-verbose | --disable-verbose:
    enable or disable verbose output. Default is on.
  --help: shows details help page

  <libpath>: the file path to the library, expect <libpath>/lib and <libpath>/include.
EOF
}

# Display a time stamp
TIMESTAMP()
{
    echo "=====" "`date`" "====="
}


# Do one step bracketed with time stamps
# The '< /dev/null' is needed to prevent some applications like MPI
# jobs blocked for reading when they read stdin unnecessary.
# $1 is banner message to be displayed.
# $2 is command to run
# $3 is logfile name for saving output from the command
STEP()
{
    banner="$1"
    command="$2"
    logfile="$3"

    echo "$banner" with output saved in $logfile
    (TIMESTAMP; nerror=0 ;
	echo "eval $command"
	eval $command || nerror=1 ;
	TIMESTAMP; exit $nerror) < /dev/null > "$logfile" 2>&1
    if [ $? -ne 0 ]; then
	echo "error in '$banner'.  $progname aborted."
	exit 1
    fi
}


# Install the generated installation image file.  Different platform uses
# different image files.
# Linux: HDF5-<version>-Linux.sh file
# Mac OS X: Not implemented yet
# Others: Not implemented yet
INSTALL_HDF5()
{
    myos="`uname -s`"
    case "$myos" in
	Linux)
	    install_file=./HDF5-${version}-Linux.sh
	    $install_file  --skip-license $*
	    ;;
	Darwin)		# Mac OSX DMG file
	    # These steps were a kludge. Need proper support from Cmake engineering.
	    echo Darwin install step needs proper implementation. Quit.
	    return 1
	    #
	    install_file=HDF5-${version}-Darwin.dmg
	    test -d hdf5 || mkdir hdf5
	    basename=`basename $install_file .dmg`
	    # mount the DMG file as /Volumes/$basename
	    # echo 'Y' as yes for license.
	    echo Y | hdiutil mount $install_file
	    # copy the contents to the install location
	    cp -R "/Volumes/$basename/HDF_Group" hdf5
	    # unmount the DMG file
	    hdiutil unmount /Volumes/$basename
	    ;;
	*) 		# unknown/unsupported OS.
	    echo "INSTALL_HDF5: Error--unknown/unsupported OS($myos)"
	    return 1
	    ;;
    esac
}


# Print logfiles.
# $*: logfiles
DUMP_LOGFILE()
{
    for x in $*; do
	if [ -f $x ]; then
	    echo "=================================="
	    echo "Dumping $x"
	    echo "=================================="
	    cat $x
	    echo "==== END $x ====="
	    echo
	fi
    done
}


#==========
# main
#==========

# Show a start time stamp
TIMESTAMP

# Initialize njobs if $AMKE is defined
if [ -n "$MAKE" ]; then
    # assume all arguments are for --jobs
    njobs=`echo $MAKE | cut -s -d' ' -f2-`
fi

# Parse Cmake configure options
# --enable-XXX or --disable-XXX will enable or disable feature XXX.
# XXX can be:
# fortran	Fortran interface
# cxx		C++ interface
# hl		Highlevel interface
# testing	Build tests
# tools		Build tools
while [ $# -gt 0 ]; do
    case "$1" in
	--enable-fortran)
	    build_fortran=-DHDF5_BUILD_FORTRAN:BOOL=ON
	    ;;
	--disable-fortran)
	    build_fortran=-DHDF5_BUILD_FORTRAN:BOOL=OFF
	    ;;
	--enable-cxx)
	    build_cpp_lib=-DHDF5_BUILD_CPP_LIB:BOOL=ON
	    ;;
	--disable-cxx)
	    build_cpp_lib=-DHDF5_BUILD_CPP_LIB:BOOL=OFF
	    ;;
	--enable-hl)
	    build_hl_lib=-DHDF5_BUILD_HL_LIB:BOOL=ON
	    ;;
	--disable-hl)
	    build_hl_lib=-DHDF5_BUILD_HL_LIB:BOOL=OFF
	    ;;
	--enable-threadsafe)
	    build_threadsafe=-DHDF5_ENABLE_THREADSAFE:BOOL=ON
	    ;;
	--disable-threadsafe)
	    build_threadsafe=-DHDF5_ENABLE_THREADSAFE:BOOL=OFF
	    ;;
	--enable-shared)
	    shared_lib=-DBUILD_SHARED_LIBS:BOOL=ON
	    ;;
	--disable-shared)
	    shared_lib=-DBUILD_SHARED_LIBS:BOOL=OFF
	    ;;
	--enable-tools)
	    build_tools=-DHDF5_BUILD_TOOLS:BOOL=ON
	    ;;
	--disable-tools)
	    build_tools=-DHDF5_BUILD_TOOLS:BOOL=OFF
	    ;;
	--enable-testing)
	    build_testing=-DBUILD_TESTING:BOOL=ON
	    ;;
	--disable-testing)
	    build_testing=-DBUILD_TESTING:BOOL=OFF
	    ;;
	--with-zlib)
	    with_zlib=-DHDF5_ENABLE_Z_LIB_SUPPORT:BOOL=ON
	    ;;
	--with-zlib=*)
	    xarg=`echo $1 | cut -d= -f2-`
	    with_zlib="-DHDF5_ENABLE_Z_LIB_SUPPORT:BOOL=ON -DZLIB_ROOT=$xarg"
	    ;;
	--without-zlib)
	    with_zlib=-DHDF5_ENABLE_Z_LIB_SUPPORT:BOOL=OFF
	    ;;
	--with-szlib)
	    with_szlib=-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=ON
	    szlib_path=""	# szlib is in default paths
	    ;;
	--with-szlib=*)
	    xarg=`echo $1 | cut -d= -f2-`
	    with_szlib="-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=ON"
	    szlib_path="SZIP_INSTALL=$xarg"
	    ;;
	--without-szlib)
	    with_szlib=-DHDF5_ENABLE_SZIP_SUPPORT:BOOL=OFF
	    szlib_path=""	# reset the path
	    ;;
	--njobs=*)
	    njobs=`echo $1 | cut -d= -f2-`
	    ;;
	--enable-verbose)
	    vflag=1
	    ;;
	--disable-verbose)
	    vflag=0
	    ;;
	--help)
	    # print the detail help page and exit
	    HELP
	    exit 0
	    ;;
	*)
	    echo "Unknown options: $1"
	    HELP
	    exit 1
	    ;;
    esac
    shift
done
$DPRINT after option parsing vflag=$vflag

# Always display the brief help page
HELP_BRIEF

# Verify there is a valid hdf5 source directory present
if [ ! -d $srcdir ]; then
    echo $srcdir not found. Aborted.
    exit 1
fi

# figure out version information
vers=bin/h5vers
if [ ! -x $srcdir/$vers ]; then
    echo $srcdir/$vers not found or not executable. Aborted.
    exit 1
fi
version=`cd $srcdir; $vers`
if [ $? != 0 ]; then
    echo $vers failed. Aborted.
    exit 1
fi

# setup output of all the log files if verbose is on upon exit
trap \
    "if [ $vflag -ne 0 ]; then DUMP_LOGFILE \$configlog \$makelog \$testlog \$packlog \$installlog; fi" \
    0

echo Running Cmake for HDF5-${version} ...
#      4. Configure the C library, tools and tests with this command:
#         If successful, append the configure summary to the configure logfile.
STEP "Configure..." \
   "env ${szlib_path} \
    cmake \
    -C $cacheinit \
    $build_cpp_lib \
    $build_fortran \
    $build_hl_lib \
    $build_threadsafe \
    $shared_lib \
    $build_testing \
    $build_tools \
    $with_zlib \
    $with_szlib \
    $srcdir" $configlog &&\
    cat $config_summary >> $configlog

#      5. Build the C library, tools and tests with this command:
STEP "Build the library, tools and tests, ..." "cmake --build . --config Release -- $njobs" $makelog

#      6. Test the C library and tools with this command:
STEP "Test the library and tools..." "ctest . -C Release $njobs" $testlog

#      7. Create an install image with this command:
STEP "Create an install image..." "cpack -C Release CPackConfig.cmake" $packlog

# The implementation of installation is imcomplete (only works for linux).
# Screen it out for now till it is completed.
if false; then
#      8. Install with this command:
STEP "Install..." "INSTALL_HDF5" $installlog
fi

# save the last exit code
exit_code=$?

# Show a closing time stamp
TIMESTAMP
exit $exit_code
