From d9be0b6af2e0369b88f7cba70ce2a455004fe3a2 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Tue, 20 Jan 2015 16:18:09 +0100 Subject: [PATCH 01/10] all build scripts moved to a sub-directory according their name --- scripts/{ => Compiler}/H5root.build | 0 scripts/{ => Compiler}/OpenBLAS.build | 0 scripts/{ => Compiler}/OpenBLAS_OMP.build | 0 scripts/{ => Compiler}/SuperLU.build | 0 scripts/{UMFPACK.bash => Compiler/UMFPACK.build} | 0 scripts/{ => HDF5}/H5hut.build | 0 scripts/{ => HDF5}/netcdf.build | 0 scripts/{ => HDF5_serial}/H5hut_serial.build | 0 scripts/{ => MPI}/BoxLib.build | 0 scripts/{ => MPI}/OPAL.build | 0 scripts/{ => MPI}/SuperLU_DIST.build | 0 scripts/{ => Programming}/Python.build | 0 scripts/{ => Programming}/Tcl.build | 0 scripts/{ => Programming}/autoconf.build | 0 scripts/{ => Programming}/automake.build | 0 scripts/{ => Programming}/cmake.build | 0 scripts/{ => Programming}/gcc.build | 0 scripts/{ => Programming}/gtest.build | 0 scripts/{ => Programming}/libtool.build | 0 scripts/{ => Programming}/lua.build | 0 scripts/{ => Programming}/m4.build | 0 scripts/{ => Programming}/psi-python27.build | 0 scripts/{ => System}/bash.build | 0 scripts/{ => System}/boost.build | 0 scripts/{ => System}/filebench.build | 0 scripts/{ => System}/fsstress.build | 0 scripts/{ => System}/giflib.build | 0 scripts/{ => System}/gmp.build | 0 scripts/{ => System}/gsl.build | 0 scripts/{ => System}/hdf5.build | 0 scripts/{ => System}/hdf5_serial.build | 0 scripts/{ => System}/ippl.build | 0 scripts/{ => System}/libungif.build | 0 scripts/{ => System}/mathlib.build | 0 scripts/{ => System}/mpc.build | 0 scripts/{ => System}/mpfr.build | 0 scripts/{ => System}/nmap.build | 0 scripts/{ => System}/openmpi.build | 0 scripts/{ => System}/optPilot.build | 0 scripts/{ => System}/parmetis.build | 0 scripts/{ => System}/patchelf.build | 0 scripts/{ => System}/root.build | 0 scripts/{ => System}/tiff.build | 0 scripts/{ => System}/trilinos.build | 0 scripts/{ => System}/vtk.build | 0 scripts/{ => Tools}/Modules.build | 0 scripts/{ => Tools}/dialog.build | 0 scripts/{ => Tools}/emacs.build | 0 scripts/{ => Tools}/global.build | 0 scripts/{ => Tools}/gnuplot.build | 0 50 files changed, 0 insertions(+), 0 deletions(-) rename scripts/{ => Compiler}/H5root.build (100%) rename scripts/{ => Compiler}/OpenBLAS.build (100%) rename scripts/{ => Compiler}/OpenBLAS_OMP.build (100%) rename scripts/{ => Compiler}/SuperLU.build (100%) rename scripts/{UMFPACK.bash => Compiler/UMFPACK.build} (100%) rename scripts/{ => HDF5}/H5hut.build (100%) rename scripts/{ => HDF5}/netcdf.build (100%) rename scripts/{ => HDF5_serial}/H5hut_serial.build (100%) rename scripts/{ => MPI}/BoxLib.build (100%) rename scripts/{ => MPI}/OPAL.build (100%) rename scripts/{ => MPI}/SuperLU_DIST.build (100%) rename scripts/{ => Programming}/Python.build (100%) rename scripts/{ => Programming}/Tcl.build (100%) rename scripts/{ => Programming}/autoconf.build (100%) rename scripts/{ => Programming}/automake.build (100%) rename scripts/{ => Programming}/cmake.build (100%) rename scripts/{ => Programming}/gcc.build (100%) rename scripts/{ => Programming}/gtest.build (100%) rename scripts/{ => Programming}/libtool.build (100%) rename scripts/{ => Programming}/lua.build (100%) rename scripts/{ => Programming}/m4.build (100%) rename scripts/{ => Programming}/psi-python27.build (100%) rename scripts/{ => System}/bash.build (100%) rename scripts/{ => System}/boost.build (100%) rename scripts/{ => System}/filebench.build (100%) rename scripts/{ => System}/fsstress.build (100%) rename scripts/{ => System}/giflib.build (100%) rename scripts/{ => System}/gmp.build (100%) rename scripts/{ => System}/gsl.build (100%) rename scripts/{ => System}/hdf5.build (100%) rename scripts/{ => System}/hdf5_serial.build (100%) rename scripts/{ => System}/ippl.build (100%) rename scripts/{ => System}/libungif.build (100%) rename scripts/{ => System}/mathlib.build (100%) rename scripts/{ => System}/mpc.build (100%) rename scripts/{ => System}/mpfr.build (100%) rename scripts/{ => System}/nmap.build (100%) rename scripts/{ => System}/openmpi.build (100%) rename scripts/{ => System}/optPilot.build (100%) rename scripts/{ => System}/parmetis.build (100%) rename scripts/{ => System}/patchelf.build (100%) rename scripts/{ => System}/root.build (100%) rename scripts/{ => System}/tiff.build (100%) rename scripts/{ => System}/trilinos.build (100%) rename scripts/{ => System}/vtk.build (100%) rename scripts/{ => Tools}/Modules.build (100%) rename scripts/{ => Tools}/dialog.build (100%) rename scripts/{ => Tools}/emacs.build (100%) rename scripts/{ => Tools}/global.build (100%) rename scripts/{ => Tools}/gnuplot.build (100%) diff --git a/scripts/H5root.build b/scripts/Compiler/H5root.build similarity index 100% rename from scripts/H5root.build rename to scripts/Compiler/H5root.build diff --git a/scripts/OpenBLAS.build b/scripts/Compiler/OpenBLAS.build similarity index 100% rename from scripts/OpenBLAS.build rename to scripts/Compiler/OpenBLAS.build diff --git a/scripts/OpenBLAS_OMP.build b/scripts/Compiler/OpenBLAS_OMP.build similarity index 100% rename from scripts/OpenBLAS_OMP.build rename to scripts/Compiler/OpenBLAS_OMP.build diff --git a/scripts/SuperLU.build b/scripts/Compiler/SuperLU.build similarity index 100% rename from scripts/SuperLU.build rename to scripts/Compiler/SuperLU.build diff --git a/scripts/UMFPACK.bash b/scripts/Compiler/UMFPACK.build similarity index 100% rename from scripts/UMFPACK.bash rename to scripts/Compiler/UMFPACK.build diff --git a/scripts/H5hut.build b/scripts/HDF5/H5hut.build similarity index 100% rename from scripts/H5hut.build rename to scripts/HDF5/H5hut.build diff --git a/scripts/netcdf.build b/scripts/HDF5/netcdf.build similarity index 100% rename from scripts/netcdf.build rename to scripts/HDF5/netcdf.build diff --git a/scripts/H5hut_serial.build b/scripts/HDF5_serial/H5hut_serial.build similarity index 100% rename from scripts/H5hut_serial.build rename to scripts/HDF5_serial/H5hut_serial.build diff --git a/scripts/BoxLib.build b/scripts/MPI/BoxLib.build similarity index 100% rename from scripts/BoxLib.build rename to scripts/MPI/BoxLib.build diff --git a/scripts/OPAL.build b/scripts/MPI/OPAL.build similarity index 100% rename from scripts/OPAL.build rename to scripts/MPI/OPAL.build diff --git a/scripts/SuperLU_DIST.build b/scripts/MPI/SuperLU_DIST.build similarity index 100% rename from scripts/SuperLU_DIST.build rename to scripts/MPI/SuperLU_DIST.build diff --git a/scripts/Python.build b/scripts/Programming/Python.build similarity index 100% rename from scripts/Python.build rename to scripts/Programming/Python.build diff --git a/scripts/Tcl.build b/scripts/Programming/Tcl.build similarity index 100% rename from scripts/Tcl.build rename to scripts/Programming/Tcl.build diff --git a/scripts/autoconf.build b/scripts/Programming/autoconf.build similarity index 100% rename from scripts/autoconf.build rename to scripts/Programming/autoconf.build diff --git a/scripts/automake.build b/scripts/Programming/automake.build similarity index 100% rename from scripts/automake.build rename to scripts/Programming/automake.build diff --git a/scripts/cmake.build b/scripts/Programming/cmake.build similarity index 100% rename from scripts/cmake.build rename to scripts/Programming/cmake.build diff --git a/scripts/gcc.build b/scripts/Programming/gcc.build similarity index 100% rename from scripts/gcc.build rename to scripts/Programming/gcc.build diff --git a/scripts/gtest.build b/scripts/Programming/gtest.build similarity index 100% rename from scripts/gtest.build rename to scripts/Programming/gtest.build diff --git a/scripts/libtool.build b/scripts/Programming/libtool.build similarity index 100% rename from scripts/libtool.build rename to scripts/Programming/libtool.build diff --git a/scripts/lua.build b/scripts/Programming/lua.build similarity index 100% rename from scripts/lua.build rename to scripts/Programming/lua.build diff --git a/scripts/m4.build b/scripts/Programming/m4.build similarity index 100% rename from scripts/m4.build rename to scripts/Programming/m4.build diff --git a/scripts/psi-python27.build b/scripts/Programming/psi-python27.build similarity index 100% rename from scripts/psi-python27.build rename to scripts/Programming/psi-python27.build diff --git a/scripts/bash.build b/scripts/System/bash.build similarity index 100% rename from scripts/bash.build rename to scripts/System/bash.build diff --git a/scripts/boost.build b/scripts/System/boost.build similarity index 100% rename from scripts/boost.build rename to scripts/System/boost.build diff --git a/scripts/filebench.build b/scripts/System/filebench.build similarity index 100% rename from scripts/filebench.build rename to scripts/System/filebench.build diff --git a/scripts/fsstress.build b/scripts/System/fsstress.build similarity index 100% rename from scripts/fsstress.build rename to scripts/System/fsstress.build diff --git a/scripts/giflib.build b/scripts/System/giflib.build similarity index 100% rename from scripts/giflib.build rename to scripts/System/giflib.build diff --git a/scripts/gmp.build b/scripts/System/gmp.build similarity index 100% rename from scripts/gmp.build rename to scripts/System/gmp.build diff --git a/scripts/gsl.build b/scripts/System/gsl.build similarity index 100% rename from scripts/gsl.build rename to scripts/System/gsl.build diff --git a/scripts/hdf5.build b/scripts/System/hdf5.build similarity index 100% rename from scripts/hdf5.build rename to scripts/System/hdf5.build diff --git a/scripts/hdf5_serial.build b/scripts/System/hdf5_serial.build similarity index 100% rename from scripts/hdf5_serial.build rename to scripts/System/hdf5_serial.build diff --git a/scripts/ippl.build b/scripts/System/ippl.build similarity index 100% rename from scripts/ippl.build rename to scripts/System/ippl.build diff --git a/scripts/libungif.build b/scripts/System/libungif.build similarity index 100% rename from scripts/libungif.build rename to scripts/System/libungif.build diff --git a/scripts/mathlib.build b/scripts/System/mathlib.build similarity index 100% rename from scripts/mathlib.build rename to scripts/System/mathlib.build diff --git a/scripts/mpc.build b/scripts/System/mpc.build similarity index 100% rename from scripts/mpc.build rename to scripts/System/mpc.build diff --git a/scripts/mpfr.build b/scripts/System/mpfr.build similarity index 100% rename from scripts/mpfr.build rename to scripts/System/mpfr.build diff --git a/scripts/nmap.build b/scripts/System/nmap.build similarity index 100% rename from scripts/nmap.build rename to scripts/System/nmap.build diff --git a/scripts/openmpi.build b/scripts/System/openmpi.build similarity index 100% rename from scripts/openmpi.build rename to scripts/System/openmpi.build diff --git a/scripts/optPilot.build b/scripts/System/optPilot.build similarity index 100% rename from scripts/optPilot.build rename to scripts/System/optPilot.build diff --git a/scripts/parmetis.build b/scripts/System/parmetis.build similarity index 100% rename from scripts/parmetis.build rename to scripts/System/parmetis.build diff --git a/scripts/patchelf.build b/scripts/System/patchelf.build similarity index 100% rename from scripts/patchelf.build rename to scripts/System/patchelf.build diff --git a/scripts/root.build b/scripts/System/root.build similarity index 100% rename from scripts/root.build rename to scripts/System/root.build diff --git a/scripts/tiff.build b/scripts/System/tiff.build similarity index 100% rename from scripts/tiff.build rename to scripts/System/tiff.build diff --git a/scripts/trilinos.build b/scripts/System/trilinos.build similarity index 100% rename from scripts/trilinos.build rename to scripts/System/trilinos.build diff --git a/scripts/vtk.build b/scripts/System/vtk.build similarity index 100% rename from scripts/vtk.build rename to scripts/System/vtk.build diff --git a/scripts/Modules.build b/scripts/Tools/Modules.build similarity index 100% rename from scripts/Modules.build rename to scripts/Tools/Modules.build diff --git a/scripts/dialog.build b/scripts/Tools/dialog.build similarity index 100% rename from scripts/dialog.build rename to scripts/Tools/dialog.build diff --git a/scripts/emacs.build b/scripts/Tools/emacs.build similarity index 100% rename from scripts/emacs.build rename to scripts/Tools/emacs.build diff --git a/scripts/global.build b/scripts/Tools/global.build similarity index 100% rename from scripts/global.build rename to scripts/Tools/global.build diff --git a/scripts/gnuplot.build b/scripts/Tools/gnuplot.build similarity index 100% rename from scripts/gnuplot.build rename to scripts/Tools/gnuplot.build From bcb6d75bcb6da0cc4ef41d1e429df9872a6d7a8f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:39:32 +0100 Subject: [PATCH 02/10] getopt, gettext added --- scripts/Bootstrap/getopt.build | 1 + scripts/Tools/gettext.build | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 120000 scripts/Bootstrap/getopt.build create mode 100755 scripts/Tools/gettext.build diff --git a/scripts/Bootstrap/getopt.build b/scripts/Bootstrap/getopt.build new file mode 120000 index 0000000..09718d1 --- /dev/null +++ b/scripts/Bootstrap/getopt.build @@ -0,0 +1 @@ +../System/getopt.build \ No newline at end of file diff --git a/scripts/Tools/gettext.build b/scripts/Tools/gettext.build new file mode 100755 index 0000000..56463f6 --- /dev/null +++ b/scripts/Tools/gettext.build @@ -0,0 +1,24 @@ +#!/bin/bash + +source "$(dirname $0)/../../lib/libem.bash" + +function em.configure() { + "${MODULE_SRCDIR}"/configure \ + --prefix="${PREFIX}" \ + --disable-java \ + --disable-threads \ + --disable-shared \ + --enable-relocatable \ + --disable-openmp \ + --disable-acl \ + --disable-curses \ + --with-included-gettext \ + --without-libiconv-prefix \ + --without-libintl-prefix \ + --with-included-libxml \ + || exit 1 +} + +em.add_to_family 'Tools' +em.set_build_dependencies "${COMPILER}" +em.make_all From e1b0cd1055fe3f9cae00e13d64c8e8d815acda9f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:40:40 +0100 Subject: [PATCH 03/10] emacs backup files added to .ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a9a5aec..29aa128 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ tmp +*~ From f9786954b49d5a254aa6d83452c60155debb4210 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:43:57 +0100 Subject: [PATCH 04/10] Bootstrap code added; put everything into Pmodules/VERSION --- scripts/Bootstrap/Modules.build | 57 ++ scripts/Bootstrap/Tcl.build | 1 + scripts/Bootstrap/bash | 70 ++ scripts/Bootstrap/bash.build | 1 + scripts/Bootstrap/bash_completion | 76 ++ scripts/Bootstrap/bootstrap.sh | 7 + scripts/Bootstrap/build_pmodules.sh | 18 + scripts/Bootstrap/dialog.bash | 346 ++++++++ scripts/Bootstrap/dialog.build | 1 + scripts/Bootstrap/gettext.build | 1 + scripts/Bootstrap/init_local_env.bash | 153 ++++ scripts/Bootstrap/install_pmodules.sh | 26 + scripts/Bootstrap/libmodules.tcl | 329 +++++++ scripts/Bootstrap/modsync.bash | 236 +++++ scripts/Bootstrap/modulecmd | 1140 +++++++++++++++++++++++++ scripts/Bootstrap/modulecmd.bash | 1140 +++++++++++++++++++++++++ scripts/Bootstrap/modulerc | 8 + 17 files changed, 3610 insertions(+) create mode 100755 scripts/Bootstrap/Modules.build create mode 120000 scripts/Bootstrap/Tcl.build create mode 100644 scripts/Bootstrap/bash create mode 120000 scripts/Bootstrap/bash.build create mode 100644 scripts/Bootstrap/bash_completion create mode 100755 scripts/Bootstrap/bootstrap.sh create mode 100755 scripts/Bootstrap/build_pmodules.sh create mode 100755 scripts/Bootstrap/dialog.bash create mode 120000 scripts/Bootstrap/dialog.build create mode 120000 scripts/Bootstrap/gettext.build create mode 100755 scripts/Bootstrap/init_local_env.bash create mode 100755 scripts/Bootstrap/install_pmodules.sh create mode 100644 scripts/Bootstrap/libmodules.tcl create mode 100755 scripts/Bootstrap/modsync.bash create mode 100644 scripts/Bootstrap/modulecmd create mode 100755 scripts/Bootstrap/modulecmd.bash create mode 100644 scripts/Bootstrap/modulerc diff --git a/scripts/Bootstrap/Modules.build b/scripts/Bootstrap/Modules.build new file mode 100755 index 0000000..be5e774 --- /dev/null +++ b/scripts/Bootstrap/Modules.build @@ -0,0 +1,57 @@ +#!/bin/bash +#set -o functrace +source "$(dirname $0)/../../lib/libem.bash" + +TCL_DIR="${PSI_PREFIX}/Tools/Pmodules/0.99.0" + +PATH="${TCL_DIR}/bin:${PATH}" + +function em.configure() { + case ${OS} in + Linux ) + declare -x LIBS="-lz -lpthread" + ;; + Darwin ) + declare -x LIBS="-lz -framework CoreFoundation" + ;; + esac + CPPFLAGS="-DUSE_INTERP_ERRORLINE" "${MODULE_SRCDIR}"/configure \ + --prefix="${PREFIX}" \ + --exec-prefix="${PREFIX}" \ + --with-module-path="${PSI_PREFIX}/${PSI_MODULES_ROOT}" \ + --with-tcl="${TCL_DIR}/lib" \ + --without-x \ + --disable-versioning \ + || exit 1 +} + +function em.post_install() { + rm -v ${PREFIX}/Modules/bin/add.modules + rm -v ${PREFIX}/Modules/bin/mkroot + rm -rfv ${PREFIX}/Modules/modulefiles + mv -v ${PREFIX}/Modules/share/man/man1/module.1 ${PREFIX}/share/man/man1 + mv -v ${PREFIX}/Modules/share/man/man4/modulefile.4 ${PREFIX}/share/man/man4 + rmdir ${PREFIX}/Modules/bin + rmdir ${PREFIX}/Modules/share/man/man1 + rmdir ${PREFIX}/Modules/share/man/man4 + rmdir ${PREFIX}/Modules/share/man + rmdir ${PREFIX}/Modules/share + rmdir ${PREFIX}/Modules +} + +# fake module command +module() { + : +} + +# use system gcc to compile +declare -rx CC=gcc + +em.add_to_family 'Tools' +em.make_all + +# Local Variables: +# mode: sh +# sh-basic-offset: 8 +# tab-width: 8 +# End: diff --git a/scripts/Bootstrap/Tcl.build b/scripts/Bootstrap/Tcl.build new file mode 120000 index 0000000..dfcb532 --- /dev/null +++ b/scripts/Bootstrap/Tcl.build @@ -0,0 +1 @@ +../Programming/Tcl.build \ No newline at end of file diff --git a/scripts/Bootstrap/bash b/scripts/Bootstrap/bash new file mode 100644 index 0000000..08a45cc --- /dev/null +++ b/scripts/Bootstrap/bash @@ -0,0 +1,70 @@ +#!/bin/bash + +if [ ${BASH_VERSINFO:-0} -lt 3 ]; then + echo "BASH version ${BASH_VERSION} ist not supported! You need at least version 3..." + return +fi + +if [ "${LOADEDMODULES:-}" = "" ]; then + declare -x LOADEDMODULES= +fi + +if [[ -r "${PSI_BASH_COMPLETION}" ]]; then + source "${PSI_BASH_COMPLETION}" +fi + +module() { + local -r modulecmd="${PMODULES_HOME}/bin/modulecmd" + + local -a args=() + local -a switches=() + local -a sub_switches=() + local subcommand='' + + while (( $# > 0 )); do + case $1 in + -u|--userlvl ) + switches+=( $1 $2 ) + shift 2 + ;; + -* ) + switches+=( $1 ) + shift + ;; + [a-z]* ) + subcommand=$1 + shift + break + ;; + esac + done + + while (( $# > 0 ));do + case $1 in + -* ) + sub_switches+=( $1 ) + ;; + [a-zA-Z]* ) + args+=( $1 ) + ;; + esac + shift + done + + if [[ ${subcommand} == '' ]]; then + subcommand='help' + fi + if (( ${#args} == 0 )); then + args+=( '' ) + fi + for arg in "${args[@]}"; do + eval $( "${modulecmd}" bash ${switches[@]} "${subcommand}" "${sub_switches[@]}" "${arg}" ) + done +} +export -f module + +# Local Variables: +# mode: sh +# sh-basic-offset: 8 +# tab-width: 8 +# End: diff --git a/scripts/Bootstrap/bash.build b/scripts/Bootstrap/bash.build new file mode 120000 index 0000000..aa482ca --- /dev/null +++ b/scripts/Bootstrap/bash.build @@ -0,0 +1 @@ +../System/bash.build \ No newline at end of file diff --git a/scripts/Bootstrap/bash_completion b/scripts/Bootstrap/bash_completion new file mode 100644 index 0000000..8b0acaa --- /dev/null +++ b/scripts/Bootstrap/bash_completion @@ -0,0 +1,76 @@ +# +# Bash commandline completion (bash 3.0 and above) for Modules 3.2.10 +# +_module_avail() { + "${MODULESHOME}"/bin/modulecmd bash -t avail 2>&1 | sed ' + /:$/d; + /:ERROR:/d; + s#^\(.*\)/\(.\+\)(default)#\1\n\1\/\2#; + s#/(default)##g; + s#/*$##g;' +} + +_module_not_yet_loaded() { + comm -23 <(_module_avail|sort) <(tr : '\n' <<<${LOADEDMODULES}|sort) +} + +_module_long_arg_list() { + local cur="$1" i + + if [[ ${COMP_WORDS[COMP_CWORD-2]} == sw* ]] + then + COMPREPLY=( $(compgen -W "$(_module_not_yet_loaded)" -- "$cur") ) + return + fi + for ((i = COMP_CWORD - 1; i > 0; i--)) + do case ${COMP_WORDS[$i]} in + add|load) + COMPREPLY=( $(compgen -W "$(_module_not_yet_loaded)" -- "$cur") ) + break;; + rm|remove|unload|switch|swap) + COMPREPLY=( $(IFS=: compgen -W "${LOADEDMODULES}" -- "$cur") ) + break;; + esac + done +} + +_module() { + local cur="$2" prev="$3" cmds opts + + COMPREPLY=() + + cmds="add apropos avail clear dependencies display help\ + initadd initclear initlist initprepend initrm initswitch\ + keyword list load purge refresh rm search show swap switch sync\ + unload unuse update use whatis" + + opts="-c -f -h -i -l -s -t -u -v -H -V\ + --create --force --help --human --icase\ + --long --silent --terse --userlvl --verbose --version" + + case "$prev" in + add|load) COMPREPLY=( $(compgen -W "$(_module_not_yet_loaded)" -- "$cur") );; + rm|remove|unload|switch|swap) + COMPREPLY=( $(IFS=: compgen -W "${LOADEDMODULES}" -- "$cur") );; + unuse) COMPREPLY=( $(IFS=: compgen -W "${MODULEPATH}" -- "$cur") );; + use|*-a*) ;; # let readline handle the completion + -u|--userlvl) COMPREPLY=( $(compgen -W "novice expert advanced" -- "$cur") );; + display|help|show|whatis) + COMPREPLY=( $(compgen -W "$(_module_avail)" -- "$cur") );; + *) if test $COMP_CWORD -gt 2 + then + _module_long_arg_list "$cur" + else + case "$cur" in + # The mappings below are optional abbreviations for convenience + ls) COMPREPLY="list";; # map ls -> list + r*) COMPREPLY="rm";; # also covers 'remove' + sw*) COMPREPLY="switch";; + + -*) COMPREPLY=( $(compgen -W "$opts" -- "$cur") );; + *) COMPREPLY=( $(compgen -W "$cmds" -- "$cur") );; + esac + fi;; + esac +} +complete -o default -F _module module diff --git a/scripts/Bootstrap/bootstrap.sh b/scripts/Bootstrap/bootstrap.sh new file mode 100755 index 0000000..6dfbe9d --- /dev/null +++ b/scripts/Bootstrap/bootstrap.sh @@ -0,0 +1,7 @@ +#!/bin/bash +declare -r BASE_DIR=$(cd "$(dirname $0)/../.." && pwd) +declare -r BOOTSTRAP_DIR="${BASE_DIR}/scripts/Bootstrap" + +${BOOTSTRAP_DIR}/build_pmodules.sh +${BOOTSTRAP_DIR}/install_pmodules.sh + diff --git a/scripts/Bootstrap/build_pmodules.sh b/scripts/Bootstrap/build_pmodules.sh new file mode 100755 index 0000000..90f7675 --- /dev/null +++ b/scripts/Bootstrap/build_pmodules.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +declare -r BASE_DIR=$(cd "$(dirname $0)/../.." && pwd) +declare -r BOOTSTRAP_DIR="${BASE_DIR}/scripts/Bootstrap" + +source "/opt/psi/config/environment.bash" +source "${BASE_DIR}/config/pmodules_version.conf" + +${BOOTSTRAP_DIR}/gettext.build --bootstrap +${BOOTSTRAP_DIR}/getopt.build --bootstrap +${BOOTSTRAP_DIR}/dialog.build --bootstrap +${BOOTSTRAP_DIR}/bash.build --bootstrap +${BOOTSTRAP_DIR}/Tcl.build --bootstrap + +# we have to remove the init directory - otherwise the next build will fail... +rm -rf "${PMODULES_HOME}/init" +${BOOTSTRAP_DIR}/Modules.build --bootstrap +mv -v "${PMODULES_HOME}/bin/modulecmd" "${PMODULES_HOME}/bin/modulecmd.tcl" diff --git a/scripts/Bootstrap/dialog.bash b/scripts/Bootstrap/dialog.bash new file mode 100755 index 0000000..92f6814 --- /dev/null +++ b/scripts/Bootstrap/dialog.bash @@ -0,0 +1,346 @@ +#!/usr/bin/env bash + +# Hardcoded path to dialog software +LOCAL_DIALOGHOME=Tools/dialog/1.2.1 +DIALOG_CMD=$PSI_PREFIX/$LOCAL_DIALOGHOME/bin/dialog + +declare -a modlist # module info +declare -A selected # module info indices selected +declare -a depcnt # dependency reference counter by module info index +declare -A uidmap # unique module id to module info index +declare -A modmap # map module names to module info indices for modlist +declare -A fdmap # module name to family definition mapping +declare -A fmmap # module name to family member mapping +declare -a relmap # module info index to release mapping +declare tempfile # temporary dialog results + +function set_difference() { # $1 \ $2 + local -a operand1=($1) + local -a operand2=($2) + local -A members + local -i elem + for elem in "${operand1[@]}"; do + members[$elem]=1 + done + for elem in "${operand2[@]}"; do + unset members[$elem] + done + echo ${!members[@]} +} + +function set_merge() { # $1 U $2 (where $1 and $2 are disjoint) + if [[ -z "$1" ]]; then + echo "$2" + elif [[ -z "$2" ]]; then + echo "$1" + else + echo "$1 $2" + fi +} + +function set_union() { # $1 U $2 (sorted) + local -a operand1=($1) + local -a operand2=($2) + local -A members + local -i elem + for elem in ${operand1[@]} ${operand2[@]}; do + members[$elem]=1 + done + { IFS=$'\n'; echo "${!members[*]}"; } | sort -n +} + +# unique id for a module +function unique_id() { # $1: module info index + local -a minfo=( ${modlist[$1]} ) + if (( ${#minfo[@]} < 4 )); then + echo ${minfo[0]} + else + echo "${minfo[@]:3} ${minfo[0]}" + fi +} + +function mod_path() { # $1: module info index + local -i i + local -a m=(${modlist[$1]}) + local res="$PSI_PREFIX/${fmmap[${m[0]%%/*}]}/${m[0]}" + for (( i=${#m[@]}; i>3; i-- )); do + res+="/${m[i-1]}" + done + echo "$res" +} + +function calc_deps() { # $1: module info index + local dpath="$(mod_path $1)/.dependencies" + [[ ! -r "$dpath" ]] && return + local -a d=( $(< "$dpath") ) # dependencies as versioned module names + local -A p # map family to versioned module name + local -A did # map dependency (versioned module name) to unique module id + local -a deps # set of module info indices + local m n f + for m in ${d[@]}; do + n=${m%%/*} + f=${fdmap[$n]} + [[ -n "$f" ]] && { p[$f]=$m; } + f=${fmmap[$n]} + if [[ -z "$f" ]]; then + did[$m]=$m + else + n=${p[$f]} + if [[ -z "$n" ]]; then + did[$m]=$m + else + did[$m]="${did[$n]} $m" + fi + fi + deps+=( ${uidmap["${did[$m]}"]} ) + done + echo "${deps[@]}" +} + +function update_deps() { # $1: 1-add dependency, -1-remove dependency $2: set of module info indices + [[ -z "$2" ]] && return + local -a q=($2) # work queue + local deps="" # set of dependencies + local -i m + while (( ${#q[@]} > 0 )); do + m=${q[-1]} + unset q[-1] + d="$(calc_deps $m)" + [[ -z "$d" ]] && continue + d="$(set_difference "$d" "$deps")" + [[ -z "$d" ]] && continue + q+=($d) + deps="$(set_merge "$d" "$deps")" + done + for m in $deps; do + let depcnt[m]+=$1 + done +} + +function find_modules() { + # construct modlist/modmap/uidmap/depcnt/fmmap/relmap arrays from module search output + local -a mc # module info components + local -i i=0 + local current="" + local name m + while read m; do + mc=($m) + [[ "${mc[2]}" == "Legacy" ]] && continue # filter out legacy stuff + name=${mc[0]%%/*} + if [[ "$current" != "$name" ]]; then + modmap[$name]="$i" + current=$name + else + modmap[$name]+=" $i" + fi + modlist[i]=$m + uidmap[$(unique_id $i)]=$i + depcnt[i]=0 + [[ -z ${fmmap[$name]} ]] && { fmmap[$name]=${mc[2]}; } + relmap[i]=${mc[1]} + i+=1 + done +} + +function find_families() { + # construct fdmap + local -a t # tcl file components + local l s n + while read l; do + s=${l%%:*} + s=${s%/*} + n=${s##*/} + if [[ -z "${fdmap[$n]}" ]]; then + t=( ${l##*:} ) + fdmap[$n]=${t[-1]//\"} + fi + done < <(grep -R set-family "${PSI_PREFIX}/${PSI_MODULES_ROOT}") +} + +function select_uid() { # $1: module uid + local -a uidc=($1) # uid components + local name=${uidc[-1]%%/*} # module name + local midx=${uidmap["$1"]} # module info index + [[ -z "$midx" ]] && return + selected[$name]="$(set_union "${selected[$name]}" "$midx")" + update_deps 1 "$midx" +} + +function preselect() { # "$1": prefix for preselected modules + # module paths must not contain white space + [[ -z "$1" ]] && return + local -a mpc # module path components + local -i i + local uid + pushd "$1/$PSI_MODULES_ROOT" > /dev/null || exit 1; + trap "popd" EXIT + + for m in $(find . -follow -type f); do + uid="" + mpc=( ${m//\// } ) + for ((i=2; i<${#mpc[@]}-2; i+=2)); do + uid+="${mpc[i]}/${mpc[i+1]} " + done + uid+="${mpc[-2]}/${mpc[-1]}" + PSI_PREFIX="$1" select_uid "$uid" + done + + popd + trap - EXIT +} + +function is_dependency() { # $1: module name + local -a map=(${modmap[$1]}) + local -i m + for ((m=0; m<${#map[@]}; m++)); do + (( ${depcnt[${map[m]}]} > 0 )) && return 0 + done + return 1 +} + +function dialog_1() { + local -a input + local marker + local m + for m in $(IFS=$'\n'; echo "${!modmap[*]}" | sort); do + marker="" + [[ -n ${selected[$m]} ]] && { marker+="*"; } + is_dependency $m && { marker+="+"; } + input+=($m "$marker$m") + done + + $DIALOG_CMD --ok-label 'Select' \ + --extra-button --extra-label 'Exit' \ + --no-tags \ + --menu Modules 50 80 50 "${input[@]}" 2>$tempfile + return $? +} + +function module_id() { # $@: module info components + echo "$1 ${@:4}" +} + +function module_release() { # $@: module info components + echo "$2" +} + +function dialog_2() { # $1: module name + local -a map=(${modmap[$1]}) + local -a sel=(${selected[$1]}) + local -i j # mapping index + local -i k=0 # selection index + local -a input + local marker minfo rel m s + for (( j=0; j!=${#map[@]}; j++ )); do + minfo=${modlist[${map[j]}]} + m="$(module_id $minfo)" + rel=" ($(module_release $minfo))" + [[ $rel = " (stable)" ]] && { rel=""; } + [[ "${map[j]}" = "${sel[k]}" ]] && { s="on"; k+=1; } || { s="off"; } + (( ${depcnt[${map[j]}]} > 0 )) && { marker="+"; l+=1; } || { marker=""; } + input+=( ${map[j]} "$marker$m$rel" $s ) + done + + $DIALOG_CMD --extra-button --extra-label 'Clear' --no-tags --checklist Versions 80 90 80 "${input[@]}" 2>$tempfile + return $? +} + +# final dialog output +function module_out() { # $1: module info index + local -a args=(${modlist[$1]}) + echo "${args[@]}" +} + +# "$1": prefix for preselected modules +function module_picker() { + find_families + find_modules + preselect "$1" + + tempfile=$(mktemp ${TMPDIR:-/tmp}/msyncXXXXXX) || { + echo "Unable to create temporary file!" + exit 1 + } + trap "rm -f $tempfile" EXIT + + local -i level=1 + local -i operation=0 # 0: OK, 1: Cancel + local oldsel + local sel + local m + while (( level != 0 )); do + case $level in + 1) + dialog_1 + res=$? + case $res in + 0) #OK + sel=$(< $tempfile) + level=2 + ;; + 1) #Cancel + operation=1 + level=0 + ;; + 3|255) #ESC/Exit = Commit + for m in ${selected[@]}; do + depcnt[m]=1 + done + for ((m=0; m<${#depcnt[@]}; m++)); do + (( ${depcnt[m]} > 0 )) && module_out $m >&2 + done + level=0 + ;; + *) + echo "Unknown return value from dialog_1: $res" + exit 1 + ;; + esac + ;; + 2) + dialog_2 $sel + res=$? + case $res in + 0) #OK + oldsel=${selected[$sel]} # old selection + selected[$sel]=$(< $tempfile) # new selection + update_deps -1 "$(set_difference "$oldsel" "${selected[$sel]}")" # remove dependencies + update_deps 1 "$(set_difference "${selected[$sel]}" "$oldsel")" # add dependencies + level=1 + ;; + 1|255) #ESC/Cancel + level=1 + ;; + 3) #Clear + oldsel=${selected[$sel]} # old selection + selected[$sel]="" # new selection + update_deps -1 "$oldsel" # remove dependencies + level=1 + ;; + *) + echo "Unknown return value from dialog_2: $res" + exit 1 + ;; + esac + ;; + *) + echo "Unknown level: $level" + exit 1 + ;; + esac + done + + rm -f $tempfile + trap - EXIT + + return $operation +} + +# if DIALOG_LIB is NOT set, call module picker +[[ ${DIALOG_LIB:+"is_lib"} == "is_lib" ]] || { + if [[ -x ${PSI_PREFIX}/${PSI_CONFIG_DIR}/modulecmd.bash ]]; then + module_picker "$1" < <(${PSI_PREFIX}/${PSI_CONFIG_DIR}/modulecmd.bash bash search --no-header -a 2>&1) + else + echo "ERROR: module environment configuration: ${PSI_PREFIX}/${PSI_CONFIG_DIR}/modulecmd.bash is not an executable!" + fi +} diff --git a/scripts/Bootstrap/dialog.build b/scripts/Bootstrap/dialog.build new file mode 120000 index 0000000..3e38d1f --- /dev/null +++ b/scripts/Bootstrap/dialog.build @@ -0,0 +1 @@ +../Tools/dialog.build \ No newline at end of file diff --git a/scripts/Bootstrap/gettext.build b/scripts/Bootstrap/gettext.build new file mode 120000 index 0000000..67fd38d --- /dev/null +++ b/scripts/Bootstrap/gettext.build @@ -0,0 +1 @@ +../Tools/gettext.build \ No newline at end of file diff --git a/scripts/Bootstrap/init_local_env.bash b/scripts/Bootstrap/init_local_env.bash new file mode 100755 index 0000000..5617288 --- /dev/null +++ b/scripts/Bootstrap/init_local_env.bash @@ -0,0 +1,153 @@ +#!/usr/bin/env bash + + +function usage() { + PROG=$(basename $0) + echo "Usage: $PROG --dir= [--user=]" + echo " Initializes a local module environment in " + echo " for user . must not exist yet." + echo " The parameter must only be present if" + echo " $PROG is executed as root." +} + +declare force='no' + +while (($# > 0)); do + if [[ "${1#--dir}" != "$1" ]]; then + option="${1#--dir}" + option="${option#=}" + [[ -z "$option" ]] && { shift; option="$1"; } + ENV_DIR="$option" + elif [[ "${1#--user}" != "$1" ]]; then + option="${1#--user}" + option="${option#=}" + [[ -z "$option" ]] && { shift; option="$1"; } + ENV_USER="$option" + else + echo "Error: Unknown option: $1" + usage + exit 1 + fi + shift +done + +[[ -z "$ENV_DIR" ]] && { + echo "Error: --dir parameter is required!" + usage + exit 1 +} + +if (( EUID == 0 )); then + [[ -z "$ENV_USER" ]] && { + echo "Error: --user parameter is required!" + usage + exit 1 + } + USER_ID=$(id -u "$ENV_USER") + (( $? == 0 )) || { + echo "Error: Unable to retrieve user id of user '$ENV_USER'" + exit 1 + } +else + [[ -z "$ENV_USER" ]] || { + echo "Error: --user option is only allowed if running as root!" + usage + exit 1 + } + USER_ID=$EUID +fi + +if [[ -d "$ENV_DIR" ]] && [[ ${force} == no ]]; then + echo "Warning: $ENV_DIR already exists." + read -p "Do you really want to re-run the initialization? (y/N) " ans + case ${ans} in + y|Y ) + : + ;; + * ) + exit 1 + ;; + esac +fi + +echo "Attempting to create a local module environment from a partial copy of the environment at '$PSI_PREFIX'" + +[[ -d "$PSI_PREFIX" ]] && +[[ -d "$PSI_PREFIX/$PSI_CONFIG_DIR" ]] && +[[ -d "$PSI_PREFIX/$PSI_MODULES_ROOT" ]] && +[[ -d "$MODULESHOME" ]] || { + echo "Error: the module environment '$PSI_PREFIX' has not been initialized properly!" + echo "Maybe it is not a module environment, not accessible, or the init script at" + echo "'$PSI_PREFIX/config/profile.bash' has not been sourced." + exit 1 +} + +echo "Creating directory $ENV_DIR..." +mkdir -p "$ENV_DIR" || { + echo "Error: cannot create directory $ENV_DIR!" + exit 1 +} +pushd "$ENV_DIR" || { + echo "Error: Cannot change to directory $ENV_DIR" + rmdir "$ENV_DIR" + exit +} +ENV_DIR=$(pwd -P) +popd +trap "rm -rf $ENV_DIR" EXIT + +(( EUID == 0 )) && { + echo "Changing owner of directory $ENV_DIR to $ENV_USER..." + chown $USER_ID "$ENV_DIR" + su $ENV_USER || { + echo "Error: cannot change user to $ENV_USER!" + exit 1 + } +} + +(( EUID == USER_ID )) || { + echo "Error: attempt to run as user with id $USER_ID failed!" + exit 1 +} + +cd "$ENV_DIR" || { + echo "Error: failed to change working directory to $ENV_DIR!" + exit 1 +} + +echo "Copy configuration..." +rsync --recursive --links --perms --delete ${PSI_PREFIX}/${PSI_CONFIG_DIR}/ ${PSI_CONFIG_DIR}/ || { + echo "Error: copy operation failed!" + exit 1 +} + +echo "Copy module software..." +LOCAL_MODHOME=${MODULESHOME#$PSI_PREFIX/} +mkdir -p ${LOCAL_MODHOME} || { + echo "Error: creating directory for modules software failed!" + exit 1 +} +rsync --recursive --links --perms --delete ${MODULESHOME}/ ${LOCAL_MODHOME}/ || { + echo "Error: copying modules software failed!" + exit 1 +} + +echo "Create directory $PSI_MODULES_ROOT..." +mkdir -p $PSI_MODULES_ROOT || { + echo "Error: cannot create directory $PSI_MODULES_ROOT!" + exit 1 +} + +# echo "Using sudo to set the link $PSI_PREFIX to $ENV_DIR..." +# sudo bash -c "rm -f $PSI_PREFIX && ln -s $ENV_DIR $PSI_PREFIX" || { +# echo "WARNING: The link $PSI_PREFIX could not be set to $ENV_DIR!" +# echo "Please set this link manually as root:" +# echo " ln -s $ENV_DIR $PSI_PREFIX" +# } + +echo "Local module environment created at $ENV_DIR." +echo "To use this environment, execute" +echo " ln -s $ENV_DIR /opt/psi as root (delete the /opt/psi link if it already exists)" +echo " source $ENV_DIR/$PSI_CONFIG_DIR/profile.bash" + +trap - EXIT diff --git a/scripts/Bootstrap/install_pmodules.sh b/scripts/Bootstrap/install_pmodules.sh new file mode 100755 index 0000000..7c3fc05 --- /dev/null +++ b/scripts/Bootstrap/install_pmodules.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +declare -r BASE_DIR=$(cd "$(dirname $0)/../.." && pwd) +declare -r BOOTSTRAP_DIR="${BASE_DIR}/scripts/Bootstrap" + +source "/opt/psi/config/environment.bash" +source "${BASE_DIR}/config/pmodules_version.conf" + +sed_cmd="s:@PMODULES_HOME@:${PMODULES_HOME}:g;" +sed_cmd+="s:@PMODULES_VERSION@:${PMODULES_VERSION}:g;" +sed_cmd+="s:@MODULES_VERSION@:${MODULES_VERSION}:g" +sed "${sed_cmd}" "${BOOTSTRAP_DIR}/modulecmd.bash" > "${BOOTSTRAP_DIR}/modulecmd" + +install -d -m 0755 "${PMODULES_HOME}/etc" + +install -m 0755 "${BOOTSTRAP_DIR}/modulecmd" "${PMODULES_HOME}/bin" +install -m 0755 "${BOOTSTRAP_DIR}/init_local_env.bash" "${PMODULES_HOME}/bin" +install -m 0755 "${BOOTSTRAP_DIR}/modsync.bash" "${PMODULES_HOME}/bin" +install -m 0755 "${BOOTSTRAP_DIR}/dialog.bash" "${PMODULES_HOME}/bin" + +install -m 0644 "${BOOTSTRAP_DIR}/modulerc" "${PMODULES_HOME}/etc" + +install -m 0644 "${BOOTSTRAP_DIR}/bash" "${PMODULES_HOME}/init" +install -m 0644 "${BOOTSTRAP_DIR}/bash_completion" "${PMODULES_HOME}/init" + +install -m 0644 "${BOOTSTRAP_DIR}/libmodules.tcl" "${PMODULES_HOME}/lib" diff --git a/scripts/Bootstrap/libmodules.tcl b/scripts/Bootstrap/libmodules.tcl new file mode 100644 index 0000000..7ad721c --- /dev/null +++ b/scripts/Bootstrap/libmodules.tcl @@ -0,0 +1,329 @@ +# +# :TODO: +# switch/swap +# unload modules if parent removed +# + +if {[info exists env(PSI_DEBUG)] && $env(PSI_DEBUG)} { + proc debug {msg} { + set level [expr [info level] -2] + set r [catch {info level ${level}} e] + if {$r} { + set caller "" + } else { + set caller [lindex [split [info level [expr [info level] - 3]]] 0] + } + puts -nonewline stderr "${caller}: " + puts stderr ${msg} + } +} else { + proc debug {msg} {} +} + +proc set-family { family } { + global env + global name + global version + global implementation + + debug $family + set Implementation [file join {*}${implementation}] + + set FAMILY [string toupper $family] + regsub -- "-" ${FAMILY} "_" FAMILY + setenv ${FAMILY} $name + setenv ${FAMILY}_VERSION $version + + set ::${family} ${name} + set ::${family}_version ${version} + + lassign [split ${::family} .] caller_family caller_release + if { "${caller_release}" != "" } { + set caller_release ".${caller_release}" + } + debug "caller family: ${caller_family}, release: ${caller_release}" + + if { [module-info mode load] } { + debug "mode is load" + append-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/${Implementation} + append-path PSI_LOADEDFAMILIES ${family} + debug "mode=load: new MODULEPATH=$env(MODULEPATH)" + debug "mode=load: new PSI_LOADEDFAMILIES=$env(PSI_LOADEDFAMILIES)" + } elseif { [module-info mode remove] } { + # remove orphan modules + debug "remove orphan modules" + set FAMILY [string toupper $family] + if { [info exists env(PSI_ACTIVE_MODULES_${FAMILY})] } { + set modules [split $env(PSI_ACTIVE_MODULES_${FAMILY}) ":"] + foreach m ${modules} { + if { ${m} == "--APPMARKER--" } { + continue + } + debug "unloading module: $m" + module unload ${m} + } + } + remove-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/${Implementation} + remove-path PSI_LOADEDFAMILIES ${family} + debug "mode=remove: $env(MODULEPATH)" + debug "mode=remove: $env(PSI_LOADEDFAMILIES)" + } + if { [module-info mode switch2] } { + debug "mode=switch2" + append-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/[module-info name] + append-path PSI_LOADEDFAMILIES ${family} + } +} + + + +proc update_active_modules { family name version } { + if { ${family} == "--APPMARKER--" } { + return + } + set FAMILY [string toupper $family] + append-path PSI_ACTIVE_MODULES_${FAMILY} "$name/$version" + remove-path PSI_ACTIVE_MODULES_${FAMILY} "--APPMARKER--" +} + +proc is-avail { m } { + debug "${m}" + set output [catch { exec "$::env(MODULESHOME)/bin/modulecmd" bash avail "${m}" } msg] + if { ${output} != "" } { + return yes + } else { + return no + } +} + + +# +# load dependencies, but do *not* unload dependencies +# +proc load_dependencies { fname } { + if { ! [ file exists ${fname} ] } { + return + } + if { ! [module-info mode load] } { + return + } + debug "load dependencies from: ${fname}" + # Slurp up the data file + set fp [open ${fname} r] + set file_data [read ${fp}] + close ${fp} + set data [split ${file_data} "\n"] + foreach line ${data} { + debug "MODULEPATH=$::env(MODULEPATH)" + set module_name [string trim $line] + if { ${module_name} == "#" || ${module_name} == "" } { + continue + } + if { [is-loaded ${module_name}] } { + debug "module already loaded: ${module_name}" + continue + } + debug "module avail: ${module_name}" + if { ! [is-avail "${module_name}"] } { + debug "module not in current MODULEPATH: ${module_name}" + set search_output [exec $::env(PSI_PREFIX)/config/init/extensions/search.bash "${module_name}"] + module use $::env(PSI_PREFIX)/modulefiles/[lindex ${search_output} 2] + } + debug "module load: ${module_name}" + module load ${module_name} + } +} + +proc lreverse_n { list n } { + set res {} + set i [expr [llength $list] - $n] + while {$i >= 0} { + lappend res {*}[lrange $list $i [expr $i+$n-1]] + incr i -$n + } + set res +} + + + +# +# set standard environment variables +# +proc set_std_environment { PREFIX name version } { + # + # Hack for supporting legacy modules + if { "${::family}" == "Legacy" } { + debug "this is a legacy module..." + return + } + + + set NAME [string toupper $name] + regsub -- "-" ${NAME} "_" NAME + + if { ! [info exist ::dont-setenv] } { + set ::dont-setenv {} + } + + if { ${version} != "" } { + if { [lsearch ${::dont-setenv} "${NAME}_VERSION"] == -1 } { + setenv ${NAME}_VERSION $version + } + } + + if { [file isdirectory "$PREFIX"] } { + if { [lsearch ${::dont-setenv} "${NAME}_PREFIX"] == -1 } { + setenv ${NAME}_PREFIX $PREFIX + } + if { [lsearch ${::dont-setenv} "${NAME}_DIR"] == -1 } { + setenv ${NAME}_DIR $PREFIX + } + if { [lsearch ${::dont-setenv} "${NAME}_HOME"] == -1 } { + setenv ${NAME}_HOME $PREFIX + } + } + + if { [file isdirectory "$PREFIX/bin"] } { + if { [lsearch ${::dont-setenv} "PATH"] == -1 } { + prepend-path PATH $PREFIX/bin + } + } + + if { [file isdirectory "$PREFIX/sbin"] } { + if { [lsearch ${::dont-setenv} "PATH"] == -1 } { + prepend-path PATH $PREFIX/sbin + } + } + + if { [file isdirectory "$PREFIX/share/man"] } { + if { [lsearch ${::dont-setenv} "MANPATH"] == -1 } { + prepend-path MANPATH $PREFIX/share/man + } + } + + # set various environment variables - as long as they are not blacklisted + debug "prepend to include paths" + if { [file isdirectory "$PREFIX/include"] } { + if { [lsearch ${::dont-setenv} "C_INCLUDE_PATH"] == -1 } { + prepend-path C_INCLUDE_PATH $PREFIX/include + } + if { [lsearch ${::dont-setenv} "CPLUS_INCLUDE_PATH"] == -1 } { + prepend-path CPLUS_INCLUDE_PATH $PREFIX/include + } + if { [lsearch ${::dont-setenv} "${NAME}_INCLUDE_DIR"] == -1 } { + setenv ${NAME}_INCLUDE_DIR $PREFIX/include + } + } + + debug "prepend to library paths" + if { [file isdirectory "$PREFIX/lib"] } { + if { [lsearch ${::dont-setenv} "LIBRARY_PATH"] == -1 } { + prepend-path LIBRARY_PATH $PREFIX/lib + } + if { [lsearch ${::dont-setenv} "LD_LIBRARY_PATH"] == -1 } { + prepend-path LD_LIBRARY_PATH $PREFIX/lib + } + if { [lsearch ${::dont-setenv} "${NAME}_LIBRARY_DIR"] == -1 } { + setenv ${NAME}_LIBRARY_DIR $PREFIX/lib + } + } + + debug "prepend to library paths (64bit)" + if { [file isdirectory "$PREFIX/lib64"] } { + if { [lsearch ${::dont-setenv} "LIBRARY_PATH"] == -1 } { + prepend-path LIBRARY_PATH $PREFIX/lib64 + } + if { [lsearch ${::dont-setenv} "LD_LIBRARY_PATH"] == -1 } { + prepend-path LD_LIBRARY_PATH $PREFIX/lib64 + } + if { [lsearch ${::dont-setenv} "${NAME}_LIBRARY_DIR"] == -1 } { + setenv ${NAME}_LIBRARY_DIR $PREFIX/lib64 + } + } + +} + +# +# What's the game plan here? +# Determine from path of module to be loaded: +# - name, +# - version +# - installation PREFIX +# +set current_modulefile [file split $ModulesCurrentModulefile] +set psi_prefix [file split $env(PSI_PREFIX)] + +# return, if module is not in $env(PSI_PREFIX) +set module_prefix [file join {*}[lrange ${current_modulefile} 0 [llength ${psi_prefix}]-1]] +if { $env(PSI_PREFIX) != ${module_prefix} } { + debug "stop sourcing: $env(PSI_PREFIX) != ${module_prefix}" + return +} + +set MODULE_ROOT_PATH $env(PSI_PREFIX)/$env(PSI_MODULES_ROOT) +set module_root_path [file split ${MODULE_ROOT_PATH}] +set len [llength $module_root_path] + +set name [lindex $current_modulefile end-1] +set version [lindex $current_modulefile end] +set family [lrange $current_modulefile $len $len] +set implementation [lrange $current_modulefile [expr $len + 1] end] + +set prefix "$psi_prefix [regsub "(.unstable|.deprecated)" $family ""] [lreverse_n [lrange $current_modulefile $len end] 2]" +set PREFIX [file join {*}$prefix] + +debug "PREFIX=$PREFIX" +debug "family of module $name: $family" + +# +# we cannot load another module with the same name +# +conflict $name + +if { [module-info mode load] } { + debug "${name}/${version}: loading ... " + if { [ string match "*.deprecated" ${family} ] == 1 } { + puts stderr "${name}/${version}: this module is deprecated!" + } + + for {set i [expr [llength ${prefix}] - 1]} {$i >= ${len}} {incr i -2} { + set info_file [lrange ${prefix} 0 $i] + lappend info_file ".info" + set fname [file join {*}${info_file}] + if { [ file exists "${fname}" ] } { + set fp [open "${fname}" r] + set info_data [read $fp] + close $fp + puts stderr ${info_data} + } + } + load_dependencies "${PREFIX}/.dependencies" +} + +set_std_environment ${PREFIX} ${name} ${version} +update_active_modules ${family} ${name} ${version} + +proc ModulesHelp { } { + if { [info exists ::whatis] } { + puts stderr "${::whatis}" + } + if { [info exists ::version] } { + puts stderr "Version: ${::version}" + } + if { [info exists ::url] } { + puts stderr "Homepage: ${::url}" + } + if { [info exists ::license] } { + puts stderr "License: ${::license}" + } + if { [info exists ::maintainer] } { + puts stderr "Maintainer: ${::maintainer}" + } + if { [info exists ::help] } { + puts stderr "${::help}\n" + } +} + +if { [info exists ::whatis] } { + module-whatis "$whatis" +} diff --git a/scripts/Bootstrap/modsync.bash b/scripts/Bootstrap/modsync.bash new file mode 100755 index 0000000..b4e83e2 --- /dev/null +++ b/scripts/Bootstrap/modsync.bash @@ -0,0 +1,236 @@ +#!/usr/bin/env bash + +declare -r DEFAULT_SRC="/afs/psi.ch/sys/psi.@sys" +declare -r DEFAULT_DST="/opt/psi.local" + +function usage() { + echo " +$0 [--from=] [--to=] [--dryrun] [--delete] + --from source module installation (default: $DEFAULT_SRC) + + --to destination module installation (default: $DEFAULT_DST) + + --dryrun just tell what would be copied and deleted + + --delete as an additional task, delete modules that are present + at the destination but not at the source installation + (destination cleanup)" >&2 +} + +function die() { + echo "$1" >&2 + exit 1 +} + +# check if directory $1 is a valid prefix +function is_module_prefix() { + if [[ -d "$1" ]] && + [[ -d "$1/$PSI_CONFIG_DIR" ]] && + [[ -d "$1/$PSI_MODULES_ROOT" ]] + then + return 0 + fi + return 1 +} + +# set the source and destination module installations +function get_options() { + local src_dir="$DEFAULT_SRC" + local dst_dir="$DEFAULT_DST" + local dryrun=false + local delete=false + local option + + while (($# > 0)); do + if [[ "${1#--from}" != "$1" ]]; then + option="${1#--from}" + option="${option#=}" + [[ -z "$option" ]] && { shift; option="$1"; } + src_dir="$option" + elif [[ "${1#--to}" != "$1" ]]; then + option="${1#--to}" + option="${option#=}" + [[ -z "$option" ]] && { shift; option="$1"; } + dst_dir="$option" + elif [[ -z "${1#--dryrun}" ]]; then + dryrun=true + elif [[ -z "${1#--delete}" ]]; then + delete=true + else + usage > /dev/fd/2 + die "Unknown option: $1" + fi + shift + done + + is_module_prefix "$src_dir" || { die "<$src_dir> is not a Pmodules installation"; } + is_module_prefix "$dst_dir" || { die "<$dst_dir> is not a Pmodules installation"; } + src_dir=$( cd "$src_dir"; pwd -P ) + dst_dir=$( cd "$dst_dir"; pwd -P ) + [[ "$src_dir" == "$dst_dir" ]] && { die "same source and destination installations"; } + local modbin=$( cd "$PMODULES_HOME"; pwd -P ) + local prefix=$( cd "$PSI_PREFIX"; pwd -P ) + modbin=${modbin#"$prefix/"}/bin/modulecmd + local -r file_type_src=$( file -b "$src_dir/$modbin" 2>&1 || echo err1 ) + local -r file_type_dst=$( file -b "$dst_dir/$modbin" 2>&1 || echo err2 ) + [[ ! "${file_type_src}" == "${file_type_dst}" ]] || { + die "The file signatures in the source and destination installation do not match!" + } + echo "$src_dir" "$dst_dir" "$dryrun" "$delete" +} + +# Derive the relative module installation path +# from the relative module file path +# $1 relative module file path +function get_modpath() { + local -a comp=( ${1//\// } ) # split rel.path into components + local -a path # result path + local -i i + for ((i=0; i<${#comp[@]}; i++)); do + case $i in + 0) path=( ${comp[0]%.*} );; + *) path+=( "${comp[$((-i-1))]}/${comp[$((-i))]}" ); i+=1;; + esac + done + echo "${path[*]}" +} + +# Derive the relative module release file path +# from the relative module file path +# $1 relative module file path +function get_release_path() { + echo "$(dirname "$1")/.release-$(basename "$1")" +} + +# $1 dryrun=(true|false) +# $2 relative module file path of destination module to be deleted +# $3 destination prefix +function delete_module() { + if [[ "$1" != "false" ]]; then + echo "(dryrun) delete: $2 at $3" 1>&2 + return 0 + fi + local modpath=$( get_modpath "$2" ) + [[ -z "$modpath" ]] && { + die "Unable to retrieve module file and installation paths"; + } + echo "rm -v \"$3/$PSI_MODULES_ROOT/$2\"" + echo "rm -v \"$3/$PSI_MODULES_ROOT/$( get_release_path $2 )\"" + echo "rmdir -vp \"$( dirname "$3/$PSI_MODULES_ROOT/$2" )\"" + echo "rm -vrf \"$3/$modpath\"" + echo "rmdir -vp \"$( dirname "$3/$modpath" )\"" + echo "deleted: $2" 1>&2 +} + +# $1 dryrun=(true|false) +# $2 relative module file path of source module to be copied to the destination +# $3 source prefix +# $4 destination prefix +function copy_module() { + if [[ "$1" != "false" ]]; then + echo "(dryrun) copy: $2 from $3 to $4" 1>&2 + return 0 + fi + local modpath=$( get_modpath "$2" ) + [[ -z "$modpath" ]] && { die "Unable to retrieve module file and installation paths"; } + install -d $( dirname "$3/$PSI_MODULES_ROOT/$2" ) + ( + cd $3 + rsync --links --perms --relative --verbose "$PSI_MODULES_ROOT/$2" "$4" + rsync --links --perms --relative --verbose "$PSI_MODULES_ROOT/$( get_release_path "$2" )" "$4" + rsync --recursive --links --perms --relative --verbose "$modpath" "$4" + ) + echo "copied: $2" 1>&2 +} + +# syncronize modules from source to +# destination module installations +# --from= default: /afs/psi.ch/sys/psi.@sys +# --to= default: /opt/psi.local +function sync_modules() { + local -a options=( $(get_options "$@") ) + [[ -z "$options" ]] && exit 1 + local src_dir="${options[0]}" + local dst_dir="${options[1]}" + local dryrun="${options[2]}" + local delete="${options[3]}" + unset options + + local profile_script="$src_dir/$PSI_CONFIG_DIR/profile.bash" + [[ -r "$profile_script" ]] || { + die "Unable to find profile script of installation $profile_script"; + } + local search_script="$src_dir/Tools/Pmodules/${PMODULES_VERSION}/bin/modulecmd" + [[ -x "$search_script" ]] || { + die "Unable to find search script of installation $search_script"; + } + local dialog_script="$src_dir/Tools/Pmodules/${PMODULES_VERSION}/bin/dialog.bash" + [[ -r "$dialog_script" ]] || { + die "Unable to find dialog script of installation $dialog_script"; + } + + . "$profile_script" # set variables for the source installation + + DIALOG_LIB=1 # use dialog script as a library + . "$dialog_script" # dialog functions + + local -a selected_modules + + # Redefine module_out to append modules to the selected_modules variable + function module_out() { + local -a args=(${modlist[$1]}) + local path="" + IFS=/ + [[ -n "${args[3]}" ]] && path="/${args[*]:3}" + unset IFS + selected_modules+=( "${args[2]}$path/${args[0]}" ) + } + + module_picker "$dst_dir" < <("$search_script" bash search --no-header -a 2>&1) + + local -a destination_modules=( $(cd "$dst_dir/$PSI_MODULES_ROOT"; find -L . -type f | while read f; do echo ${f#./}; done) ) + + # redefine set difference, the version in dialog.bash only handles integers + function set_difference() { # $1 \ $2 + local -a operand1=($1) + local -a operand2=($2) + local -A members + local elem + for elem in "${operand1[@]}"; do + members[$elem]=1 + done + for elem in "${operand2[@]}"; do + unset members[$elem] + done + echo ${!members[@]} + } + + [[ "$delete" == "true" ]] && { + local -a modules_delete=( $(set_difference "${destination_modules[*]}" "${selected_modules[*]}") ) + for m in "${modules_delete[@]}"; do + delete_module "$dryrun" "$m" "$dst_dir" + done + unset modules_delete + } + + + local -a modules_copy=( $(set_difference "${selected_modules[*]}" "${destination_modules[*]}") ) + [[ -z $modules_copy ]] || { + if [[ "$dryrun" != "false" ]]; then + echo "(dryrun) update: $dst_dir/$PSI_CONFIG_DIR from $src_dir/$PSI_CONFIG_DIR" 1>&2 + else + ( + local -a extraoption="$( [[ "$delete" == "true" ]] && echo --delete )" + cd "$src_dir" + rsync --recursive --links --perms --relative $extraoption --verbose --exclude .git "$PSI_CONFIG_DIR" "$dst_dir" + echo "updated: $PSI_CONFIG_DIR from $src_dir" 1>&2 + ) + fi + for m in "${modules_copy[@]}"; do + copy_module "$dryrun" "$m" "$src_dir" "$dst_dir" + done + } + unset modules_copy +} + +sync_modules "$@" diff --git a/scripts/Bootstrap/modulecmd b/scripts/Bootstrap/modulecmd new file mode 100644 index 0000000..0fa91d4 --- /dev/null +++ b/scripts/Bootstrap/modulecmd @@ -0,0 +1,1140 @@ +#!/opt/psi/Tools/Pmodules/0.99.0/bin/bash + +declare -r PMODULES_DIR=$( cd "$(dirname $0)/.." && pwd ) +declare -r version='0.99.0' +declare -r modulecmd="${PMODULES_DIR}/bin/modulecmd.tcl" +#declare -rx TCL_LIBRARY="${PMODULES_DIR}/lib/tcl8.6" + +declare -r modulepath_root="${PSI_PREFIX}/${PSI_MODULES_ROOT}" +declare -ra modulepath=( ${MODULEPATH//:/ } ) + +if set -o | grep 'xtrace' | grep -q 'on'; then + declare -r __XTRACE__='on' +else + declare -r __XTRACE__='off' +fi + +declare output_function='human_readable_output' +declare verbosity='silent' +declare userlvl='expert' +declare sw_force='no' +declare sw_create='no' + + +print_version() { + echo " +Pmodules ${version} using Tcl Environment Modules 3.2.10 +Copyright GNU GPL v2 +" 1>&2 +} + +usage() { + print_version + echo " +Usage: module [ switches ] [ subcommand ] [subcommand-args ] + +Switches: + -H|--help this usage info + -V|--version modules version & configuration options + -f|--force force active dependency resolution + -t|--terse terse format avail and list format + -l|--long long format avail and list format + -h|--human readable format avail and list format + -v|--verbose enable verbose messages + -s|--silent disable verbose messages + -c|--create create caches for avail and apropos + -i|--icase ignored + -u|--userlvl set user level to (nov[ice],exp[ert],adv[anced]) + Available SubCommands and Args: + + add|load modulefile [modulefile ...] + + rm|unload modulefile [modulefile ...] + + switch|swap [modulefile1] modulefile2 + + display|show modulefile [modulefile ...] + + avail [modulefile [modulefile ...]] + + search [ switches ] [ args ] + + use [-a|--append] [dir|family|release ...] + + unuse dir|family|release [dir|family|release ...] + + update + + refresh + + purge + + list + + clear + + help [modulefile|subcommand] + + whatis [modulefile [modulefile ...]] + + apropos|keyword string + + initadd modulefile [modulefile ...] + + initprepend modulefile [modulefile ...] + + initrm modulefile [modulefile ...] + + initswitch modulefile1 modulefile2 + + initlist + + initclear + + sync [ switches ] +" 1>&2 + +} + + +subcommand_help_add() { + echo " +add modulefile... +load modulefile... + Load modulefile(s) into the shell environment. Loading a + 'family-head' will extend the MODULEPATH. E.g.: loading a + compiler makes additional modules like openmpi and libraries + compiled with this compiler available. +" 1>&2 +} + +subcommand_help_load() { + subcommand_help_add +} + +subcommand_help_rm() { + echo " +rm modulefile... +unload modulefile... + Remove modulefile(s) from the shell environment. Removing + a 'family-head' will also unload all modules in the family. +" 1>&2 +} + +subcommand_help_unload() { + subcommand_help_rm +} + +subcommand_help_switch() { + echo " +switch [modulefile1] modulefile2 +swap [modulefile1] modulefile2 + Switch loaded modulefile1 with modulefile2. If modulefile1 + is not specified, then it is assumed to be the currently + loaded module with the same root name as modulefile2. +" 1>&2 +} + +subcommand_help_swap() { + subcommand_help_switch +} + +subcommand_help_display() { + echo " +display modulefile... +show modulefile... + Display information about one or more modulefiles. The + display sub-command will list the full path of the + modulefile(s) and all (or most) of the environment changes + the modulefile(s) will make if loaded. It will not display + any environment changes found within conditional statements. +" 1>&2 +} + +subcommand_help_show() { + subcommand_help_display +} + +subcommand_help_apropos() { + echo " +apropos string +keyword string Seeks through the 'whatis' informations of all modulefiles for + the specified string. All module-whatis informations matching + the string will be displayed. + +" 1>&2 +} + +subcommand_help_keyword() { + subcommand_help_apropos +} + + +subcommand_help_avail() { + echo " +avail string List all available modulefiles in the current MODULEPATH. If + an argument is given, then each directory in the MODULEPATH + is searched for modulefiles whose pathname match the argument. + + This command does *not* display all installed modules on the + system. Only *loadable* modules are listed. The list of + available modules may change either by loading other modules, + e.g. a compiler, or with the sub-command 'use'. +" 1>&2 +} + +subcommand_help_search() { + echo " +search [switches] STRING... + Search installed modules. If an argument is given, search + for modules whose name match the argument. + +SWITCHES: +--no-header Suppress output of a header. + +--release=RELEASE + Search for modules within this release. You can specify this + switch multiple times. Without this switch, the used releases + will be searched. + +-a|--all-releases + Search within all releases. + +--with=STRING + Search for modules compiled with modules matching string. The + command + + module search --with=gcc/4.8.3 + + lists all modules in the hierarchy compiled with gcc 4.8.3. +" 1>&2 +} + +subcommand_help_use() { + echo " +use [-a|--append|-p|--prepend] [directory|family|release...] + Without arguments this sub-command displays information about + the module search path, used families and releases. You can + use this sub-command to get a list of available families and + releases. + + With a directory as argument, this directory will either be + prepended or appended to the module search path. The default + is to prepend the directory. + + With a family as argument, the modules in this family will + be made available. + + With a release as argument, this modules with this release + will be made available. +" 1>&2 +} + +subcommand_help_unuse() { + echo " +unuse directory|family|release... + Remove the given directory, family or release from the search + path. +" 1>&2 +} +subcommand_help_update() { + echo " +update Attempt to reload all loaded modulefiles. +" 1>&2 +} + +subcommand_help_refresh() { + echo " +refresh Force a refresh of all non-persistent components of currently + loaded modules. This should be used on derived shells where + aliases need to be reinitialized but the environment variables + have already been set by the currently loaded modules. +" 1>&2 +} + +subcommand_help_purge() { + echo " +purge Unload all loaded modulefiles. +" 1>&2 +} + +subcommand_help_list() { + echo " +list List loaded modules. +" 1>&2 +} + +subcommand_help_clear() { + echo " +clear Force the Modules package to believe that no modules are + currently loaded. +" 1>&2 +} + +subcommand_help_whatis() { + echo " +whatis [modulefile...] + Display the information set up by the module-whatis commands + inside the specified modulefile(s). If no modulefile is + specified, all 'whatis' lines will be shown. +" 1>&2 +} + +subcommand_help_initadd() { + echo " +initadd modulefile... + Add modulefile(s) to the shell's initialization file in the + user's home directory. The startup files checked (in order) + are: + + csh - .modules, .cshrc(.ext), .csh_variables, and + .login(.ext) + tcsh - .modules, .tcshrc, .cshrc(.ext), .csh_variables, + and .login(.ext) + (k)sh - .modules, .profile(.ext), and .kshenv(.ext) + bash - .modules, .bash_profile, .bash_login, + .profile(.ext) and .bashrc(.ext) + zsh - .modules, .zcshrc(.ext), .zshenv(.ext), and + .zlogin(.ext) + + If a 'module load' line is found in any of these files, the + modulefile(s) is(are) appended to any existing list of + modulefiles. The 'module load' line must be located in at + least one of the files listed above for any of the 'init' + sub-commands to work properly. If the 'module load' line + line is found in multiple shell initialization files, all + of the lines are changed. +" 1>&2 +} + +subcommand_help_initprepend() { + echo " +initprepend modulefile... + Does the same as initadd but prepends the given modules to + the beginning of the list. +" 1>&2 +} + +subcommand_help_initrm() { + echo " +initrm modulefile... + Remove modulefile(s) from the shell's initialization files. +" 1>&2 +} + +subcommand_help_initswitch() { + echo " +initswitch modulefile1 modulefile2 + Switch modulefile1 with modulefile2 in the shell's initialization files. +" 1>&2 +} + +subcommand_help_initlist() { + echo " +initlist List all of the modulefiles loaded from the shell's initialization file. +" 1>&2 +} + +subcommand_help_initclear() { + echo " +initclear Clear all of the modulefiles from the shell's initialization files. +" 1>&2 +} + +subcommand_help_sync() { + echo " +sync [--from=DIR] [--to=DIR] [--dryrun] [--delete] + Synchronize two Pmodules hierarchies. +" 1>&2 +} + +append_path () { + local -r P=$1 + local -r d=$2 + + if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then + if [[ -z ${!P} ]]; then + eval $P=${d} + else + eval $P=${!P}:${d} + fi + fi +} + +prepend_path () { + local -r P=$1 + local -r d=$2 + + if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then + if [[ -z ${!P} ]]; then + eval $P=${d} + else + eval $P=${d}:${!P} + fi + fi +} + +remove_path() { + local -r P=$1 + local -r d=$2 + local new_path='' + local -r _P=( ${!P//:/ } ) + # loop over all entries in path + for entry in "${_P[@]}"; do + [[ "${entry}" != "${d}" ]] && new_path+=":${entry}" + done + # remove leading ':' + eval ${P}="${new_path:1}" +} + +module_is_available() { + is_loadable() { + release=$( get_release "$1" ) + [[ :${PSI_USED_RELEASES}: =~ ${release} ]] && return 0 + return 1 + } + + [[ -f $1 ]] && return 0 + for dir in "${modulepath[@]}"; do + if [[ -d ${dir}/$1 ]]; then + while read fname; do + is_loadable "${fname}" && return 0 + done < <(find "${dir}" -type l -o -type f \! -name ".*") + else + [[ -f ${dir}/$1 ]] || continue + [[ -r ${dir}/$1 ]] || continue + is_loadable "${dir}/$1" && return 0 + fi + done + return 1 +} + +get_release() { + local -r modulefile=$1 + local -r releasefile="${modulefile%/*}/.release-${modulefile##*/}" + if [[ -r ${releasefile} ]]; then + local -r data=$( < "${releasefile}" ) + local -r release=$( echo ${data} ) + else + local -r release='unstable' + fi + echo ${release} +} + +if [[ ${PSI_RELEASES_CONF} ]] && [[ -r "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_RELEASES_CONF}" ]]; then + declare -r available_releases=:$(< "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_RELEASES_CONF}"): +else + # set defaults, if file doesn't exist or isn't readable + declare -r available_releases=":unstable:stable:deprecated:" +fi +declare used_releases=":${PSI_USED_RELEASES}:" + +is_release() { + [[ ${available_releases} =~ :$1: ]] +} + +is_used_release() { + [[ ${used_releases} =~ :$1: ]] +} + +declare available_families=':' +declare family +declare depth +while read family depth rest; do + if (( depth == 0 )); then + available_families+="${family}:" + fi +done < "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_FAMILY_CONF}" +declare used_families=":${PSI_LOADEDFAMILIES}:" + +is_family() { + [[ ${available_families} =~ :$1: ]] +} + +is_used_family() { + [[ ${used_families} =~ :$1: ]] +} + +module_is_loaded() { + [[ :${LOADEDMODULES}: =~ :$1: ]] +} + +subcommand_generic0() { + local -r subcommand=$1 + shift + if [[ $# != 0 ]]; then + echo "${subcommand}: no arguments allowed" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" +} + +subcommand_generic0plus() { + local -r subcommand=$1 + shift + "${modulecmd}" "${shell}" "${subcommand}" "$@" +} + +subcommand_generic1() { + local -r subcommand=$1 + shift + if [[ $# != 1 ]]; then + echo "${subcommand}: only one argument allowed" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" "$1" +} + +subcommand_generic1plus() { + local -r subcommand=$1 + shift + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" "$@" +} + +subcommand_load() { + output_load_hints() { + local -ra rels=( ${available_releases//:/ } ) + for rel in "${rels[@]}"; do + eval $( subcommand_use "${rel}" ) + if module_is_available "${m}"; then + echo "${m}: is ${rel}! If you really want to load this module, run" 1>&2 + echo -e "\tmodule use ${rel}" 1>&2 + echo "before running" 1>&2 + echo -e "\tmodule load ${m}" 1>&2 + exit 42 + fi + done + local something_found='no' + local -a output=() + local -a release=() + local -a loadable=() + local -i i=0 + local -i n=0 + while read -a line; do + output[n]="module load ${line[@]:3} ${line[0]}" + release[n]=${line[1]} + if [[ ":${PSI_USED_RELEASES}:" =~ "${release[n]}" ]]; then + loadable[n]='yes' + else + loadable[n]='no' + fi + n+=1 + done < <(subcommand_search "${m}" -a --no-header 2>&1) + if (( n > 0 )); then + echo "The following modules chain(s) are available:" 1>&2 + for ((i=n-1; i >=0; i--)); do + echo -en "${output[i]}\t# ${release[i]}" 1>&2 + if [[ "${loadable[i]}" == "no" ]]; then + echo -e "\t# ${release[i]}" 1>&2 + else + echo "" 1>&2 + fi + done + else + echo "${m}: module does not exist!" 1>&2 + fi + } + + local -r m=$1 + if module_is_available "${m}"; then + "${modulecmd}" "${shell}" load "${m}" + else + if [[ ${userlvl} = 'novice' ]]; then + output_load_hints + else + echo "${m}: module unavailable" 1>&2 + fi + fi +} + + +subcommand_unload() { + # :FIXME: add dependency tests: don't unload if module is required be + # another module + subcommand_generic1plus unload "$@" +} + +subcommand_swap() { + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + if [[ $# > 2 ]]; then + echo "${subcommand}: to many arguments" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" swap "$@" +} + +subcommand_show() { + subcommand_generic1plus show "$@" +} + +# +# get all available modules in given directory. +# return list like +# modulename1 release1 modulename2 release2 ... +# +get_available_modules() { + local -r dir=$1 + local -r module=$2 + local -r use_releases=${3:-${PSI_USED_RELEASES}} + local -a mods=() + while read mod; do + local release=$( get_release "${dir}/${mod}" ) + + if [[ :${use_releases}: =~ :${release}: ]]; then + mods+=( "${mod}" ${release} ) + fi + done < <(MODULEPATH="${dir}" "${modulecmd}" bash -t avail "${module}" 2>&1 | tail -n +2) + echo "${mods[@]}" +} + + +# :FIXXME: support for all output formats +subcommand_avail() { + # use this variable in the output functions + local -a mods=() + local dir='' + + # get number of columns of terminal + eval $(resize) + + output_header() { + let i=($COLUMNS-${#dir})/2-2 + printf -- "%0.s-" $(seq 1 $i) 1>&2 + printf -- " %s " "${dir}" 1>&2 + printf -- "%0.s-" $(seq 1 $i) 1>&2 + printf -- "\n" 1>&2 + } + + terse_output() { + output_header + for (( i=0; i<${#mods[@]}; i+=2 )); do + local mod=${mods[i]} + local release=${mods[i+1]} + case $release in + stable ) + out='' + ;; + * ) + out=${release} + ;; + esac + printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 + done + echo 1>&2 + } + + long_output() { + output_header + for (( i=0; i<${#mods[@]}; i+=2 )); do + local mod=${mods[i]} + local release=${mods[i+1]} + case $release in + stable ) + out='' + ;; + * ) + out=${release} + ;; + esac + printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 + done + echo 1>&2 + } + + human_readable_output() { + output_header + + local -i column=$COLUMNS + local -i colsize=16 + for ((i=0; i<${#mods[@]}; i+=2)); do + if [[ ${userlvl} == 'novice' ]]; then + local release=${mods[i+1]} + case ${mods[i+1]} in + stable ) + mod=${mods[i]} + ;; + * ) + mod="${mods[i]}(${release:0:1})" + ;; + esac + else + mod=${mods[i]} + fi + local -i len=${#mod} + local -i span=$(( len / 16 + 1 )) + local -i colsize=$(( span * 16 )) + if (( column+len >= COLUMNS )); then + printf -- "\n" 1>&2 + column=0 + fi + if (( column+colsize < COLUMNS )); then + fmt="%-${colsize}s" + else + fmt="%-s" + fi + printf "${fmt}" "${mod}" 1>&2 + column+=colsize + done + printf -- "\n\n" 1>&2 + } + + if [[ $# == 0 ]]; then + set -- '' + fi + while (( $# > 0 )); do + local module=$1 + for dir in "${modulepath[@]}"; do + mods=( $( get_available_modules "${dir}" "${module}" ) ) + [[ ${#mods[@]} == 0 ]] && continue + + ${output_function} + done + shift + done +} + +subcommand_use() { + if [[ $# == 0 ]]; then + local f + local r + echo -e "Used families:" 1>&2 + for f in ${used_families//:/ }; do + echo -e "\t${f}" 1>&2 + done + echo -e "\nFamilies you may use in addition:" 1>&2 + for f in ${available_families//:/ }; do + if ! is_used_family $f; then + echo -e "\t${f}" 1>&2 + fi + done + + echo -e "\nUsed releases:" 1>&2 + for r in ${used_releases//:/ }; do + echo -e "\t${r}" 1>&2 + done + echo -e "\nReleases you may use in addition:" 1>&2 + for r in ${available_releases//:/ }; do + if ! is_used_release $r; then + echo -e "\t${r}" + fi + done + + echo -e "\nAdditonal directories in MODULEPATH:" 1>&2 + for (( i=0; i<${#modulepath[@]}; i++)); do + if [[ ! ${modulepath[i]} =~ ${PSI_PREFIX} ]]; then + echo -e "\t${modulepath[i]}" 1>&2 + fi + done + else + local dirs_to_add=() + local subcommand_switches='' + while (( $# > 0)); do + arg=$1 + if [[ ${arg} == -a ]] || [[ ${arg} == --append ]]; then + subcommand_switches='--append' + elif [[ ${arg} == -p ]] || [[ ${arg} == --prepend ]]; then + subcommand_switches='' + elif is_release "${arg}"; then + # releases are always *appended* + append_path PSI_USED_RELEASES "${arg}" + elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulepath_root}/${arg} ]]; then + dirs_to_add+=( ${modulepath_root}/${arg} ) + elif [[ -d ${arg} ]]; then + local normalized_dir=$(cd "${arg}" && pwd) + dirs_to_add+=( ${normalized_dir} ) + elif [[ ${arg} =~ "-*" ]]; then + echo "${0##_}: illegal switch: ${arg}" 1>&2 + return 3 + else + echo "${0##_}: neither a directory, release or family: ${arg}" 1>&2 + return 3 + fi + shift + done + echo "export PSI_USED_RELEASES=${PSI_USED_RELEASES}" + [[ ${#dirs_to_add[@]} == 0 ]] && return + + subcommand_generic1plus use ${subcommand_switches} "${dirs_to_add[@]}" + fi +} + +subcommand_unuse() { + local dirs_to_remove=() + while (( $# > 0)); do + arg=$1 + if is_release "${arg}"; then + remove_path PSI_USED_RELEASES "${arg}" + elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulepath_root}/${arg} ]]; then + dirs_to_remove+=( ${modulepath_root}/${arg} ) + elif [[ -d ${arg} ]]; then + local normalized_dir=$(cd "${arg}" && pwd) + dirs_to_remove+=( ${normalized_dir} ) + elif [[ ${arg} =~ "-*" ]]; then + echo "${0##_}: illegal switch: ${arg}" 1>&2 + return 3 + else + echo "${0##_}: not a directory: ${arg}" 1>&2 + return 3 + fi + shift + done + echo "export PSI_USED_RELEASES=${PSI_USED_RELEASES}" + [[ ${#dirs_to_remove[@]} == 0 ]] && return + subcommand_generic1plus unuse "${dirs_to_remove[@]}" +} + +subcommand_update() { + subcommand_generic0 update "$@" +} + +subcommand_refresh() { + subcommand_generic0 refresh "$@" +} + +subcommand_purge() { + subcommand_generic0 purge "$@" +} + +subcommand_list() { + subcommand_generic0 list "$@" +} + +subcommand_clear() { + subcommand_generic0 clear "$@" +} + +subcommand_search() { + local modules=() + local with_modules='//' + local _print_header='yes' + local use_releases=':' + local -r fmt="%-20s %-10s %-12s %-s\n" + + # no args + print_header() { + printf '\n' 1>&1 + printf "${fmt}" "Module" "Release" "Family" "Requires" 1>&2 + printf -- '-%.0s' {1..60} 1>&2 + printf '\n' 1>&2 + } + + # args: + # $1: module name pattern + search () { + local -r module=$1 + # we must write temporary results to a file for sorting + local -r tmpfile=$( mktemp /tmp/$(basename $0).XXXXXX ) || exit 1 + local family depth unused + # loop over all families + while read family depth unused; do + # get all potential directories of family $f with module-files + local mpaths=( $(find \ + "${modulepath_root}/${family}" \ + -type d \ + -mindepth ${depth} -maxdepth ${depth} \ + 2>/dev/null)) + local mpath + for mpath in "${mpaths[@]}"; do + # get dependencies encoded in directory name + local p="${mpath/${modulepath_root}}" + p=( ${p//\// } ) + local deps=() + local -i i + for ((i=1; i < ${#p[@]}; i+=2)); do + deps+=( ${p[i]}/${p[i+1]} ) + done + local requires=${deps[@]} + + # get and print all available modules in $mpath + # with respect to the requested releases + local mods=( $( get_available_modules \ + "${mpath}" \ + "${module}" \ + "${use_releases}" ) ) + [[ ${#mods[@]} == 0 ]] && continue + for (( i=0; i<${#mods[@]}; i+=2 )); do + printf "${fmt}" ${mods[i]} "${mods[i+1]}" \ + ${family} "${requires}" >> "${tmpfile}" + done + done + done < "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_FAMILY_CONF}" + sort -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | awk "${with_modules}" 1>&2 + + rm -f "${tmpfile}" + } + + + while (( $# > 0 )); do + case $1 in + --no-header ) + _print_header='no' + ;; + --release=* ) + _val=${1/--release=} + if is_release "${_val}"; then + use_releases+="${_val}:" + else + echo "${_val}: illegal release name." 1>&2 + exit 1 + fi + ;; + --with=* ) + _arg=${1/--with=} + if [[ -z ${_arg} ]]; then + echo "$1: module missing." 1>&2 + exit 1 + fi + with_modules+=" && / ${_arg//\//\\/}/" + ;; + -a | --all-releases ) + use_releases=${available_releases} + ;; + -? | -h | --help ) + usage + ;; + -* ) + echo "$1: invalid argument." 1>&2 + exit 1 + ;; + * ) + modules+=( $1 ) + ;; + esac + shift + done + + if [[ "${use_releases}" == ":" ]]; then + use_releases=":${PSI_USED_RELEASES}:" + fi + + [[ "${_print_header}" == "yes" ]] && print_header + if [[ ${#modules[@]} == 0 ]]; then + modules+=( '' ) + fi + + for module in "${modules[@]}"; do + search "${module}" + done +} + +subcommand_help() { + if [[ $# == 0 ]]; then + usage + elif typeset -F subcommand_help_$1 > /dev/null 2>&1 ; then + # help for sub-command + subcommand_help_$1 + else + # :FIXME: print help of newest *available* module + # (respecting PSI_USED_RELEASES) + subcommand_generic1plus help "$@" + fi +} + +subcommand_whatis() { + subcommand_generic0plus whatis "$@" +} + +subcommand_apropos() { + subcommand_generic1 apropos "$@" +} + +subcommand_initadd() { + subcommand_generic1plus initadd "$@" +} + +subcommand_initprepend() { + subcommand_generic1plus initprepend "$@" +} + +subcommand_initrm() { + subcommand_generic1plus initrm "$@" +} + +subcommand_initswitch() { + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + if [[ $# > 2 ]]; then + echo "${subcommand}: to many arguments" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" initswap "$@" +} + +subcommand_initlist() { + subcommand_generic0 initlist "$@" +} + +subcommand_initclear() { + subcommand_generic0 initclear "$@" +} + +subcommand_sync() { + local _srcdir + local _dstdir + local _dryrun='no' + local _delete='no' + local _args=() + while (( $# > 0 )); do + case $1 in + --from=* ) + _srcdir=${1/--from=} + _args+=( $1 ) + ;; + --to=* ) + _dstdir=${1/--to=} + _args+=( $1 ) + ;; + --dry-run ) + _dryrun='yes' + _args+=( --dryrun ) + ;; + --delete ) + _delete='yes' + _args+=( $1 ) + ;; + * ) + echo "$1: invalid argument." 1>&2 + exit 1 + ;; + esac + shift + done + ${PMODULES_HOME}/bin/modsync.bash "${_args[@]}" +} + +case $1 in + bash ) + declare shell=$1 + ;; + * ) + echo "$1: unsupported shell" 1>&2 + exit 1 + ;; +esac +shift + +while (( $# > 0 )); do + case $1 in + -h | -H | -\? | --help | -help ) + usage + exit 1 + ;; + -V | --version ) + print_version + exit 1 + ;; + -f | --force ) + # ignored + ;; + -t | --terse ) + output_function='terse_output' + ;; + -l | --long ) + output_function='long_output' + ;; + --human ) + output_function='human_readable_output' + ;; + --versbose ) + verbosity='verbose' + ;; + --silent ) + verbosity='silent' + ;; + -c | --create ) + sw_create='yes' + ;; + -i | --icase ) + # ignored + ;; + -u | --userlvl ) + case $2 in + nov | novi | novic | novice ) + userlvl='novice' + ;; + exp | expe | exper | expert ) + userlvl='expert' + ;; + adv | adva | advan | advanc | advance | advanced ) + userlvl='advanced' + ;; + * ) + echo "$1: unknown user level" 1>&2 + exit 1 + ;; + esac + shift + ;; + -* ) + echo "$1: unknown switch.\n" 1>&2 + exit 1 + ;; + add|load ) + subcommand='subcommand_load' + shift + sargs=( $* ) + shift $# + ;; + rm|unload ) + subcommand='subcommand_unload' + shift + sargs=( $* ) + shift $# + ;; + switch|swap ) + subcommand='subcommand_swap' + shift + sargs=( $* ) + shift $# + ;; + display|show ) + subcommand='subcommand_show' + shift + sargs=( $* ) + shift $# + ;; + apropos|keyword ) + subcommand='subcommand_apropos' + shift + sargs=( $* ) + shift $# + ;; + avail|search|use|unuse|update|refresh|purge|list|clear|whatis|help ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + initadd|initprepend|initrm|initswitch|initlist|initclear ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + sync ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + * ) + echo "$1: unknown sub-command" 1>&2 + exit 1 + esac + shift +done + +#for ((i=0; i<$#; i++)); do +# case "${sargs[i]}" in +# -a | --append ) +# if [[ ${subcommand} != use ]]; then +# echo "${subcommand}: unsupported switch '$1'" 1>&2 +# exit 1 +# fi +# ;; +# -* ) +# echo "${subcommand}: unsupported switch '$1'" 1>&2 +# exit 1 +# ;; +# [a-zA-Z0-9] ) +# : +# ;; +# * ) +# echo "$1: illegal module name" 1>&2 +# ;; +# esac +#done + +$subcommand "${sargs[@]}" + +# Local Variables: +# mode: sh +# sh-basic-offset: 8 +# tab-width: 8 +# End: diff --git a/scripts/Bootstrap/modulecmd.bash b/scripts/Bootstrap/modulecmd.bash new file mode 100755 index 0000000..01293d9 --- /dev/null +++ b/scripts/Bootstrap/modulecmd.bash @@ -0,0 +1,1140 @@ +#!@PMODULES_HOME@/bin/bash + +declare -r PMODULES_DIR=$( cd "$(dirname $0)/.." && pwd ) +declare -r version='@PMODULES_VERSION@' +declare -r modulecmd="${PMODULES_DIR}/bin/modulecmd.tcl" +#declare -rx TCL_LIBRARY="${PMODULES_DIR}/lib/tcl8.6" + +declare -r modulepath_root="${PSI_PREFIX}/${PSI_MODULES_ROOT}" +declare -ra modulepath=( ${MODULEPATH//:/ } ) + +if set -o | grep 'xtrace' | grep -q 'on'; then + declare -r __XTRACE__='on' +else + declare -r __XTRACE__='off' +fi + +declare output_function='human_readable_output' +declare verbosity='silent' +declare userlvl='expert' +declare sw_force='no' +declare sw_create='no' + + +print_version() { + echo " +Pmodules ${version} using Tcl Environment Modules @MODULES_VERSION@ +Copyright GNU GPL v2 +" 1>&2 +} + +usage() { + print_version + echo " +Usage: module [ switches ] [ subcommand ] [subcommand-args ] + +Switches: + -H|--help this usage info + -V|--version modules version & configuration options + -f|--force force active dependency resolution + -t|--terse terse format avail and list format + -l|--long long format avail and list format + -h|--human readable format avail and list format + -v|--verbose enable verbose messages + -s|--silent disable verbose messages + -c|--create create caches for avail and apropos + -i|--icase ignored + -u|--userlvl set user level to (nov[ice],exp[ert],adv[anced]) + Available SubCommands and Args: + + add|load modulefile [modulefile ...] + + rm|unload modulefile [modulefile ...] + + switch|swap [modulefile1] modulefile2 + + display|show modulefile [modulefile ...] + + avail [modulefile [modulefile ...]] + + search [ switches ] [ args ] + + use [-a|--append] [dir|family|release ...] + + unuse dir|family|release [dir|family|release ...] + + update + + refresh + + purge + + list + + clear + + help [modulefile|subcommand] + + whatis [modulefile [modulefile ...]] + + apropos|keyword string + + initadd modulefile [modulefile ...] + + initprepend modulefile [modulefile ...] + + initrm modulefile [modulefile ...] + + initswitch modulefile1 modulefile2 + + initlist + + initclear + + sync [ switches ] +" 1>&2 + +} + + +subcommand_help_add() { + echo " +add modulefile... +load modulefile... + Load modulefile(s) into the shell environment. Loading a + 'family-head' will extend the MODULEPATH. E.g.: loading a + compiler makes additional modules like openmpi and libraries + compiled with this compiler available. +" 1>&2 +} + +subcommand_help_load() { + subcommand_help_add +} + +subcommand_help_rm() { + echo " +rm modulefile... +unload modulefile... + Remove modulefile(s) from the shell environment. Removing + a 'family-head' will also unload all modules in the family. +" 1>&2 +} + +subcommand_help_unload() { + subcommand_help_rm +} + +subcommand_help_switch() { + echo " +switch [modulefile1] modulefile2 +swap [modulefile1] modulefile2 + Switch loaded modulefile1 with modulefile2. If modulefile1 + is not specified, then it is assumed to be the currently + loaded module with the same root name as modulefile2. +" 1>&2 +} + +subcommand_help_swap() { + subcommand_help_switch +} + +subcommand_help_display() { + echo " +display modulefile... +show modulefile... + Display information about one or more modulefiles. The + display sub-command will list the full path of the + modulefile(s) and all (or most) of the environment changes + the modulefile(s) will make if loaded. It will not display + any environment changes found within conditional statements. +" 1>&2 +} + +subcommand_help_show() { + subcommand_help_display +} + +subcommand_help_apropos() { + echo " +apropos string +keyword string Seeks through the 'whatis' informations of all modulefiles for + the specified string. All module-whatis informations matching + the string will be displayed. + +" 1>&2 +} + +subcommand_help_keyword() { + subcommand_help_apropos +} + + +subcommand_help_avail() { + echo " +avail string List all available modulefiles in the current MODULEPATH. If + an argument is given, then each directory in the MODULEPATH + is searched for modulefiles whose pathname match the argument. + + This command does *not* display all installed modules on the + system. Only *loadable* modules are listed. The list of + available modules may change either by loading other modules, + e.g. a compiler, or with the sub-command 'use'. +" 1>&2 +} + +subcommand_help_search() { + echo " +search [switches] STRING... + Search installed modules. If an argument is given, search + for modules whose name match the argument. + +SWITCHES: +--no-header Suppress output of a header. + +--release=RELEASE + Search for modules within this release. You can specify this + switch multiple times. Without this switch, the used releases + will be searched. + +-a|--all-releases + Search within all releases. + +--with=STRING + Search for modules compiled with modules matching string. The + command + + module search --with=gcc/4.8.3 + + lists all modules in the hierarchy compiled with gcc 4.8.3. +" 1>&2 +} + +subcommand_help_use() { + echo " +use [-a|--append|-p|--prepend] [directory|family|release...] + Without arguments this sub-command displays information about + the module search path, used families and releases. You can + use this sub-command to get a list of available families and + releases. + + With a directory as argument, this directory will either be + prepended or appended to the module search path. The default + is to prepend the directory. + + With a family as argument, the modules in this family will + be made available. + + With a release as argument, this modules with this release + will be made available. +" 1>&2 +} + +subcommand_help_unuse() { + echo " +unuse directory|family|release... + Remove the given directory, family or release from the search + path. +" 1>&2 +} +subcommand_help_update() { + echo " +update Attempt to reload all loaded modulefiles. +" 1>&2 +} + +subcommand_help_refresh() { + echo " +refresh Force a refresh of all non-persistent components of currently + loaded modules. This should be used on derived shells where + aliases need to be reinitialized but the environment variables + have already been set by the currently loaded modules. +" 1>&2 +} + +subcommand_help_purge() { + echo " +purge Unload all loaded modulefiles. +" 1>&2 +} + +subcommand_help_list() { + echo " +list List loaded modules. +" 1>&2 +} + +subcommand_help_clear() { + echo " +clear Force the Modules package to believe that no modules are + currently loaded. +" 1>&2 +} + +subcommand_help_whatis() { + echo " +whatis [modulefile...] + Display the information set up by the module-whatis commands + inside the specified modulefile(s). If no modulefile is + specified, all 'whatis' lines will be shown. +" 1>&2 +} + +subcommand_help_initadd() { + echo " +initadd modulefile... + Add modulefile(s) to the shell's initialization file in the + user's home directory. The startup files checked (in order) + are: + + csh - .modules, .cshrc(.ext), .csh_variables, and + .login(.ext) + tcsh - .modules, .tcshrc, .cshrc(.ext), .csh_variables, + and .login(.ext) + (k)sh - .modules, .profile(.ext), and .kshenv(.ext) + bash - .modules, .bash_profile, .bash_login, + .profile(.ext) and .bashrc(.ext) + zsh - .modules, .zcshrc(.ext), .zshenv(.ext), and + .zlogin(.ext) + + If a 'module load' line is found in any of these files, the + modulefile(s) is(are) appended to any existing list of + modulefiles. The 'module load' line must be located in at + least one of the files listed above for any of the 'init' + sub-commands to work properly. If the 'module load' line + line is found in multiple shell initialization files, all + of the lines are changed. +" 1>&2 +} + +subcommand_help_initprepend() { + echo " +initprepend modulefile... + Does the same as initadd but prepends the given modules to + the beginning of the list. +" 1>&2 +} + +subcommand_help_initrm() { + echo " +initrm modulefile... + Remove modulefile(s) from the shell's initialization files. +" 1>&2 +} + +subcommand_help_initswitch() { + echo " +initswitch modulefile1 modulefile2 + Switch modulefile1 with modulefile2 in the shell's initialization files. +" 1>&2 +} + +subcommand_help_initlist() { + echo " +initlist List all of the modulefiles loaded from the shell's initialization file. +" 1>&2 +} + +subcommand_help_initclear() { + echo " +initclear Clear all of the modulefiles from the shell's initialization files. +" 1>&2 +} + +subcommand_help_sync() { + echo " +sync [--from=DIR] [--to=DIR] [--dryrun] [--delete] + Synchronize two Pmodules hierarchies. +" 1>&2 +} + +append_path () { + local -r P=$1 + local -r d=$2 + + if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then + if [[ -z ${!P} ]]; then + eval $P=${d} + else + eval $P=${!P}:${d} + fi + fi +} + +prepend_path () { + local -r P=$1 + local -r d=$2 + + if ! echo ${!P} | egrep -q "(^|:)${d}($|:)" ; then + if [[ -z ${!P} ]]; then + eval $P=${d} + else + eval $P=${d}:${!P} + fi + fi +} + +remove_path() { + local -r P=$1 + local -r d=$2 + local new_path='' + local -r _P=( ${!P//:/ } ) + # loop over all entries in path + for entry in "${_P[@]}"; do + [[ "${entry}" != "${d}" ]] && new_path+=":${entry}" + done + # remove leading ':' + eval ${P}="${new_path:1}" +} + +module_is_available() { + is_loadable() { + release=$( get_release "$1" ) + [[ :${PSI_USED_RELEASES}: =~ ${release} ]] && return 0 + return 1 + } + + [[ -f $1 ]] && return 0 + for dir in "${modulepath[@]}"; do + if [[ -d ${dir}/$1 ]]; then + while read fname; do + is_loadable "${fname}" && return 0 + done < <(find "${dir}" -type l -o -type f \! -name ".*") + else + [[ -f ${dir}/$1 ]] || continue + [[ -r ${dir}/$1 ]] || continue + is_loadable "${dir}/$1" && return 0 + fi + done + return 1 +} + +get_release() { + local -r modulefile=$1 + local -r releasefile="${modulefile%/*}/.release-${modulefile##*/}" + if [[ -r ${releasefile} ]]; then + local -r data=$( < "${releasefile}" ) + local -r release=$( echo ${data} ) + else + local -r release='unstable' + fi + echo ${release} +} + +if [[ ${PSI_RELEASES_CONF} ]] && [[ -r "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_RELEASES_CONF}" ]]; then + declare -r available_releases=:$(< "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_RELEASES_CONF}"): +else + # set defaults, if file doesn't exist or isn't readable + declare -r available_releases=":unstable:stable:deprecated:" +fi +declare used_releases=":${PSI_USED_RELEASES}:" + +is_release() { + [[ ${available_releases} =~ :$1: ]] +} + +is_used_release() { + [[ ${used_releases} =~ :$1: ]] +} + +declare available_families=':' +declare family +declare depth +while read family depth rest; do + if (( depth == 0 )); then + available_families+="${family}:" + fi +done < "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_FAMILY_CONF}" +declare used_families=":${PSI_LOADEDFAMILIES}:" + +is_family() { + [[ ${available_families} =~ :$1: ]] +} + +is_used_family() { + [[ ${used_families} =~ :$1: ]] +} + +module_is_loaded() { + [[ :${LOADEDMODULES}: =~ :$1: ]] +} + +subcommand_generic0() { + local -r subcommand=$1 + shift + if [[ $# != 0 ]]; then + echo "${subcommand}: no arguments allowed" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" +} + +subcommand_generic0plus() { + local -r subcommand=$1 + shift + "${modulecmd}" "${shell}" "${subcommand}" "$@" +} + +subcommand_generic1() { + local -r subcommand=$1 + shift + if [[ $# != 1 ]]; then + echo "${subcommand}: only one argument allowed" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" "$1" +} + +subcommand_generic1plus() { + local -r subcommand=$1 + shift + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" "${subcommand}" "$@" +} + +subcommand_load() { + output_load_hints() { + local -ra rels=( ${available_releases//:/ } ) + for rel in "${rels[@]}"; do + eval $( subcommand_use "${rel}" ) + if module_is_available "${m}"; then + echo "${m}: is ${rel}! If you really want to load this module, run" 1>&2 + echo -e "\tmodule use ${rel}" 1>&2 + echo "before running" 1>&2 + echo -e "\tmodule load ${m}" 1>&2 + exit 42 + fi + done + local something_found='no' + local -a output=() + local -a release=() + local -a loadable=() + local -i i=0 + local -i n=0 + while read -a line; do + output[n]="module load ${line[@]:3} ${line[0]}" + release[n]=${line[1]} + if [[ ":${PSI_USED_RELEASES}:" =~ "${release[n]}" ]]; then + loadable[n]='yes' + else + loadable[n]='no' + fi + n+=1 + done < <(subcommand_search "${m}" -a --no-header 2>&1) + if (( n > 0 )); then + echo "The following modules chain(s) are available:" 1>&2 + for ((i=n-1; i >=0; i--)); do + echo -en "${output[i]}\t# ${release[i]}" 1>&2 + if [[ "${loadable[i]}" == "no" ]]; then + echo -e "\t# ${release[i]}" 1>&2 + else + echo "" 1>&2 + fi + done + else + echo "${m}: module does not exist!" 1>&2 + fi + } + + local -r m=$1 + if module_is_available "${m}"; then + "${modulecmd}" "${shell}" load "${m}" + else + if [[ ${userlvl} = 'novice' ]]; then + output_load_hints + else + echo "${m}: module unavailable" 1>&2 + fi + fi +} + + +subcommand_unload() { + # :FIXME: add dependency tests: don't unload if module is required be + # another module + subcommand_generic1plus unload "$@" +} + +subcommand_swap() { + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + if [[ $# > 2 ]]; then + echo "${subcommand}: to many arguments" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" swap "$@" +} + +subcommand_show() { + subcommand_generic1plus show "$@" +} + +# +# get all available modules in given directory. +# return list like +# modulename1 release1 modulename2 release2 ... +# +get_available_modules() { + local -r dir=$1 + local -r module=$2 + local -r use_releases=${3:-${PSI_USED_RELEASES}} + local -a mods=() + while read mod; do + local release=$( get_release "${dir}/${mod}" ) + + if [[ :${use_releases}: =~ :${release}: ]]; then + mods+=( "${mod}" ${release} ) + fi + done < <(MODULEPATH="${dir}" "${modulecmd}" bash -t avail "${module}" 2>&1 | tail -n +2) + echo "${mods[@]}" +} + + +# :FIXXME: support for all output formats +subcommand_avail() { + # use this variable in the output functions + local -a mods=() + local dir='' + + # get number of columns of terminal + eval $(resize) + + output_header() { + let i=($COLUMNS-${#dir})/2-2 + printf -- "%0.s-" $(seq 1 $i) 1>&2 + printf -- " %s " "${dir}" 1>&2 + printf -- "%0.s-" $(seq 1 $i) 1>&2 + printf -- "\n" 1>&2 + } + + terse_output() { + output_header + for (( i=0; i<${#mods[@]}; i+=2 )); do + local mod=${mods[i]} + local release=${mods[i+1]} + case $release in + stable ) + out='' + ;; + * ) + out=${release} + ;; + esac + printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 + done + echo 1>&2 + } + + long_output() { + output_header + for (( i=0; i<${#mods[@]}; i+=2 )); do + local mod=${mods[i]} + local release=${mods[i+1]} + case $release in + stable ) + out='' + ;; + * ) + out=${release} + ;; + esac + printf "%-20s\t%s\n" "${mod}" "${out}" 1>&2 + done + echo 1>&2 + } + + human_readable_output() { + output_header + + local -i column=$COLUMNS + local -i colsize=16 + for ((i=0; i<${#mods[@]}; i+=2)); do + if [[ ${userlvl} == 'novice' ]]; then + local release=${mods[i+1]} + case ${mods[i+1]} in + stable ) + mod=${mods[i]} + ;; + * ) + mod="${mods[i]}(${release:0:1})" + ;; + esac + else + mod=${mods[i]} + fi + local -i len=${#mod} + local -i span=$(( len / 16 + 1 )) + local -i colsize=$(( span * 16 )) + if (( column+len >= COLUMNS )); then + printf -- "\n" 1>&2 + column=0 + fi + if (( column+colsize < COLUMNS )); then + fmt="%-${colsize}s" + else + fmt="%-s" + fi + printf "${fmt}" "${mod}" 1>&2 + column+=colsize + done + printf -- "\n\n" 1>&2 + } + + if [[ $# == 0 ]]; then + set -- '' + fi + while (( $# > 0 )); do + local module=$1 + for dir in "${modulepath[@]}"; do + mods=( $( get_available_modules "${dir}" "${module}" ) ) + [[ ${#mods[@]} == 0 ]] && continue + + ${output_function} + done + shift + done +} + +subcommand_use() { + if [[ $# == 0 ]]; then + local f + local r + echo -e "Used families:" 1>&2 + for f in ${used_families//:/ }; do + echo -e "\t${f}" 1>&2 + done + echo -e "\nFamilies you may use in addition:" 1>&2 + for f in ${available_families//:/ }; do + if ! is_used_family $f; then + echo -e "\t${f}" 1>&2 + fi + done + + echo -e "\nUsed releases:" 1>&2 + for r in ${used_releases//:/ }; do + echo -e "\t${r}" 1>&2 + done + echo -e "\nReleases you may use in addition:" 1>&2 + for r in ${available_releases//:/ }; do + if ! is_used_release $r; then + echo -e "\t${r}" + fi + done + + echo -e "\nAdditonal directories in MODULEPATH:" 1>&2 + for (( i=0; i<${#modulepath[@]}; i++)); do + if [[ ! ${modulepath[i]} =~ ${PSI_PREFIX} ]]; then + echo -e "\t${modulepath[i]}" 1>&2 + fi + done + else + local dirs_to_add=() + local subcommand_switches='' + while (( $# > 0)); do + arg=$1 + if [[ ${arg} == -a ]] || [[ ${arg} == --append ]]; then + subcommand_switches='--append' + elif [[ ${arg} == -p ]] || [[ ${arg} == --prepend ]]; then + subcommand_switches='' + elif is_release "${arg}"; then + # releases are always *appended* + append_path PSI_USED_RELEASES "${arg}" + elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulepath_root}/${arg} ]]; then + dirs_to_add+=( ${modulepath_root}/${arg} ) + elif [[ -d ${arg} ]]; then + local normalized_dir=$(cd "${arg}" && pwd) + dirs_to_add+=( ${normalized_dir} ) + elif [[ ${arg} =~ "-*" ]]; then + echo "${0##_}: illegal switch: ${arg}" 1>&2 + return 3 + else + echo "${0##_}: neither a directory, release or family: ${arg}" 1>&2 + return 3 + fi + shift + done + echo "export PSI_USED_RELEASES=${PSI_USED_RELEASES}" + [[ ${#dirs_to_add[@]} == 0 ]] && return + + subcommand_generic1plus use ${subcommand_switches} "${dirs_to_add[@]}" + fi +} + +subcommand_unuse() { + local dirs_to_remove=() + while (( $# > 0)); do + arg=$1 + if is_release "${arg}"; then + remove_path PSI_USED_RELEASES "${arg}" + elif [[ ! ${arg} =~ */* ]] && [[ -d ${modulepath_root}/${arg} ]]; then + dirs_to_remove+=( ${modulepath_root}/${arg} ) + elif [[ -d ${arg} ]]; then + local normalized_dir=$(cd "${arg}" && pwd) + dirs_to_remove+=( ${normalized_dir} ) + elif [[ ${arg} =~ "-*" ]]; then + echo "${0##_}: illegal switch: ${arg}" 1>&2 + return 3 + else + echo "${0##_}: not a directory: ${arg}" 1>&2 + return 3 + fi + shift + done + echo "export PSI_USED_RELEASES=${PSI_USED_RELEASES}" + [[ ${#dirs_to_remove[@]} == 0 ]] && return + subcommand_generic1plus unuse "${dirs_to_remove[@]}" +} + +subcommand_update() { + subcommand_generic0 update "$@" +} + +subcommand_refresh() { + subcommand_generic0 refresh "$@" +} + +subcommand_purge() { + subcommand_generic0 purge "$@" +} + +subcommand_list() { + subcommand_generic0 list "$@" +} + +subcommand_clear() { + subcommand_generic0 clear "$@" +} + +subcommand_search() { + local modules=() + local with_modules='//' + local _print_header='yes' + local use_releases=':' + local -r fmt="%-20s %-10s %-12s %-s\n" + + # no args + print_header() { + printf '\n' 1>&1 + printf "${fmt}" "Module" "Release" "Family" "Requires" 1>&2 + printf -- '-%.0s' {1..60} 1>&2 + printf '\n' 1>&2 + } + + # args: + # $1: module name pattern + search () { + local -r module=$1 + # we must write temporary results to a file for sorting + local -r tmpfile=$( mktemp /tmp/$(basename $0).XXXXXX ) || exit 1 + local family depth unused + # loop over all families + while read family depth unused; do + # get all potential directories of family $f with module-files + local mpaths=( $(find \ + "${modulepath_root}/${family}" \ + -type d \ + -mindepth ${depth} -maxdepth ${depth} \ + 2>/dev/null)) + local mpath + for mpath in "${mpaths[@]}"; do + # get dependencies encoded in directory name + local p="${mpath/${modulepath_root}}" + p=( ${p//\// } ) + local deps=() + local -i i + for ((i=1; i < ${#p[@]}; i+=2)); do + deps+=( ${p[i]}/${p[i+1]} ) + done + local requires=${deps[@]} + + # get and print all available modules in $mpath + # with respect to the requested releases + local mods=( $( get_available_modules \ + "${mpath}" \ + "${module}" \ + "${use_releases}" ) ) + [[ ${#mods[@]} == 0 ]] && continue + for (( i=0; i<${#mods[@]}; i+=2 )); do + printf "${fmt}" ${mods[i]} "${mods[i+1]}" \ + ${family} "${requires}" >> "${tmpfile}" + done + done + done < "${PSI_PREFIX}/${PSI_CONFIG_DIR}/${PSI_FAMILY_CONF}" + sort -k 1,1 -k 4,4 -k 5,5 "${tmpfile}" | awk "${with_modules}" 1>&2 + + rm -f "${tmpfile}" + } + + + while (( $# > 0 )); do + case $1 in + --no-header ) + _print_header='no' + ;; + --release=* ) + _val=${1/--release=} + if is_release "${_val}"; then + use_releases+="${_val}:" + else + echo "${_val}: illegal release name." 1>&2 + exit 1 + fi + ;; + --with=* ) + _arg=${1/--with=} + if [[ -z ${_arg} ]]; then + echo "$1: module missing." 1>&2 + exit 1 + fi + with_modules+=" && / ${_arg//\//\\/}/" + ;; + -a | --all-releases ) + use_releases=${available_releases} + ;; + -? | -h | --help ) + usage + ;; + -* ) + echo "$1: invalid argument." 1>&2 + exit 1 + ;; + * ) + modules+=( $1 ) + ;; + esac + shift + done + + if [[ "${use_releases}" == ":" ]]; then + use_releases=":${PSI_USED_RELEASES}:" + fi + + [[ "${_print_header}" == "yes" ]] && print_header + if [[ ${#modules[@]} == 0 ]]; then + modules+=( '' ) + fi + + for module in "${modules[@]}"; do + search "${module}" + done +} + +subcommand_help() { + if [[ $# == 0 ]]; then + usage + elif typeset -F subcommand_help_$1 > /dev/null 2>&1 ; then + # help for sub-command + subcommand_help_$1 + else + # :FIXME: print help of newest *available* module + # (respecting PSI_USED_RELEASES) + subcommand_generic1plus help "$@" + fi +} + +subcommand_whatis() { + subcommand_generic0plus whatis "$@" +} + +subcommand_apropos() { + subcommand_generic1 apropos "$@" +} + +subcommand_initadd() { + subcommand_generic1plus initadd "$@" +} + +subcommand_initprepend() { + subcommand_generic1plus initprepend "$@" +} + +subcommand_initrm() { + subcommand_generic1plus initrm "$@" +} + +subcommand_initswitch() { + if [[ $# == 0 ]]; then + echo "${subcommand}: missing argument" 1>&2 + return 3 + fi + if [[ $# > 2 ]]; then + echo "${subcommand}: to many arguments" 1>&2 + return 3 + fi + "${modulecmd}" "${shell}" initswap "$@" +} + +subcommand_initlist() { + subcommand_generic0 initlist "$@" +} + +subcommand_initclear() { + subcommand_generic0 initclear "$@" +} + +subcommand_sync() { + local _srcdir + local _dstdir + local _dryrun='no' + local _delete='no' + local _args=() + while (( $# > 0 )); do + case $1 in + --from=* ) + _srcdir=${1/--from=} + _args+=( $1 ) + ;; + --to=* ) + _dstdir=${1/--to=} + _args+=( $1 ) + ;; + --dry-run ) + _dryrun='yes' + _args+=( --dryrun ) + ;; + --delete ) + _delete='yes' + _args+=( $1 ) + ;; + * ) + echo "$1: invalid argument." 1>&2 + exit 1 + ;; + esac + shift + done + ${PMODULES_HOME}/bin/modsync.bash "${_args[@]}" +} + +case $1 in + bash ) + declare shell=$1 + ;; + * ) + echo "$1: unsupported shell" 1>&2 + exit 1 + ;; +esac +shift + +while (( $# > 0 )); do + case $1 in + -h | -H | -\? | --help | -help ) + usage + exit 1 + ;; + -V | --version ) + print_version + exit 1 + ;; + -f | --force ) + # ignored + ;; + -t | --terse ) + output_function='terse_output' + ;; + -l | --long ) + output_function='long_output' + ;; + --human ) + output_function='human_readable_output' + ;; + --versbose ) + verbosity='verbose' + ;; + --silent ) + verbosity='silent' + ;; + -c | --create ) + sw_create='yes' + ;; + -i | --icase ) + # ignored + ;; + -u | --userlvl ) + case $2 in + nov | novi | novic | novice ) + userlvl='novice' + ;; + exp | expe | exper | expert ) + userlvl='expert' + ;; + adv | adva | advan | advanc | advance | advanced ) + userlvl='advanced' + ;; + * ) + echo "$1: unknown user level" 1>&2 + exit 1 + ;; + esac + shift + ;; + -* ) + echo "$1: unknown switch.\n" 1>&2 + exit 1 + ;; + add|load ) + subcommand='subcommand_load' + shift + sargs=( $* ) + shift $# + ;; + rm|unload ) + subcommand='subcommand_unload' + shift + sargs=( $* ) + shift $# + ;; + switch|swap ) + subcommand='subcommand_swap' + shift + sargs=( $* ) + shift $# + ;; + display|show ) + subcommand='subcommand_show' + shift + sargs=( $* ) + shift $# + ;; + apropos|keyword ) + subcommand='subcommand_apropos' + shift + sargs=( $* ) + shift $# + ;; + avail|search|use|unuse|update|refresh|purge|list|clear|whatis|help ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + initadd|initprepend|initrm|initswitch|initlist|initclear ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + sync ) + subcommand=subcommand_$1 + shift + sargs=( $* ) + shift $# + ;; + * ) + echo "$1: unknown sub-command" 1>&2 + exit 1 + esac + shift +done + +#for ((i=0; i<$#; i++)); do +# case "${sargs[i]}" in +# -a | --append ) +# if [[ ${subcommand} != use ]]; then +# echo "${subcommand}: unsupported switch '$1'" 1>&2 +# exit 1 +# fi +# ;; +# -* ) +# echo "${subcommand}: unsupported switch '$1'" 1>&2 +# exit 1 +# ;; +# [a-zA-Z0-9] ) +# : +# ;; +# * ) +# echo "$1: illegal module name" 1>&2 +# ;; +# esac +#done + +$subcommand "${sargs[@]}" + +# Local Variables: +# mode: sh +# sh-basic-offset: 8 +# tab-width: 8 +# End: diff --git a/scripts/Bootstrap/modulerc b/scripts/Bootstrap/modulerc new file mode 100644 index 0000000..f7a7a28 --- /dev/null +++ b/scripts/Bootstrap/modulerc @@ -0,0 +1,8 @@ +#%Module1.0 + +setenv PSI_LIBMODULES "$env(PSI_PREFIX)/$env(PSI_CONFIG_DIR)/libmodules.tcl" + +if { ! [info exists env(PSI_LIBMODULES) ] } { + puts stderr "Module cannot be loaded, because the shell environment is not setup correctly." + exit 42 +} From f9f3be25dfff92365ed39f9b376ccae79842aa43 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:44:32 +0100 Subject: [PATCH 05/10] config/pmodule_version.conf: added --- config/pmodules_version.conf | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 config/pmodules_version.conf diff --git a/config/pmodules_version.conf b/config/pmodules_version.conf new file mode 100644 index 0000000..9908d11 --- /dev/null +++ b/config/pmodules_version.conf @@ -0,0 +1,2 @@ +PMODULES_VERSION=0.99.0 +MODULES_VERSION=3.2.10 From eed7d9e90e6cb5e123a410ec8fffe456e9ec52c2 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:45:10 +0100 Subject: [PATCH 06/10] scripts/System/getopt.build: added --- scripts/System/getopt.build | 42 +++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100755 scripts/System/getopt.build diff --git a/scripts/System/getopt.build b/scripts/System/getopt.build new file mode 100755 index 0000000..e502f0e --- /dev/null +++ b/scripts/System/getopt.build @@ -0,0 +1,42 @@ +#!/bin/bash + +source "$(dirname $0)/../../lib/libem.bash" + +function em.configure() { + : +} + +function em.build() { + case ${OS} in + Linux ) + declare -x LDFLAGS="-lintl -liconv" + ;; + Darwin ) + declare -x LDFLAGS="-lintl -liconv -framework CoreFoundation" + ;; + esac + + cd "${MODULE_SRCDIR}" + make -e +} + +function em.install() { + cd "${MODULE_SRCDIR}" + declare -x DESTDIR="${PREFIX}" + declare -x prefix='' + make -e install +} + +function em.cleanup_build() { + cd "${MODULE_SRCDIR}" + make -e realclean +} + +em.add_to_family 'Tools' +em.make_all + +# Local Variables: +# mode: sh +# sh-basic-offset: 8 +# tab-width: 8 +# End: From 62181b761b26c27a34e14a3b5e46994b84ad2117 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:58:37 +0100 Subject: [PATCH 07/10] changes to support easy bootstraping; re-orginazation of build scripts --- scripts/{System => Libraries}/giflib.build | 0 scripts/{System => Libraries}/gmp.build | 0 scripts/{System => Libraries}/libungif.build | 0 scripts/{System => Libraries}/mpc.build | 0 scripts/{System => Libraries}/mpfr.build | 0 scripts/{System => Libraries}/tiff.build | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename scripts/{System => Libraries}/giflib.build (100%) rename scripts/{System => Libraries}/gmp.build (100%) rename scripts/{System => Libraries}/libungif.build (100%) rename scripts/{System => Libraries}/mpc.build (100%) rename scripts/{System => Libraries}/mpfr.build (100%) rename scripts/{System => Libraries}/tiff.build (100%) diff --git a/scripts/System/giflib.build b/scripts/Libraries/giflib.build similarity index 100% rename from scripts/System/giflib.build rename to scripts/Libraries/giflib.build diff --git a/scripts/System/gmp.build b/scripts/Libraries/gmp.build similarity index 100% rename from scripts/System/gmp.build rename to scripts/Libraries/gmp.build diff --git a/scripts/System/libungif.build b/scripts/Libraries/libungif.build similarity index 100% rename from scripts/System/libungif.build rename to scripts/Libraries/libungif.build diff --git a/scripts/System/mpc.build b/scripts/Libraries/mpc.build similarity index 100% rename from scripts/System/mpc.build rename to scripts/Libraries/mpc.build diff --git a/scripts/System/mpfr.build b/scripts/Libraries/mpfr.build similarity index 100% rename from scripts/System/mpfr.build rename to scripts/Libraries/mpfr.build diff --git a/scripts/System/tiff.build b/scripts/Libraries/tiff.build similarity index 100% rename from scripts/System/tiff.build rename to scripts/Libraries/tiff.build From 074dda7b9ecdd2c8505d895211b73f62372b4d9f Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:58:54 +0100 Subject: [PATCH 08/10] changes to support easy bootstraping; re-orginazation of build scripts --- scripts/Compiler/H5root.build | 2 +- scripts/Compiler/OpenBLAS.build | 2 +- scripts/Compiler/OpenBLAS_OMP.build | 2 +- scripts/Compiler/SuperLU.build | 2 +- scripts/Compiler/UMFPACK.build | 2 +- scripts/HDF5/H5hut.build | 2 +- scripts/HDF5/netcdf.build | 2 +- scripts/HDF5_serial/H5hut_serial.build | 2 +- scripts/Libraries/giflib.build | 2 +- scripts/Libraries/gmp.build | 2 +- scripts/Libraries/libungif.build | 2 +- scripts/Libraries/mpc.build | 2 +- scripts/Libraries/mpfr.build | 2 +- scripts/Libraries/tiff.build | 2 +- scripts/Programming/Python.build | 2 +- scripts/Programming/Tcl.build | 2 +- scripts/Programming/autoconf.build | 2 +- scripts/Programming/automake.build | 2 +- scripts/Programming/cmake.build | 2 +- scripts/Programming/gcc.build | 2 +- scripts/Programming/gtest.build | 2 +- scripts/Programming/libtool.build | 2 +- scripts/Programming/lua.build | 2 +- scripts/Programming/m4.build | 2 +- scripts/Programming/psi-python27.build | 2 +- scripts/System/bash.build | 2 +- scripts/Tools/Modules.build | 2 +- scripts/Tools/dialog.build | 2 +- scripts/Tools/emacs.build | 2 +- scripts/Tools/global.build | 2 +- scripts/Tools/gnuplot.build | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/scripts/Compiler/H5root.build b/scripts/Compiler/H5root.build index 8843e87..46fe671 100755 --- a/scripts/Compiler/H5root.build +++ b/scripts/Compiler/H5root.build @@ -1,6 +1,6 @@ #!/bin/bash -source $(dirname $0)/../lib/libem.bash +source $(dirname $0)/../../lib/libem.bash function em.pre_configure() { ./autogen.sh diff --git a/scripts/Compiler/OpenBLAS.build b/scripts/Compiler/OpenBLAS.build index dadd1f4..2c980fb 100755 --- a/scripts/Compiler/OpenBLAS.build +++ b/scripts/Compiler/OpenBLAS.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { cat < "${MODULE_SRCDIR}/make.inc" diff --git a/scripts/Compiler/OpenBLAS_OMP.build b/scripts/Compiler/OpenBLAS_OMP.build index 0355b30..ee48ee0 100755 --- a/scripts/Compiler/OpenBLAS_OMP.build +++ b/scripts/Compiler/OpenBLAS_OMP.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { cat < "${MODULE_SRCDIR}/make.inc" diff --git a/scripts/Compiler/SuperLU.build b/scripts/Compiler/SuperLU.build index a4c416a..ea85951 100755 --- a/scripts/Compiler/SuperLU.build +++ b/scripts/Compiler/SuperLU.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { cat < "${MODULE_SRCDIR}/make.inc" diff --git a/scripts/Compiler/UMFPACK.build b/scripts/Compiler/UMFPACK.build index 0e2098b..7ee5afc 100755 --- a/scripts/Compiler/UMFPACK.build +++ b/scripts/Compiler/UMFPACK.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { cat < "${MODULE_SRCDIR}/SuiteSparse_config/SuiteSparse_config.mk" diff --git a/scripts/HDF5/H5hut.build b/scripts/HDF5/H5hut.build index 9783215..20c78d3 100755 --- a/scripts/HDF5/H5hut.build +++ b/scripts/HDF5/H5hut.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.pre_configure() { ./autogen.sh diff --git a/scripts/HDF5/netcdf.build b/scripts/HDF5/netcdf.build index e4d2fce..62485ba 100755 --- a/scripts/HDF5/netcdf.build +++ b/scripts/HDF5/netcdf.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.pre_configure() { : diff --git a/scripts/HDF5_serial/H5hut_serial.build b/scripts/HDF5_serial/H5hut_serial.build index 72cb8d7..9a4370b 100755 --- a/scripts/HDF5_serial/H5hut_serial.build +++ b/scripts/HDF5_serial/H5hut_serial.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { (cd "${MODULE_SRCDIR}" && ./autogen.sh) diff --git a/scripts/Libraries/giflib.build b/scripts/Libraries/giflib.build index 8060ae0..6f800ef 100755 --- a/scripts/Libraries/giflib.build +++ b/scripts/Libraries/giflib.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Libraries/gmp.build b/scripts/Libraries/gmp.build index 53830dc..4f9bf17 100755 --- a/scripts/Libraries/gmp.build +++ b/scripts/Libraries/gmp.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Libraries/libungif.build b/scripts/Libraries/libungif.build index 8060ae0..6f800ef 100755 --- a/scripts/Libraries/libungif.build +++ b/scripts/Libraries/libungif.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Libraries/mpc.build b/scripts/Libraries/mpc.build index 6b5479a..7db4393 100755 --- a/scripts/Libraries/mpc.build +++ b/scripts/Libraries/mpc.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Libraries/mpfr.build b/scripts/Libraries/mpfr.build index f087dce..d4c1ab0 100755 --- a/scripts/Libraries/mpfr.build +++ b/scripts/Libraries/mpfr.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Libraries/tiff.build b/scripts/Libraries/tiff.build index 8060ae0..6f800ef 100755 --- a/scripts/Libraries/tiff.build +++ b/scripts/Libraries/tiff.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/Python.build b/scripts/Programming/Python.build index 6269f12..fed0766 100755 --- a/scripts/Programming/Python.build +++ b/scripts/Programming/Python.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/Tcl.build b/scripts/Programming/Tcl.build index ef59b83..0adbeab 100755 --- a/scripts/Programming/Tcl.build +++ b/scripts/Programming/Tcl.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { case ${OS} in diff --git a/scripts/Programming/autoconf.build b/scripts/Programming/autoconf.build index 1e787fb..431b95a 100755 --- a/scripts/Programming/autoconf.build +++ b/scripts/Programming/autoconf.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/automake.build b/scripts/Programming/automake.build index 1dfa5a4..7c6bebc 100755 --- a/scripts/Programming/automake.build +++ b/scripts/Programming/automake.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/cmake.build b/scripts/Programming/cmake.build index 5dc8f67..137f989 100755 --- a/scripts/Programming/cmake.build +++ b/scripts/Programming/cmake.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}/bootstrap" --prefix="${PREFIX}" diff --git a/scripts/Programming/gcc.build b/scripts/Programming/gcc.build index 0496100..7ae5406 100755 --- a/scripts/Programming/gcc.build +++ b/scripts/Programming/gcc.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/gtest.build b/scripts/Programming/gtest.build index cfabab8..65d3110 100755 --- a/scripts/Programming/gtest.build +++ b/scripts/Programming/gtest.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" em.add_to_family 'Programming' em.set_runtime_dependencies "" diff --git a/scripts/Programming/libtool.build b/scripts/Programming/libtool.build index dd388f9..8df068a 100755 --- a/scripts/Programming/libtool.build +++ b/scripts/Programming/libtool.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/lua.build b/scripts/Programming/lua.build index d282527..f02bdfc 100755 --- a/scripts/Programming/lua.build +++ b/scripts/Programming/lua.build @@ -3,7 +3,7 @@ # Lua cannot be build in a seperate directory! # -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { cd "${MODULE_SRCDIR}" diff --git a/scripts/Programming/m4.build b/scripts/Programming/m4.build index 178b82e..cfc5cc0 100755 --- a/scripts/Programming/m4.build +++ b/scripts/Programming/m4.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Programming/psi-python27.build b/scripts/Programming/psi-python27.build index 54350f9..08f970e 100755 --- a/scripts/Programming/psi-python27.build +++ b/scripts/Programming/psi-python27.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { : diff --git a/scripts/System/bash.build b/scripts/System/bash.build index 2867315..122c5f9 100755 --- a/scripts/System/bash.build +++ b/scripts/System/bash.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Tools/Modules.build b/scripts/Tools/Modules.build index c20212a..171be58 100755 --- a/scripts/Tools/Modules.build +++ b/scripts/Tools/Modules.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" TCL_VERSION='8.6.3' TCL_DIR="${PSI_PREFIX}/Programming/Tcl/${TCL_VERSION}" diff --git a/scripts/Tools/dialog.build b/scripts/Tools/dialog.build index c614f09..b5d7a1d 100755 --- a/scripts/Tools/dialog.build +++ b/scripts/Tools/dialog.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Tools/emacs.build b/scripts/Tools/emacs.build index 087edd5..c436bd2 100755 --- a/scripts/Tools/emacs.build +++ b/scripts/Tools/emacs.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" module use 'Libraries' diff --git a/scripts/Tools/global.build b/scripts/Tools/global.build index fffff75..6a0b3a1 100755 --- a/scripts/Tools/global.build +++ b/scripts/Tools/global.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ diff --git a/scripts/Tools/gnuplot.build b/scripts/Tools/gnuplot.build index e263f3d..034a143 100755 --- a/scripts/Tools/gnuplot.build +++ b/scripts/Tools/gnuplot.build @@ -1,6 +1,6 @@ #!/bin/bash -source "$(dirname $0)/../lib/libem.bash" +source "$(dirname $0)/../../lib/libem.bash" function em.configure() { "${MODULE_SRCDIR}"/configure \ From 52d0dd13cc4a3ff7ef614c6169a492bb6e27fd1c Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 18:59:55 +0100 Subject: [PATCH 09/10] lib/libem.bash: change code to support bootstraping --- lib/libem.bash | 278 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 190 insertions(+), 88 deletions(-) diff --git a/lib/libem.bash b/lib/libem.bash index 96e07f8..a43d828 100644 --- a/lib/libem.bash +++ b/lib/libem.bash @@ -5,25 +5,17 @@ PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin shopt -s expand_aliases source "${PSI_PREFIX}/${PSI_CONFIG_DIR}/profile.bash" -module use unstable -declare -r MODULECMD="${PSI_PREFIX}/${PSI_CONFIG_DIR}/modulecmd.bash" - -declare -r BUILDSCRIPT=$( cd $(dirname "$0") && pwd )/$(basename "$0") -declare -rx ARGS="$@" -declare -rx SHLIBDIR=$( cd $(dirname "$BASH_SOURCE") && pwd ) -declare -r OS=$(uname -s) +declare -r BUILDSCRIPT=$( cd $(dirname "$0") && pwd )/$(basename "$0") +declare -rx ARGS="$@" +declare -rx SHLIBDIR=$( cd $(dirname "$BASH_SOURCE") && pwd ) +declare -r OS=$(uname -s) # number of parallel make jobs -declare -i JOBS=3 +declare -i JOBS=3 source "${SHLIBDIR}/lib.bash" -# while bootstraping the module command is not yet available -if typeset -f module > /dev/null 2>&1 ; then - module purge -fi - declare -rx BUILD_BASEDIR=$(abspath $SHLIBDIR/..) source "$(readlink ${BUILD_BASEDIR}/config/environment.bash)" @@ -37,6 +29,7 @@ declare -xr BUILD_VERSIONSFILE="${BUILD_CONFIGDIR}/versions.conf" if [[ -z "${BUILD_CONFIGDIR}/families.d/"*.conf ]]; then die 1 "Default family configuration not set in ${BUILD_CONFIGDIR}/families.d" fi + for f in "${BUILD_CONFIGDIR}/families.d/"*.conf; do source "${f}" done @@ -47,7 +40,6 @@ declare -x MODULE_FAMILY='' declare -x MODULE_RELEASE='' declare cur_module_release='' - declare DEPEND_RELEASE='' declare -x MODULE_NAME='' @@ -58,16 +50,13 @@ declare -x MODULE_BUILDDIR='' declare -x MODULE_BUILD_DEPENDENCIES declare -x MODULE_DEPENDENCIES -declare -x C_INCLUDE_PATH -declare -x CPLUS_INCLUDE_PATH -declare -x CPP_INCLUDE_PATH -declare -x LIBRARY_PATH -declare -x LD_LIBRARY_PATH -declare -x DYLD_LIBRARY_PATH +declare -x C_INCLUDE_PATH +declare -x CPLUS_INCLUDE_PATH +declare -x CPP_INCLUDE_PATH +declare -x LIBRARY_PATH +declare -x LD_LIBRARY_PATH +declare -x DYLD_LIBRARY_PATH -if [[ $DEBUG_ON ]]; then - trap 'echo "$BASH_COMMAND"' DEBUG -fi function usage() { error " @@ -92,6 +81,9 @@ ENV=VALUE -f | --force-rebuild Force rebuild of module. +-b | --bootstrap + Bootstrap Pmodules + --with=P/V Preload module P with version V. To preload multiple modules, use this option per module. Nete that order may matter. @@ -103,18 +95,15 @@ ENV=VALUE } -P=$(basename $0) -P=${P%.*} -_P=$(echo $P | tr [:lower:] [:upper:]) -_P=${_P//-/_} -_V=${_P}_VERSION - -DEBUG_ON='' -FORCE_REBUILD='' +debug_on='no' +force_rebuild='no' ENVIRONMENT_ARGS='' -WITH_ARGS='' -DRY_RUN='' +dry_run='no' +bootstrap='no' + +# array collecting all modules specified on the command line via '--with=module' with_modules=() + while (( $# > 0 )); do case $1 in -j ) @@ -125,16 +114,20 @@ while (( $# > 0 )); do JOBS=${1/--jobs=} ;; -v | --verbose) - DEBUG_ON=':' + debug_on='yes' ;; -f | --force-rebuild ) - FORCE_REBUILD=':' + force_rebuild='yes' + ;; + -b | --bootstrap ) + bootstrap='yes' + force_rebuild='yes' ;; -? | -h | --help ) usage ;; --dry-run ) - DRY_RUN='dry-run' + dry_run='yes' ;; --release=* ) MODULE_RELEASE=${1/--release=} @@ -153,6 +146,22 @@ while (( $# > 0 )); do shift done +if [[ ${debug_on} == yes ]]; then + trap 'echo "$BASH_COMMAND"' DEBUG +fi + +# while bootstraping the module command is not yet available +if [[ ${bootstrap} == no ]]; then + [[ -x ${MODULECMD} ]] || die 1 "${MODULECMD}: no such executable" + module use unstable + module purge +fi + +P=$(basename $0) +P=${P%.*} +_P=$(echo $P | tr [:lower:] [:upper:]) +_P=${_P//-/_} +_V=${_P}_VERSION eval "${ENVIRONMENT_ARGS}" @@ -233,7 +242,9 @@ function _load_build_dependencies() { die 1 "${m}: module available with release \"${rel}\", add this release with \"module use ${rel}\" and re-run build script." fi done - [[ ${DRY_RUN} ]] && die 1 "${m}: module does not exist, cannot continue with dry run..." + [[ ${dry_run} == yes ]] && { + die 1 "${m}: module does not exist, cannot continue with dry run..." + } echo "$m: module does not exist, trying to build it..." local args=( '' ) @@ -272,13 +283,13 @@ function _load_build_dependencies() { tmp=${tmp/${modulepath_root}\/} tmp=${tmp%%/*} local _family=( ${tmp//./ } ) - # set module release to 'deprecated' if a build dependency - # is deprecated if [[ ${_family[1]} == deprecated ]]; then + # set module release to 'deprecated' if a build dependency + # is deprecated DEPEND_RELEASE='deprecated' - # set module release to 'unstable' if a build dependency is - # unstable and release not yet set elif [[ ${_family[1]} == unstable ]] && [[ -z ${DEPEND_RELEASE} ]]; then + # set module release to 'unstable' if a build dependency is + # unstable and release not yet set DEPEND_RELEASE='unstable' fi echo "Loading module: ${m}" @@ -286,6 +297,12 @@ function _load_build_dependencies() { done } +if [[ ${bootstrap} == yes ]]; then + function _load_build_dependencies() { + : + } +fi + function _write_runtime_dependencies() { local -r fname="${PREFIX}/.dependencies" info "Writing run-time dependencies to ${fname}" @@ -325,6 +342,12 @@ function _setup_env1() { LD_LIBRARY_PATH='' DYLD_LIBRARY_PATH='' + CFLAGS='' + CPPFLAGS='' + CXXFLAGS='' + LIBS='' + LDFLAGS='' + while read _name _version; do [[ -z ${_name} ]] && continue [[ -z ${_version} ]] && continue @@ -344,7 +367,8 @@ function _setup_env2() { # overwrite environment variables with values we got on the cmd line eval "${ENVIRONMENT_ARGS}" - # this allows us to specify the version as PKGNAME_VERSION=1.2.3 on the cmd-line + # this allows us to specify the version as PKGNAME_VERSION=1.2.3 on + # the cmd-line if [[ -z $V ]]; then V=$(eval echo \$${_P}_VERSION) fi @@ -354,47 +378,67 @@ function _setup_env2() { die 1 "$P: Missing version." fi MODULE_SRCDIR="${BUILD_TMPDIR}/src/${P/_serial}-$V" - MODULE_BUILDDIR="${BUILD_TMPDIR}/build/$P-$V/$COMPILER/$COMPILER_VERSION" + MODULE_BUILDDIR="${BUILD_TMPDIR}/build/$P-$V" # build module name # :FIXME: the MODULE_PREFIX should be derived from MODULE_NAME # :FIXME: this should be read from a configuration file case ${MODULE_FAMILY} in - Tools ) - MODULE_RPREFIX="${P}/${V}" - MODULE_NAME="${P}/${V}" - ;; - Programming ) - MODULE_RPREFIX="${P}/${V}" - MODULE_NAME="${P}/${V}" - ;; - Libraries ) - MODULE_RPREFIX="${P}/${V}" - MODULE_NAME="${P}/${V}" - ;; - System ) - MODULE_RPREFIX="${P}/${V}" - MODULE_NAME="${P}/${V}" - ;; - Compiler ) - MODULE_RPREFIX="${P}/${V}/${COMPILER}/${COMPILER_VERSION}" - MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/${P}/${V}" - ;; - MPI ) - MODULE_RPREFIX="${P}/${V}/${MPI}/${MPI_VERSION}/${COMPILER}/${COMPILER_VERSION}" - MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/${MPI}/${MPI_VERSION}/${P}/${V}" - ;; - HDF5 ) - MODULE_RPREFIX="${P}/${V}/${HDF5}/${HDF5_VERSION}/${MPI}/${MPI_VERSION}/${COMPILER}/${COMPILER_VERSION}/" - MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/${MPI}/${MPI_VERSION}/${HDF5}/${HDF5_VERSION}/${P}/${V}" - ;; - HDF5_serial ) - MODULE_RPREFIX="${P}/${V}/hdf5_serial/${HDF5_SERIAL_VERSION}/${COMPILER}/${COMPILER_VERSION}" - MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/hdf5_serial/${HDF5_VERSION}/${P}/${V}" - ;; - * ) - die 1 "$P: oops: unknown family: ${MODULE_FAMILY}" - ;; + Tools ) + MODULE_RPREFIX="${P}/${V}" + MODULE_NAME="${P}/${V}" + ;; + Programming ) + MODULE_RPREFIX="${P}/${V}" + MODULE_NAME="${P}/${V}" + ;; + Libraries ) + MODULE_RPREFIX="${P}/${V}" + MODULE_NAME="${P}/${V}" + ;; + System ) + MODULE_RPREFIX="${P}/${V}" + MODULE_NAME="${P}/${V}" + ;; + Compiler ) + MODULE_RPREFIX="${P}/${V}" + MODULE_RPREFIX+="/${COMPILER}/${COMPILER_VERSION}" + + MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/" + MODULE_NAME+="${P}/${V}" + ;; + MPI ) + MODULE_RPREFIX="${P}/${V}/" + MODULE_RPREFIX+="${MPI}/${MPI_VERSION}/" + MODULE_RPREFIX+="${COMPILER}/${COMPILER_VERSION}" + + MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/" + MODULE_NAME+="${MPI}/${MPI_VERSION}/" + MODULE_NAME+="${P}/${V}" + ;; + HDF5 ) + MODULE_RPREFIX="${P}/${V}" + MODULE_RPREFIX+="/${HDF5}/${HDF5_VERSION}" + MODULE_RPREFIX+="/${MPI}/${MPI_VERSION}" + MODULE_RPREFIX+="/${COMPILER}/${COMPILER_VERSION}" + + MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/" + MODULE_NAME+="${MPI}/${MPI_VERSION}/" + MODULE_NAME+="${HDF5}/${HDF5_VERSION}/" + MODULE_NAME+="${P}/${V}" + ;; + HDF5_serial ) + MODULE_RPREFIX="${P}/${V}" + MODULE_RPREFIX+="/hdf5_serial/${HDF5_SERIAL_VERSION}" + MODULE_RPREFIX+="/${COMPILER}/${COMPILER_VERSION}" + + MODULE_NAME="${COMPILER}/${COMPILER_VERSION}/" + MODULE_NAME+="hdf5_serial/${HDF5_VERSION}/" + MODULE_NAME+="${P}/${V}" + ;; + * ) + die 1 "$P: oops: unknown family: ${MODULE_FAMILY}" + ;; esac # set PREFIX of module @@ -430,7 +474,8 @@ function _setup_env2() { # release is stable # - if all build-dependency are stable or # - the module already exists and is stable - # - an unstable release of the module exists and the release is changed to stable on the command line + # - an unstable release of the module exists and the release is + # changed to stable on the command line elif [[ "${depend_release}" == 'stable' ]] \ || [[ "${cur_module_release}" == 'stable' ]] \ || [[ "${MODULE_RELEASE}" == 'stable' ]]; then @@ -439,7 +484,8 @@ function _setup_env2() { # # release is unstable # - if a build-dependency is unstable or - # - if the module does not exists and no other release-type is given on the command line + # - if the module does not exists and no other release-type is + # given on the command line # - and all the cases I didn't think of else MODULE_RELEASE='unstable' @@ -466,6 +512,59 @@ function _setup_env2() { } +if [[ ${bootstrap} == yes ]]; then + # redefine function for bootstrapping + function _setup_env2() { + if [[ -z ${MODULE_FAMILY} ]]; then + die 1 "$P: family not set." + fi + + if [[ -z $V ]]; then + V=$(eval echo \$${_P}_VERSION) + fi + + # oops, we need a version + if [[ -z $V ]]; then + die 1 "$P: Missing version." + fi + MODULE_SRCDIR="${BUILD_TMPDIR}/src/${P/_serial}-$V" + MODULE_BUILDDIR="${BUILD_TMPDIR}/build/$P-$V" + MODULE_FAMILY='Tools' + MODULE_NAME="Pmodules/0.99.0" + # set PREFIX of module + PREFIX="${PSI_PREFIX}/${MODULE_FAMILY}/${MODULE_NAME}" + + MODULE_RELEASE='unstable' + info "${MODULE_NAME}: will be released as \"${MODULE_RELEASE}\"" + + # directory for README's, license files etc + DOCDIR="${PREFIX}/share/doc/$P" + + # set tar-ball and flags for tar + TARBALL="${BUILD_DOWNLOADSDIR}/${P/_serial}" + if [[ -r "${TARBALL}-${V}.tar.gz" ]]; then + TARBALL+="-${V}.tar.gz" + elif [[ -r "${TARBALL}-${OS}-${V}.tar.gz" ]]; then + TARBALL+="-${OS}-${V}.tar.gz" + elif [[ -r "${TARBALL}-${V}.tar.bz2" ]]; then + TARBALL+="-${V}.tar.bz2" + elif [[ -r "${TARBALL}-${OS}-${V}.tar.bz2" ]]; then + TARBALL+="-${OS}-${V}.tar.bz2" + else + error "tar-ball for $P/$V not found." + exit 43 + fi + C_INCLUDE_PATH="${PREFIX}/include" + CPLUS_INCLUDE_PATH="${PREFIX}/include" + CPP_INCLUDE_PATH="${PREFIX}/include" + LIBRARY_PATH="${PREFIX}/lib" + LD_LIBRARY_PATH="${PREFIX}/lib" + DYLD_LIBRARY_PATH="${PREFIX}/lib" + + PATH+=":${PREFIX}/bin" + } +fi + function _prep() { # untar sources @@ -526,7 +625,7 @@ function _set_link() { echo "${MODULE_RELEASE}" > "${release_file}" } -function _cleanup_build() { +function em.cleanup_build() { ( [[ -d /${MODULE_BUILDDIR} ]] || return 0 cd "/${MODULE_BUILDDIR}/.."; @@ -581,9 +680,9 @@ function em.make_all() { # setup module specific environment _setup_env2 - if [[ ! -d "${PREFIX}" ]] || [[ ${FORCE_REBUILD} ]]; then + if [[ ! -d "${PREFIX}" ]] || [[ ${force_rebuild} == 'yes' ]]; then echo "Building $P/$V ..." - [[ "${DRY_RUN}" ]] && die 0 "" + [[ ${dry_run} == yes ]] && die 0 "" _check_compiler _prep cd "${MODULE_SRCDIR}" @@ -595,17 +694,20 @@ function em.make_all() { em.post_install em.install_doc _post_install - _write_runtime_dependencies - _write_build_dependencies + if [[ ${bootstrap} == 'no' ]]; then + _write_runtime_dependencies + _write_build_dependencies + fi else echo "Not rebuilding $P/$V ..." fi - _set_link - _cleanup_build + if [[ ${bootstrap} == 'no' ]]; then + _set_link + fi + em.cleanup_build } - # Local Variables: # mode: sh # sh-basic-offset: 8 From 2a04faca3212473fc00db6100790b1f081046c3a Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Mon, 26 Jan 2015 19:00:33 +0100 Subject: [PATCH 10/10] config/versions.conf: various versions added --- config/versions.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/versions.conf b/config/versions.conf index bf43224..08f4ec8 100644 --- a/config/versions.conf +++ b/config/versions.conf @@ -1,11 +1,14 @@ autoconf 2.69 automake 1.14 +bash 4.3.30 boost 1.55.0 BoxLib 2014-02-28 cmake 2.8.12.2 dialog 1.2.1 emacs 24.3 filebench 1.4.9.1 +getopt 1.1.6 +gettext 0.19.4 giflib 5.0.6 gmp 5.1.1 gnuplot 4.6.3 @@ -36,6 +39,7 @@ Python 3.4.0 root 5.34.19 SuperLU 4.3 SuperLU_DIST 3.3 +Tcl 8.6.3 tiff 4.0.3 trilinos 11.10.2 UMFPACK 5.6.2