#!/bin/bash
#
# NOTE: This script is dual-purpose and it's behvaior is determined by the
#       name of the symlink used to invoke it!
#
# Purpose:
# Run a build for a type determined by the name of the script invoked.
# The actual name of this script is 'mk-mkd', depending on the name of
# the symlink used to invoke it, different behavior is triggered.
#   invoking 'mk' causes a production build
#            'mkd' causes a debug build
#
# This reduces overhead and potential confusion as there 
# is only one script to maintain.
#
# Arguments:
#  Command-line arguments passed to this script are handed off to the
#  gmake invocation that executes the builder generated by the
#  cmake pass immediately prior.
#  This allows for 
#        mk[mkd] clean       -to clean the build and output trees
#                             of object, library, and executables files.
#
#        mk[mkd] cleaner     -removes all bin/lib/module files in the 
#                             current project production/debug directory 
#                             tree and the upper level production/debug
#                             directory tree 
#                        
#        mk[mkd] obliterate  -removes ALL bin/lib/module files for ALL 
#                             projects in ALL production/debug directories.
#                             PLEASE USE WISELY!
#                            
#        mk[mkd] test        -Runs a build and then runs a build check or 
#                             test, if available.
#                            
# 
#---------------------------------------------------------------------------

#set -x

# Start time
DATE1=$(date +"%s")

# Just in case, re-check and reset ACC Release variable - taken from acc_vars.sh
if [ "${DIST_BUILD}" != "TRUE" ] 
then
    export ACC_TRUE_RELEASE=`readlink ${ACC_RELEASE_DIR}`
    if ( [ "${ACC_TRUE_RELEASE}" == "" ] ) then
	ACC_TRUE_RELEASE=${ACC_RELEASE}
    fi
fi

# Function to calculate and display total Compile and Link time
func_display_build_time () {
    DATE2=$(date +"%s")
    DIFF=$((${DATE2}-${DATE1}))
    if [ "${DIFF}" -gt 0 ]
	then
	DTIME=$(echo "scale = 2; ${DIFF}/60" | bc)
	DTIME_MIN=$(echo "scale = 0; ${DIFF}/60" | bc)
	DTIME_SEC=$(echo $(echo ${DTIME:(-3)})*60 | bc)
	[ "${DTIME_MIN}" != 0 ] && DTIME_MESS="${DTIME_MIN}min ${DTIME_SEC}sec" || DTIME_MESS="${DTIME_SEC}sec"
	echo -e "\n${PWD} Compile/Link time: ${DTIME_MESS}\n"
    fi
}

# Check for the type obuild requested
[ -z "${THIS_SCRIPT}" ] && THIS_SCRIPT=`basename $0` 

# Assign build type based on invoked name of script.
[ "${THIS_SCRIPT}" == "mk" ] && BUILD_TYPE="production" || BUILD_TYPE="debug"

# Determine if the current working directory is a buildable project
if [ ! -e CMakeLists.txt ] && [ ! -e acc_build ]
then
    echo -e "\nThis working directory is not a project supported by the ACC build system.\n"
    exit 1
fi

# Set the requested value for -j or just incase the gmake -j level is not set, we'll set it here, to "2".
# And grab any exe directives.
[[ ${1} = *exe* ]] && export ACC_EXE_NAME=${1}
if [[ ${1} = *j* ]]
then
    REQUESTED_GMAKE_JOBS=$(echo ${1} | cut -dj -f2)
    [ ${REQUESTED_GMAKE_JOBS} ] && export ACC_SET_GMAKE_JOBS=${REQUESTED_GMAKE_JOBS} || export ACC_SET_GMAKE_JOBS=${2}

    if ! [ "${ACC_SET_GMAKE_JOBS}" -eq "${ACC_SET_GMAKE_JOBS}" ] 2> /dev/null
    then
	export ACC_SET_GMAKE_JOBS=2
    fi

    if [[ ${2} = *exe* ]] 
    then
	export ACC_EXE_NAME=${2} 
    elif [[ ${3} = *exe* ]]
    then
	export ACC_EXE_NAME=${3}
    fi

elif [ -z ${ACC_SET_GMAKE_JOBS} ] || [ "${ACC_SET_GMAKE_JOBS}" == "0" ]
then
    export ACC_SET_GMAKE_JOBS=2
fi

# Logic to check for the presence of gmake, else use make
[ "$(type gmake &> /dev/null ; echo $?)" -eq 0 ] \
    && export GMAKE="gmake" \
    || export GMAKE="make"

# Only invoke cmake if the user has not requested a 'clean'.
case ${@} in
    clean)
	if [ -d ${BUILD_TYPE} ]
	then
	    cd ${BUILD_TYPE}
	    ${GMAKE} clean
	fi
	;;

    cleaner)
	rm -rf `pwd`/${BUILD_TYPE}
	DIR=`pwd`
	rm -rf "../config/$(basename ${DIR})"
	[ -e acc_build ] && ./acc_build -"${BUILD_TYPE}" -"${1}"
	echo -e "\nRemoved cached files.  This will force a reconfiguration upon the next build request.\n"
	;;

    obliterate)
	rm -rf `pwd`/${BUILD_TYPE}
	DIR=`pwd`
	rm -rf "../config/$(basename ${DIR})"
	cd ..
	rm -rf ${BUILD_TYPE}
	rm -rf `pwd`/*/${BUILD_TYPE}
	echo -e "\nRemoved ${BUILD_TYPE} directories in all build project directories within the current tree:\n" 
	echo -e "   "`pwd`"\n"
	;;

    *test)
	if [ -e acc_build ] 
	then 
	    ./acc_build -"${BUILD_TYPE}" -test
	    [ $? -eq 0 ] && func_display_build_time
	else
	    [ -d ${BUILD_TYPE} ] && cd ${BUILD_TYPE}
	    ctest --verbose --build-and-test
	    [ $? -eq 0 ] && func_display_build_time
	fi
	;;

    *)
	if [ -e acc_build ] 
	then 
	    ./acc_build -"${BUILD_TYPE}"
	    [ $? -eq 0 ] && func_display_build_time
	else
            # If the local out-of-source build directory does not yet exist, create it.
	    [ ! -d ${BUILD_TYPE} ] && mkdir ${BUILD_TYPE}
	    cd ${BUILD_TYPE}

	    # set the generator for cmake
	    if [[ $ACC_COMPILER_TOOLSET == mingw*-msys ]]; then
	        ACC_CMAKE_ARGS=(-G 'MSYS Makefiles')
	    else
	        ACC_CMAKE_ARGS=()
	    fi

	    cmake ${CMAKE_ARGS} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}  "${ACC_CMAKE_ARGS[@]}" .. || exit 1
	    ${GMAKE} -j ${ACC_SET_GMAKE_JOBS} ${ACC_EXE_NAME}
	    [ $? -eq 0 ] && func_display_build_time
	fi
	;;
esac

