mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-26 13:15:21 -04:00
748 lines
23 KiB
Bash
748 lines
23 KiB
Bash
# A set of tools used in the toolchain installer, intended to be used
|
|
# by sourcing this file inside other scripts.
|
|
|
|
# TODO: Review and if possible fix shellcheck errors.
|
|
# shellcheck disable=all
|
|
# shellcheck shell=bash
|
|
|
|
SYS_INCLUDE_PATH=${SYS_INCLUDE_PATH:-"/usr/local/include:/usr/include"}
|
|
SYS_LIB_PATH=${SYS_LIB_PATH:-"/usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/aarch64-linux-gnu:/lib64:/lib"}
|
|
INCLUDE_PATHS=${INCLUDE_PATHS:-"CPATH SYS_INCLUDE_PATH"}
|
|
LIB_PATHS=${LIB_PATHS:-"LIBRARY_PATH LD_LIBRARY_PATH LD_RUN_PATH SYS_LIB_PATH"}
|
|
time_start=$(date +%s)
|
|
|
|
# report timing
|
|
report_timing() {
|
|
time_stop=$(date +%s)
|
|
printf "Step %s took %0.2f seconds.\n" "$1" $((time_stop - time_start))
|
|
}
|
|
|
|
# report a warning message with script name and line number
|
|
report_warning() {
|
|
if [ $# -gt 1 ]; then
|
|
local __lineno=", line $1"
|
|
local __message="$2"
|
|
else
|
|
local __lineno=''
|
|
local __message="$1"
|
|
fi
|
|
echo "WARNING: (${SCRIPT_NAME}${__lineno}) $__message" >&2
|
|
}
|
|
|
|
# report an error message with script name and line number
|
|
report_error() {
|
|
if [ $# -gt 1 ]; then
|
|
local __lineno=", line $1"
|
|
local __message="$2"
|
|
else
|
|
local __lineno=''
|
|
local __message="$1"
|
|
fi
|
|
echo "ERROR: (${SCRIPT_NAME}${__lineno}) $__message" >&2
|
|
return 1
|
|
}
|
|
|
|
# error handler for line trap from set -e
|
|
error_handler() {
|
|
report_error "$1" "Non-zero exit code detected."
|
|
}
|
|
|
|
# source a file if it exists, otherwise do nothing
|
|
load() {
|
|
if [ -f "$1" ]; then
|
|
source "$1"
|
|
fi
|
|
}
|
|
|
|
# Take excerpt of ${LOG_LINES} lines from tail of a file, always reporting
|
|
# its absolute path at the top, and then exit with non-zero code
|
|
tail_excerpt() {
|
|
local __filename=$(real_path "$1")
|
|
if [ -n "${LOG_LINES}" ]; then
|
|
local __lines="${LOG_LINES}"
|
|
elif [ $# -gt 1 ]; then
|
|
local __lines="$2"
|
|
fi
|
|
tail -v -n "${__lines}" "${__filename}"
|
|
exit 1
|
|
}
|
|
|
|
# A more portable command that will give the full path, removing
|
|
# symlinks, of a given path. This is more portable than readlink -f
|
|
# which does not work on Mac OS X
|
|
# Former name is "realpath", renamed to avoid accidentally overriding
|
|
# the native GNU coreutils command when this script is sourced
|
|
# https://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html
|
|
real_path() {
|
|
local __path="$1"
|
|
if [ "x$__path" = x ]; then
|
|
return 0
|
|
fi
|
|
local __basename=$(basename "$__path")
|
|
if [ -e "$__path" ]; then
|
|
echo $(
|
|
cd "$(dirname "$__path")"
|
|
pwd -P
|
|
)/"$__basename"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# given a list, outputs a list with duplicated items filtered out
|
|
unique() (
|
|
# given a list, outputs a list with duplicated items filtered out.
|
|
# If -d <delimiter> option exists, then output the list delimited
|
|
# by <delimiter>; note that this option does not effect the input.
|
|
local __result=''
|
|
local __delimiter=' '
|
|
local __item=''
|
|
if [ "$1" = "-d" ]; then
|
|
shift
|
|
__delimiter="$1"
|
|
shift
|
|
fi
|
|
# It is essential that we quote $@, which makes it equivalent to
|
|
# "$1" "$2" ... So this works if any of the arguments contains
|
|
# space. And we use \n to separate the fields in the
|
|
# __result for now, so that fields that contain spaces are
|
|
# correctly grepped.
|
|
for __item in "$@"; do
|
|
if [ x"$__result" = x ]; then
|
|
__result="${__item}"
|
|
# Note that quoting $__result after echo is essential to
|
|
# retain the \n in the variable from the output of echo. Also
|
|
# remember grep only works on a line by line basis, so if
|
|
# items are delimited by newlines, then for grep search it
|
|
# should be delimited by ^ and $ (beginning and end of line)
|
|
elif ! (echo "$__result" |
|
|
grep -s -q -e "^$__item\$"); then
|
|
__result="${__result}
|
|
${__item}"
|
|
fi
|
|
done
|
|
__result="$(echo "$__result" | paste -s -d "$__delimiter" -)"
|
|
# quoting $__result below is again essential for correct
|
|
# behaviour if IFS is set to be the same $__delimiter in the
|
|
# parent shell calling this macro
|
|
echo "$__result"
|
|
)
|
|
|
|
# reverse a list
|
|
reverse() (
|
|
# given a list, output a list with reversed order. If -d
|
|
# <delimiter> option exists, then output the list delimited by
|
|
# <delimiter>; note that this option does not effect the input.
|
|
local __result=''
|
|
local __delimiter=' '
|
|
local __item=''
|
|
if [ "$1" = "-d" ]; then
|
|
shift
|
|
__delimiter="$1"
|
|
shift
|
|
fi
|
|
for __item in "$@"; do
|
|
if [ x"$__result" = x ]; then
|
|
__result="$__item"
|
|
else
|
|
__result="${__item}${__delimiter}${__result}"
|
|
fi
|
|
done
|
|
echo "$__result"
|
|
)
|
|
|
|
# get the number of processes available for compilation
|
|
get_nprocs() {
|
|
if [ -n "${NPROCS_OVERWRITE}" ]; then
|
|
echo ${NPROCS_OVERWRITE} | sed 's/^0*//'
|
|
elif $(command -v nproc > /dev/null 2>&1); then
|
|
echo $(nproc --all)
|
|
elif $(command -v sysctl > /dev/null 2>&1); then
|
|
echo $(sysctl -n hw.ncpu)
|
|
else
|
|
echo 1
|
|
fi
|
|
}
|
|
|
|
# convert a list of paths to -L<dir> ... used by ld
|
|
paths_to_ld() {
|
|
# need to define the POSIX default IFS values here, cannot just do
|
|
# __ifs=$IFS first, because IFS can be unset, and if so __ifs will
|
|
# becomes an empty string (null) and NOT unset, so later when IFS
|
|
# is set to __ifs it becomes null rather than unset, and thus
|
|
# causing wrong behaviour. So if IFS is unset, __ifs should be
|
|
# the POSIX default value. Further more, due to shell
|
|
# automatically remove the tailing "\n" in a string during
|
|
# variable assignment, we need to add x after \n and then remove
|
|
# it.
|
|
local __paths=$@
|
|
local __name=''
|
|
local __raw_path=''
|
|
local __dir=''
|
|
local __lib_dirs=''
|
|
# set default IFS first
|
|
local __ifs=$(printf " \t\nx")
|
|
__ifs="${__ifs%x}"
|
|
[ "$IFS" ] && __ifs="$IFS"
|
|
for __name in $__paths; do
|
|
eval __raw_path=\$"$__name"
|
|
# change internal field separator to :
|
|
IFS=':'
|
|
# loop over all dirs in path, and filter out duplications
|
|
for __dir in $__raw_path; do
|
|
if ! [ x"$__dir" = x ]; then
|
|
if ! [[ "$__lib_dirs" =~ (^|[[:space:]])"-L'$__dir'"($|[[:space:]]) ]]; then
|
|
__lib_dirs="$__lib_dirs -L'$__dir'"
|
|
fi
|
|
fi
|
|
done
|
|
IFS="$__ifs"
|
|
done
|
|
echo $__lib_dirs
|
|
}
|
|
|
|
# Find a file from directories given in a list of paths, each has the
|
|
# same format as env variable PATH. If the file is found, then echoes
|
|
# the full path of the file. If the file is not found, then echoes
|
|
# __FALSE__. The file name can also contain wildcards that are
|
|
# acceptable for bash, and in that case the full path of the first
|
|
# matching file will be echoed.
|
|
find_in_paths() {
|
|
local __target=$1
|
|
shift
|
|
local __paths=$@
|
|
local __name=''
|
|
local __raw_path=''
|
|
local __dir=''
|
|
local __file=''
|
|
local __files=''
|
|
# use the IFS variable to take care of possible spaces in file/dir names
|
|
local __ifs="$(printf " \t\nx")"
|
|
__ifs="${__ifs%x}"
|
|
[ "$IFS" ] && __ifs="$IFS"
|
|
for __name in $__paths; do
|
|
eval __raw_path=\$"$__name"
|
|
# fields in paths are separated by :
|
|
IFS=':'
|
|
for __dir in $__raw_path; do
|
|
# files in possible glob expansion are to be delimited by "\n\b"
|
|
IFS="$(printf "\nx")"
|
|
IFS="${IFS%x}"
|
|
for __file in $__dir/$__target; do
|
|
if [ -e "$__file" ]; then
|
|
echo $(real_path "$__file")
|
|
# must remember to change IFS back when exiting
|
|
IFS="$__ifs"
|
|
return 0
|
|
fi
|
|
done
|
|
IFS=':'
|
|
done
|
|
IFS=$__ifs
|
|
done
|
|
echo "__FALSE__"
|
|
}
|
|
|
|
# search through a list of given paths, try to find the required file
|
|
# or directory, and if found then add full path of dirname file, or
|
|
# directory, to the -I include list for CFLAGS and append to a user
|
|
# specified variable (__cflags_name). If not found, then nothing is
|
|
# done. If the option -p is present, then if the search target is a
|
|
# directory, then the parent directory of the directory is used for -I
|
|
# instead. The search target accepts bash wildcards, and in this case
|
|
# the first match will be used.
|
|
add_include_from_paths() {
|
|
local __parent_dir_only=false
|
|
if [ $1 = "-p" ]; then
|
|
__parent_dir_only=true
|
|
shift
|
|
fi
|
|
local __cflags_name=$1
|
|
shift
|
|
local __search_target=$1
|
|
shift
|
|
local __paths=$@
|
|
local __found_target=""
|
|
local __cflags=""
|
|
__found_target="$(find_in_paths "$__search_target" \
|
|
$__paths)"
|
|
if [ "$__found_target" != "__FALSE__" ]; then
|
|
if [ -f "$__found_target" ] || $__parent_dir_only; then
|
|
__found_target="$(dirname "$__found_target")"
|
|
fi
|
|
echo "Found include directory $__found_target"
|
|
eval __cflags=\$"${__cflags_name}"
|
|
__cflags="${__cflags} -I${__found_target}"
|
|
# remove possible duplicates
|
|
__cflags="$(unique $__cflags)"
|
|
# must escape all quotes again before the last eval, as
|
|
# otherwise all quotes gets interpreted by the shell when
|
|
# assigning to variable because eval will reduce one escape
|
|
# level
|
|
__cflags="${__cflags//'/\\'/}"
|
|
eval $__cflags_name=\"$__cflags\"
|
|
fi
|
|
}
|
|
|
|
# search through a list of given paths, try to find the required file
|
|
# or directory, and if found then add full path of dirname file, or
|
|
# directory, to the -L library list (including -Wl,-rpath) for LDFLAGS
|
|
# and append to a user specified variable (__ldflags_name). If not
|
|
# found, then nothing is done. If the option -p is present, then if
|
|
# the search target is a directory, then the parent directory of the
|
|
# directory is used for -L instead. The search target accepts bash
|
|
# wildcards, and in this case the first match will be used.
|
|
add_lib_from_paths() {
|
|
local __parent_dir_only=false
|
|
if [ $1 = "-p" ]; then
|
|
__parent_dir_only=true
|
|
shift
|
|
fi
|
|
local __ldflags_name=$1
|
|
shift
|
|
local __search_target=$1
|
|
shift
|
|
local __paths=$@
|
|
local __found_target=""
|
|
local __ldflags=""
|
|
__found_target="$(find_in_paths "$__search_target" \
|
|
$__paths)"
|
|
if [ "$__found_target" != "__FALSE__" ]; then
|
|
if [ -f "$__found_target" ] || $__parent_dir_only; then
|
|
__found_target="$(dirname "$__found_target")"
|
|
fi
|
|
echo "Found lib directory $__found_target"
|
|
eval __ldflags=\$"${__ldflags_name}"
|
|
__ldflags="${__ldflags} -L${__found_target} -Wl,-rpath,${__found_target}"
|
|
# remove possible duplicates
|
|
__ldflags="$(unique $__ldflags)"
|
|
# must escape all quotes again before the last eval, as
|
|
# otherwise all quotes gets interpreted by the shell when
|
|
# assigning to variable because eval will reduce one escape
|
|
# level
|
|
__ldflags="${__ldflags//'/\\'/}"
|
|
eval $__ldflags_name=\"$__ldflags\"
|
|
fi
|
|
}
|
|
|
|
# check if environment variable is assigned and non-empty
|
|
# https://serverfault.com/questions/7503/how-to-determine-if-a-bash-variable-is-empty
|
|
require_env() {
|
|
local __env_var_name=$1
|
|
local __env_var="$(eval echo \"\$$__env_var_name\")"
|
|
if [ -z "${__env_var+set}" ]; then
|
|
report_error "requires environment variable $__env_var_name to work"
|
|
fi
|
|
}
|
|
|
|
# check if a command is available
|
|
check_command() {
|
|
local __command=${1}
|
|
if [ $# -eq 1 ]; then
|
|
local __package=${1}
|
|
elif [ $# -gt 1 ]; then
|
|
local __package=${2}
|
|
fi
|
|
if $(command -v ${__command} > /dev/null 2>&1); then
|
|
echo "path to ${__command} is $(real_path $(command -v ${__command}))"
|
|
else
|
|
report_error "Cannot find ${__command}, please check if the package ${__package} is installed or in system search path"
|
|
fi
|
|
}
|
|
|
|
# Check pkg-config package
|
|
check_pkgconfig() {
|
|
local pkg="$1"
|
|
if $(pkg-config --exists "${pkg}"); then
|
|
echo "pkg-config found ${pkg} under $(pkg-config --variable=prefix "${pkg}")"
|
|
else
|
|
report_error "Cannot find pkg-config package ${pkg}"
|
|
fi
|
|
}
|
|
|
|
# check if directory exists
|
|
check_dir() {
|
|
local __dir=$1
|
|
if [ -d "$__dir" ]; then
|
|
echo "Found directory $__dir"
|
|
else
|
|
report_error "Cannot find $__dir"
|
|
fi
|
|
}
|
|
|
|
# check if a command has been installed correctly
|
|
check_install() {
|
|
local __command=${1}
|
|
if [ $# -eq 1 ]; then
|
|
local __package=${1}
|
|
elif [ $# -gt 1 ]; then
|
|
local __package=${2}
|
|
fi
|
|
if $(command -v ${__command} > /dev/null 2>&1); then
|
|
echo "$(basename ${__command}) is installed as $(command -v ${__command})"
|
|
else
|
|
report_error "cannot find ${__command}, please check if the package ${__package} has been installed correctly"
|
|
fi
|
|
}
|
|
|
|
# check if a library can be found by ld, library names should in the
|
|
# format -lname, which would then referred to libname.a or libname.so
|
|
# by ld
|
|
check_lib() {
|
|
local __libname="${1#-l}"
|
|
if [ $# -eq 1 ]; then
|
|
local __package=lib"$__libname"
|
|
elif [ $# -gt 1 ]; then
|
|
local __package=$2
|
|
fi
|
|
# Note that LD_LIBRARY_PATH is NOT used by ld during linking
|
|
# stage, and is only used for searching to the shared libraries
|
|
# required by the executable AFTER it has already been compiled, to
|
|
# override its internal search paths built into the binary when it
|
|
# was compiled. Here, we explicitly include the commonly defined
|
|
# library search paths---including LD_LIBRARY_PATH---in the -L
|
|
# search paths of ld. This is the only way ld can include
|
|
# non-standard directories in its search path. If we use gcc
|
|
# instead of ld for linker then we can use LIBRARY_PATH, which IS
|
|
# used during link stage. However, I think using ld is more
|
|
# general, as in most systems LIBRARY_PATH is rarely defined, and
|
|
# we would have to rely on gcc.
|
|
local __search_engine="ld -o /dev/null"
|
|
local __search_paths="$LIB_PATHS"
|
|
# convert a list of paths to -L<dir> list used by ld
|
|
__search_engine="$__search_engine $(paths_to_ld $__search_paths)"
|
|
# needed the eval to interpret the quoted directories correctly (somehow)
|
|
if (eval $__search_engine -l$__libname 2>&1 | grep -q -s "\-l$__libname"); then
|
|
# if library not found, ld will return error message
|
|
# containing the library name
|
|
report_error \
|
|
"ld cannot find -l$__libname, please check if $__package is installed or in system search path"
|
|
else
|
|
# if library is found, then ld will return error message about
|
|
# not able to find _start or _main symbol
|
|
echo "lib$__libname is found in ld search path"
|
|
fi
|
|
}
|
|
|
|
# check if a module is available for the current version of gfortran,
|
|
# returns 0 if available and 1 if not
|
|
check_gfortran_module() {
|
|
local __module_name=$1
|
|
local __FC=${FC:-gfortran}
|
|
cat << EOF | $__FC -c -o /dev/null -xf95 -ffree-form - > /dev/null 2>&1
|
|
PROGRAM check_gfortran_module
|
|
USE ${__module_name}
|
|
IMPLICIT NONE
|
|
PRINT *, "PASS"
|
|
END PROGRAM check_gfortran_module
|
|
EOF
|
|
}
|
|
|
|
# check if a flag is allowed for the current version of
|
|
# gfortran. returns 0 if allowed and 1 if not
|
|
check_gfortran_flag() {
|
|
local __flag=$1
|
|
local __FC=${FC:-gfortran}
|
|
# no need to do a full compilation, just -E -cpp would do for
|
|
# checking flags
|
|
cat << EOF | $__FC -E -cpp $__flag -xf95 -ffree-form - > /dev/null 2>&1
|
|
PROGRAM test_code
|
|
IMPLICIT NONE
|
|
PRINT *, "PASS"
|
|
END PROGRAM test_code
|
|
EOF
|
|
}
|
|
|
|
# check if a flag is allowed for the current version of
|
|
# gcc. returns 0 if allowed and 1 if not
|
|
check_gcc_flag() {
|
|
local __flag=$1
|
|
local __CC=${CC:-gcc}
|
|
# no need to do a full compilation, just -E -cpp would do for
|
|
# checking flags
|
|
cat << EOF | $__CC -E -cpp $__flag -xc - > /dev/null 2>&1
|
|
#include <stdio.h>
|
|
int main() {
|
|
printf("PASS\n");
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# check if a flag is allowed for the current version of
|
|
# g++. returns 0 if allowed and 1 if not
|
|
check_gxx_flag() {
|
|
local __flag=$1
|
|
local __CXX=${CXX:-g++}
|
|
# no need to do a full compilation, just -E -cpp would do for
|
|
# checking flags
|
|
cat << EOF | $__CXX -E -cpp $__flag -xc - > /dev/null 2>&1
|
|
#include <stdio.h>
|
|
int main() {
|
|
printf("PASS\n");
|
|
}
|
|
EOF
|
|
}
|
|
|
|
# given a list of flags, only print out what is allowed by the current
|
|
# version of gfortran
|
|
allowed_gfortran_flags() {
|
|
local __flags=$@
|
|
local __flag=''
|
|
local __result=''
|
|
for __flag in $__flags; do
|
|
if (check_gfortran_flag $__flag); then
|
|
[ -z "$__result" ] && __result="$__flag" || __result="$__result $__flag"
|
|
fi
|
|
done
|
|
echo $__result
|
|
}
|
|
|
|
# given a list of flags, only print out what is allowed by the current
|
|
# version of gcc
|
|
allowed_gcc_flags() {
|
|
local __flags=$@
|
|
local __flag=''
|
|
local __result=''
|
|
for __flag in $__flags; do
|
|
if (check_gcc_flag $__flag); then
|
|
[ -z "$__result" ] && __result="$__flag" || __result="$__result $__flag"
|
|
fi
|
|
done
|
|
echo $__result
|
|
}
|
|
|
|
# given a list of flags, only print out what is allowed by the current
|
|
# version of g++
|
|
allowed_gxx_flags() {
|
|
local __flags=$@
|
|
local __flag=''
|
|
local __result=''
|
|
for __flag in $__flags; do
|
|
if (check_gxx_flag $__flag); then
|
|
[ -z "$__result" ] && __result="$__flag" || __result="$__result $__flag"
|
|
fi
|
|
done
|
|
echo $__result
|
|
}
|
|
|
|
# remove a directory to a given path
|
|
remove_path() {
|
|
local __path_name=$1
|
|
local __directory=$2
|
|
local __path="$(eval echo \$$__path_name)"
|
|
# must remove all the middle ones first before treating two ends,
|
|
# otherwise there can be cases where not all __directory are
|
|
# removed.
|
|
__path=${__path//:$__directory:/:}
|
|
__path=${__path#$__directory:}
|
|
__path=${__path%:$__directory}
|
|
__path=$(echo "$__path" | sed "s#^$__directory\$##g")
|
|
eval $__path_name=\"$__path\"
|
|
export $__path_name
|
|
}
|
|
|
|
# prepend a directory to a given path
|
|
prepend_path() {
|
|
# prepend directory to $path_name and then export path_name. If
|
|
# the directory already exists in path, bring the directory to the
|
|
# front of the list.
|
|
# $1 is path name
|
|
# $2 is directory
|
|
remove_path "$1" "$2"
|
|
eval $1=\"$2\${$1:+\":\$$1\"}\"
|
|
eval export $1
|
|
}
|
|
|
|
# append a directory to a given path
|
|
append_path() {
|
|
# append directory to $path_name and then export path_name. If
|
|
# the directory already exists in path, bring the directory to the
|
|
# back of the list.
|
|
# $1 is path name
|
|
# $2 is directory
|
|
remove_path "$1" "$2"
|
|
eval $1=\"\${$1:+\"\$$1:\"}$2\"
|
|
eval export $1
|
|
}
|
|
|
|
# helper routine for reading --enable=* input options
|
|
read_enable() {
|
|
local __input_var="${1#*=}"
|
|
case $__input_var in
|
|
"$1")
|
|
# if there is no "=" then treat as "yes"
|
|
echo "__TRUE__"
|
|
;;
|
|
yes)
|
|
echo "__TRUE__"
|
|
;;
|
|
no)
|
|
echo "__FALSE__"
|
|
;;
|
|
*)
|
|
echo "__INVALID__"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# helper routine for reading --with=* input options
|
|
read_with() {
|
|
local __input_var="${1#--with*=}"
|
|
case $__input_var in
|
|
"${1}")
|
|
# if there is no "=" then treat as "install"
|
|
if [ ${#} -gt 1 ]; then
|
|
echo "${2}"
|
|
else
|
|
echo "__INSTALL__"
|
|
fi
|
|
;;
|
|
install)
|
|
echo "__INSTALL__"
|
|
;;
|
|
system)
|
|
echo "__SYSTEM__"
|
|
;;
|
|
no)
|
|
echo "__DONTUSE__"
|
|
;;
|
|
*)
|
|
echo "${__input_var//\~/$HOME}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# get checksum command based on OS type, inspired by part of gcc package
|
|
# (gcc-14.3.0/contrib/download_prerequisites)
|
|
get_checksum_cmd() {
|
|
local __os=$(uname)
|
|
local __chksum="sha256sum"
|
|
case $__os in
|
|
"Darwin" | "FreeBSD" | "DragonFly" | "AIX")
|
|
__chksum='shasum -a 256'
|
|
;;
|
|
"OpenBSD")
|
|
__chksum='sha256'
|
|
;;
|
|
*)
|
|
__chksum='sha256sum'
|
|
;;
|
|
esac
|
|
echo "$__chksum"
|
|
}
|
|
|
|
# helper routine to check integrity of files
|
|
# intended to be used as condition test in an if-then-else construct, because
|
|
# no extra actions are taken for missing file or failed match in this form
|
|
# usage: checksum sha256 filename
|
|
checksum() {
|
|
local __sha256="$1"
|
|
local __filename="$2"
|
|
local __shasum_command=$(get_checksum_cmd)
|
|
echo "$__sha256 $__filename" | ${__shasum_command} --check
|
|
}
|
|
|
|
# downloader for the package tars, includes checksum
|
|
download_pkg_from_urlpath() {
|
|
# usage: download_pkg_from_url_path sha256 filename urlpath [outfile]
|
|
local __sha256="$1"
|
|
local __filename="$2"
|
|
local __url="$3/${__filename}"
|
|
local __outfile="${4:-${__filename}}"
|
|
local __command="wget ${DOWNLOADER_FLAGS} --quiet ${__url} -O ${__outfile}"
|
|
echo "${__command}"
|
|
# download
|
|
if ! eval "${__command}"; then
|
|
report_error "failed to download ${__url}"
|
|
fi
|
|
# checksum
|
|
if checksum "${__sha256}" "${__outfile}"; then
|
|
echo "Checksum of $__filename Ok"
|
|
else
|
|
rm -vf "${__outfile}"
|
|
report_error "Checksum of $__filename could not be verified, abort."
|
|
fi
|
|
}
|
|
|
|
# download from CP2K.org
|
|
download_pkg_from_cp2k_org() {
|
|
# usage: download_pkg_from_cp2k_org sha256 filename
|
|
download_pkg_from_urlpath "$1" "$2" https://www.cp2k.org/static/downloads
|
|
}
|
|
|
|
# retrieve package under current directory with filename and checksum verification
|
|
# if file exists and checksum is correct, only print a message
|
|
# if file exists but checksum is incorrect, delete and re-download from cp2k.org
|
|
# if file does not exist, download from cp2k.org
|
|
retrieve_package() {
|
|
local __sha256="$1"
|
|
local __filename="$2"
|
|
if ! [ -f "${__filename}" ]; then
|
|
download_pkg_from_cp2k_org "${__sha256}" "${__filename}"
|
|
else
|
|
if ! checksum "${__sha256}" "${__filename}"; then
|
|
echo "$__filename is found but checksum is wrong; delete and re-download"
|
|
rm -vf "${__filename}"
|
|
download_pkg_from_cp2k_org "${__sha256}" "${__filename}"
|
|
else
|
|
echo "$__filename is found and checksum is right"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# verify the checksums inside the given checksum file
|
|
verify_checksums() {
|
|
local __checksum_file=$1
|
|
local __shasum_command=$(get_checksum_cmd)
|
|
|
|
${__shasum_command} --check "${__checksum_file}" > /dev/null 2>&1
|
|
}
|
|
|
|
# write a checksum file $1 containing checksums for each given file $2, $3, ... (plus the $VERSION_FILE)
|
|
write_checksums() {
|
|
local __checksum_file=$1
|
|
shift # remove output file from arguments to be able to pass them along properly quoted
|
|
local __shasum_command=$(get_checksum_cmd)
|
|
|
|
${__shasum_command} "${VERSION_FILE}" "$@" > "${__checksum_file}"
|
|
}
|
|
|
|
# generate a filtered toolchain.env
|
|
write_toolchain_env() {
|
|
local __installdir=$1
|
|
|
|
# run the following in a subshell to not affect the currently running shell
|
|
# we do not need to achieve complete filtering, it is sufficient to
|
|
# remove problematic variables (TERM/TERMCAP/COLORTERM) which may trigger
|
|
# 'too many arguments' (since the environment vars are stored in the same memory block as command line arguments)
|
|
# or which may not be valid anymore the next time the user runs the toolchain scripts,
|
|
# like the proxy vars which may affect fetching tarballs
|
|
(
|
|
unset COLORTERM DISPLAY EDITOR LESS LESSOPEN LOGNAME LS_COLORS PAGER
|
|
unset TERM TERMCAP USER
|
|
unset ftp_proxy http_proxy no_proxy
|
|
unset GPG_AGENT_INFO SSH_AGENT_PID SSH_AUTH_SOCK SSH_CLIENT SSH_CONNECTION SSH_TTY
|
|
unset LS_COLORS LS_OPTIONS
|
|
unset STY WINDOW XAUTHORITY
|
|
unset XDG_CURRENT_DESKTOP XDG_RUNTIME_DIR XDG_SEAT XDG_SESSION_CLASS XDG_SESSION_DESKTOP XDG_SESSION_ID XDG_SESSION_TYPE XDG_VTNR XDG_CONFIG_DIRS XDG_DATA_DIRS
|
|
unset DBUS_SESSION_BUS_ADDRESS
|
|
|
|
export -p
|
|
) > "${__installdir}/toolchain.env"
|
|
}
|
|
|
|
# Write a setup file without containing flags unnecessay for building and running CP2K
|
|
filter_setup() {
|
|
local source_file="$1"
|
|
local target_file="$2"
|
|
|
|
# Check if setup_xxx file exists
|
|
if [[ ! -f "$source_file" ]]; then
|
|
report_error "File '$source_file' does not exist."
|
|
fi
|
|
|
|
local filename=$(basename "$source_file")
|
|
echo "# ==================== Setup for ${filename#*_} ==================== #" >> "$target_file"
|
|
grep -v -E 'CPATH|FLAGS|_LIBS|_INCLUDES' "$source_file" >> "$target_file"
|
|
}
|