Commit a42cdf46 authored by gsell's avatar gsell
Browse files

scripts/Bootstrap:

- PSI_ variables renamed
- new modulefiles layout implemented
- autoload libmodules.tcl
- use of term 'group' instead of 'family'
parent ccf5f2b9
......@@ -2,7 +2,7 @@
#set -o functrace
source "$(dirname $0)/../../../lib/libem.bash"
TCL_DIR="${PSI_PREFIX}/Tools/Pmodules/${PMODULES_VERSION}"
TCL_DIR="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}"
PATH="${TCL_DIR}/bin:${PATH}"
......@@ -18,7 +18,7 @@ function em.configure() {
CPPFLAGS="-DUSE_INTERP_ERRORLINE" "${MODULE_SRCDIR}"/configure \
--prefix="${PREFIX}" \
--exec-prefix="${PREFIX}" \
--with-module-path="${PSI_PREFIX}/${PSI_MODULES_ROOT}" \
--with-module-path="${PMODULES_ROOT}/Tools/${PMODULES_MODULEFILES_DIR}" \
--with-tcl="${TCL_DIR}/lib" \
--without-x \
--disable-versioning \
......
......@@ -136,17 +136,17 @@ declare -x LOADEDMODULES=''
declare -x _LMFILES_=''
declare -x PMODULES_USED_GROUPS=''
declare -x MODULEPATH=''
for f in ${PMODULES_DEFAULT_GROUPS//:/ }; do
append_path MODULEPATH "${PSI_PREFIX}/${PSI_MODULES_ROOT}/$f"
append_path PMODULES_USED_GROUPS "${f}"
for group in ${PMODULES_DEFAULT_GROUPS//:/ }; do
append_path MODULEPATH "${PMODULES_ROOT}/${group}/${PMODULES_MODULEFILES_DIR}"
append_path PMODULES_USED_GROUPS "${group}"
done
declare -x USED_RELEASES=''
declare -x UsedReleases=''
for r in ${PMODULES_DEFAULT_RELEASES//:/ }; do
append_path USED_RELEASES "${r}"
append_path UsedReleases "${r}"
done
eval $(save_env USED_RELEASES PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES)
unset USED_RELEASES
eval $(save_env UsedReleases PMODULES_DEFAULT_RELEASES PMODULES_DEFAULT_GROUPS PMODULES_DEFINED_RELEASES)
unset UsedReleases
unset PMODULES_DEFAULT_RELEASES
unset PMODULES_DEFAULT_GROUPS
unset PMODULES_DEFINED_RELEASES
......
......@@ -61,7 +61,7 @@ function unique_id() { # $1: module info index
function mod_path() { # $1: module info index
local -i i
local -a m=(${modlist[$1]})
local res="$PSI_PREFIX/${fmmap[${m[0]%%/*}]}/${m[0]}"
local res="$PMODULES_ROOT/${fmmap[${m[0]%%/*}]}/${m[0]}"
for (( i=${#m[@]}; i>3; i-- )); do
res+="/${m[i-1]}"
done
......@@ -156,7 +156,7 @@ function find_families() {
t=( ${l##*:} )
fdmap[$n]=${t[-1]//\"}
fi
done < <(grep -R set-family "$1/${PSI_MODULES_ROOT}")
done < <(grep -R set-family "$1/*/${PMODULES_MODULEFILES_DIR}")
}
function select_uid() { # $1: module uid
......@@ -174,7 +174,7 @@ function preselect() { # "$1": prefix for preselected modules
local -a mpc # module path components
local -i i
local uid n
pushd "$1/$PSI_MODULES_ROOT" > /dev/null || exit 1;
pushd "$1/$PMODULES_MODULEFILES_DIR" > /dev/null || exit 1;
trap "popd" EXIT
for m in $(find . -follow -type f); do
......@@ -186,7 +186,7 @@ function preselect() { # "$1": prefix for preselected modules
uid+="${mpc[i]}/${mpc[i+1]} "
done
uid+="${mpc[-2]}/${mpc[-1]}"
PSI_PREFIX="$1" select_uid "$uid"
PMODULES_ROOT="$1" select_uid "$uid"
done
popd
......@@ -309,8 +309,8 @@ function module_picker() {
0) #OK
oldsel=${selected[$sel]} # old selection
selected[$sel]=$(< $tempfile) # new selection
PSI_PREFIX="$2" update_deps -1 "$(set_difference "$oldsel" "${selected[$sel]}")" # remove dependencies
PSI_PREFIX="$2" update_deps 1 "$(set_difference "${selected[$sel]}" "$oldsel")" # add dependencies
PMODULES_ROOT="$2" update_deps -1 "$(set_difference "$oldsel" "${selected[$sel]}")" # remove dependencies
PMODULES_ROOT="$2" update_deps 1 "$(set_difference "${selected[$sel]}" "$oldsel")" # add dependencies
level=1
;;
1|255) #ESC/Cancel
......@@ -344,7 +344,7 @@ function module_picker() {
# if DIALOG_LIB is NOT set, call module picker
[[ ${DIALOG_LIB:+"is_lib"} == "is_lib" ]] || {
if [[ -x ${PMODULES_HOME}/bin/modulecmd ]]; then
module_picker "${1:-$PSI_PREFIX}" "${2:-/afs/psi.ch/sys/psi.x86_64_slp6}"
module_picker "${1:-$PMODULES_ROOT}" "${2:-/afs/psi.ch/sys/psi.x86_64_slp6}"
exit $?
else
echo "ERROR: module environment configuration: ${PMODULES_HOME}/bin/modulecmd is not an executable!"
......
#!/bin/bash
declare -x PSI_PREFIX=$(cd $(dirname "${BASH_SOURCE}")/.. && pwd)
declare -x PMODULES_ROOT=$(cd $(dirname "${BASH_SOURCE}")/.. && pwd)
if [[ -z ${PMODULES_VERSION} ]]; then
declare -x PMODULES_VERSION="@PMODULES_VERSION@"
fi
declare -x PMODULES_HOME="${PSI_PREFIX}/Tools/Pmodules/${PMODULES_VERSION}"
declare -x PMODULES_HOME="${PMODULES_ROOT}/Tools/Pmodules/${PMODULES_VERSION}"
declare -x PMODULES_DIR="${PMODULES_HOME}"
declare -x PSI_CONFIG_DIR=$(basename $(cd $(dirname "${BASH_SOURCE}") && pwd))
declare -x PSI_MODULES_ROOT='modulefiles'
declare -x PSI_TEMPLATES_DIR='templates'
declare -x PMODULES_CONFIG_DIR=$(basename $(cd $(dirname "${BASH_SOURCE}") && pwd))
declare -x PMODULES_MODULEFILES_DIR='modulefiles'
declare -x PMODULES_TEMPLATES_DIR='templates'
declare -x PMODULES_DEFAULT_GROUPS='Tools Programming'
declare -x PMODULES_DEFAULT_RELEASES='stable'
declare -x PMODULES_DEFINED_RELEASES=':unstable:stable:deprecated:'
declare -x PMODULES_DEFAULT_RELEASES='stable'
# legacy vars
declare -x PSI_PREFIX="${PMODULES_ROOT}"
declare -x PSI_CONFIG_DIR="${PMODULES_CONFIG_DIR}"
declare -x PSI_MODULES_ROOT="${PMODULES_MODULES_ROOT}"
declare -x PSI_TEMPLATES_DIR="${PMODULES_TEMPLATES_DIR}"
declare -x PSI_DEFAULT_FAMILIES="${PMODULES_DEFAULT_GROUPS}"
declare -x PSI_DEFAULT_RELEASES="${PMODULES_DEFAULT_RELEASES}"
declare -x PSI_DEFINED_RELEASES="${PMODULES_DEFINED_RELEASES}"
......@@ -4,7 +4,7 @@
# unload modules if parent removed
#
if {[info exists env(PSI_DEBUG)] && $env(PSI_DEBUG)} {
if {[info exists env(PMODULES_DEBUG)] && $env(PMODULES_DEBUG)} {
proc debug {msg} {
set level [expr [info level] -2]
set r [catch {info level ${level}} e]
......@@ -20,87 +20,77 @@ if {[info exists env(PSI_DEBUG)] && $env(PSI_DEBUG)} {
proc debug {msg} {}
}
proc set-family { family } {
debug "loading libmodules"
proc module-addgroup { group } {
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
debug $group
set Implementation [file join {*}$::implementation]
set ::${family} ${name}
set ::${family}_version ${version}
set GROUP [string toupper $group]
regsub -- "-" ${GROUP} "_" GROUP
setenv ${GROUP} $name
setenv ${GROUP}_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}"
set ::${group} $name
set ::${group}_version $version
if { [module-info mode load] } {
debug "mode is load"
append-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/${Implementation}
append-path PMODULES_USED_GROUPS ${family}
append-path MODULEPATH $::PmodulesRoot/$group/$::PmodulesModulfilesDir/$Implementation
append-path PMODULES_USED_GROUPS $group
debug "mode=load: new MODULEPATH=$env(MODULEPATH)"
debug "mode=load: new PMODULES_USED_GROUPS=$env(PMODULES_USED_GROUPS)"
} 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}) ":"]
set GROUP [string toupper $group]
if { [info exists env(PMODULES_LOADED_${GROUP})] } {
set modules [split $env(PMODULES_LOADED_${GROUP}) ":"]
foreach m ${modules} {
if { ${m} == "--APPMARKER--" } {
continue
}
debug "unloading module: $m"
module unload ${m}
if { [is-loaded ${module_name}] } {
debug "unloading module: $m"
module unload ${m}
}
}
}
remove-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/${Implementation}
remove-path PMODULES_USED_GROUPS ${family}
remove-path MODULEPATH $::PmodulesRoot/$group/$::PmodulesModulfilesDir/$Implementation
remove-path PMODULES_USED_GROUPS $group
debug "mode=remove: $env(MODULEPATH)"
debug "mode=remove: $env(PMODULES_USED_GROUPS)"
}
if { [module-info mode switch2] } {
debug "mode=switch2"
append-path MODULEPATH ${::MODULE_ROOT_PATH}/${family}/[module-info name]
append-path PMODULES_USED_GROUPS ${family}
append-path MODULEPATH $::PmodulesRoot/$group/$::PmodulesModulfilesDir/[module-info name]
append-path PMODULES_USED_GROUPS ${group}
}
}
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 set-family { group } {
module-addgroup $group
}
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
proc _pmodules_update_loaded_modules { group name version } {
if { ${group} == "--APPMARKER--" } {
return
}
set GROUP [string toupper $group]
debug "${GROUP} $name/$version"
append-path PMODULES_LOADED_${GROUP} "$name/$version"
remove-path PMODULES_LOADED_${GROUP} "--APPMARKER--"
}
#
# load dependencies, but do *not* unload dependencies
#
proc load_dependencies { fname } {
proc _pmodules_load_dependencies { fname } {
if { ! [ file exists ${fname} ] } {
return
}
......@@ -123,12 +113,6 @@ proc load_dependencies { fname } {
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}
}
......@@ -144,20 +128,17 @@ proc lreverse_n { list n } {
set res
}
#
# set standard environment variables
#
proc set_std_environment { PREFIX name version } {
proc _pmodules_setenv { PREFIX name version } {
#
# Hack for supporting legacy modules
if { "${::family}" == "Legacy" } {
if { "${::group}" == "Legacy" } {
debug "this is a legacy module..."
return
}
set NAME [string toupper $name]
regsub -- "-" ${NAME} "_" NAME
......@@ -242,75 +223,34 @@ proc set_std_environment { PREFIX name version } {
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
proc module-url { _url } {
set ::url ${_url}
}
if { [module-info mode load] } {
debug "${name}/${version}: loading ... "
if { [ string match "*.deprecated" ${family} ] == 1 } {
puts stderr "${name}/${version}: this module is deprecated!"
}
proc module-license { _license } {
set ::license ${_license}
}
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"
proc module-maintainer { _maintainer } {
set ::maintainer ${_maintainer}
}
set_std_environment ${PREFIX} ${name} ${version}
update_active_modules ${family} ${name} ${version}
proc module-help { _help } {
set ::help ${_help}
}
proc ModulesHelp { } {
if { [info exists ::whatis] } {
puts stderr "${::whatis}"
} else {
module whatis ModulesCurrentModulefile
}
if { [info exists ::version] } {
puts stderr "Version: ${::version}"
} else {
module whatis
}
if { [info exists ::url] } {
puts stderr "Homepage: ${::url}"
......@@ -326,6 +266,75 @@ proc ModulesHelp { } {
}
}
#
# intialize global vars
# Modulefile is something like
#
# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/name/version
# or
# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/X1/Y1/name/version
# or
# ${PMODULES_ROOT}/group/${PMODULES_MODULEFILES_DIR}/X1/Y1//X2/Y2/name/version
#
proc _pmodules_init_global_vars { } {
global group
global name
global version
global implementation
global PREFIX # prefix of package
debug "$::ModulesCurrentModulefile"
set ::PmodulesRoot $::env(PMODULES_ROOT)
set ::PmodulesModulfilesDir $::env(PMODULES_MODULEFILES_DIR)
set modulefile [file split $::ModulesCurrentModulefile]
set pmodules_root [file split $::PmodulesRoot]
set pmodules_root_num_dirs [llength $pmodules_root]
set modulefile_root [file join {*}[lrange $modulefile 0 [expr $pmodules_root_num_dirs - 1]]]
if { $::PmodulesRoot != $modulefile_root } {
debug "stop sourcing: ${::PmodulesRoot} != $modulefile_root"
return
}
debug "modulefile is inside our root"
set rel_modulefile [lrange $modulefile [llength $pmodules_root] end]
set group [lindex $rel_modulefile 0]
set name [lindex $modulefile end-1]
set version [lindex $modulefile end]
set implementation [lrange $rel_modulefile 2 end]
set prefix "$pmodules_root $group [lreverse_n $implementation 2]"
set PREFIX [file join {*}$prefix]
debug "PREFIX=$PREFIX"
debug "group of module $name: $group"
}
proc _pmodules_output_message { fname } {
if { [ file exists "${fname}" ] } {
set fp [open "${fname}" r]
set info_text [read $fp]
close $fp
puts stderr ${info_text}
}
}
if { [info exists ::whatis] } {
module-whatis "$whatis"
}
_pmodules_init_global_vars
#
# we cannot load another module with the same name
#
conflict $name
if { [module-info mode load] } {
debug "${name}/${version}: loading ... "
_pmodules_output_message "${PREFIX}/.info"
_pmodules_load_dependencies "${PREFIX}/.dependencies"
}
_pmodules_setenv ${PREFIX} ${name} ${version}
_pmodules_update_loaded_modules ${group} ${name} ${version}
debug "return from lib"
......@@ -21,7 +21,7 @@ error() {
}
debug() {
[[ ${PSI_DEBUG} ]] || return 0
[[ ${PMODULES_DEBUG} ]] || return 0
log 2 "$@"
}
......@@ -72,10 +72,9 @@ get_options() {
}
check_pmodules_env_vars() {
[[ -n "${PSI_PREFIX}" ]] &&
[[ -n "${PSI_CONFIG_DIR}" ]] &&
[[ -n "${PSI_MODULES_ROOT}" ]] &&
[[ -n "${PSI_TEMPLATES_DIR}" ]] &&
[[ -n "${PMODULES_ROOT}" ]] &&
[[ -n "${PMODULES_CONFIG_DIR}" ]] &&
[[ -n "${PMODULES_TEMPLATES_DIR}" ]] &&
[[ -n "${PMODULES_HOME}" ]] &&
[[ -n "${PMODULES_VERSION}" ]] || die 1 "
Error: the module environment you are going to use as source has not been
......@@ -86,16 +85,15 @@ check_pmodules_directories() {
local -r src_prefix="$1"
[[ -d "${src_prefix}" ]] &&
[[ -d "${src_prefix}/${PSI_CONFIG_DIR}" ]] &&
[[ -d "${src_prefix}/${PSI_MODULES_ROOT}" ]] &&
[[ -d "${src_prefix}/${PSI_TEMPLATES_DIR}" ]] &&
[[ -d "${src_prefix}/${PMODULES_CONFIG_DIR}" ]] &&
[[ -d "${src_prefix}/${PMODULES_TEMPLATES_DIR}" ]] &&
[[ -d "${src_prefix}/Tools/Pmodules/${PMODULES_VERSION}" ]] || die 1 "
Error: the module environment '${src_prefix}' has not been initialized properly!"
}
check_pmodules_env() {
check_pmodules_env_vars
check_pmodules_directories "${PSI_PREFIX}"
check_pmodules_directories "${PMODULES_ROOT}"
}
append_path () {
......
......@@ -98,7 +98,7 @@ get_module_prefix() {
local -a comp=( ${1//\// } ) # split rel.path into components
local path="${comp[0]}" # result path
local -i i
for ((i=1; i<${#comp[@]}; i+=2)); do
for ((i=1; i<${#comp[@]}-1; i+=2)); do
path+="/${comp[$((-i-1))]}/${comp[$((-i))]}"
done
echo "${path}"
......@@ -120,6 +120,10 @@ get_releasefile_name() {
# - sync modulefile
# - sync release file
#
# Note:
# We do not take care of files in $PMODULES_ROOT/$PMODULES_TEMPLATES_DIR. If
# the modulefile is a sym-link it is expected that the target exists.
#
# $1: relative modulefile path (something like: Tools/gnuplot/5.0.0)
# $2: source prefix of Pmodule environment
# $3: target prefix of Pmodule environment
......@@ -139,10 +143,10 @@ sync_module() {
"${src_prefix}/${rel_module_prefix}/" \
"${target_prefix}/${rel_module_prefix}/" || return $?
fi
local -r src_modulefile="${src_prefix}/${PSI_MODULES_ROOT}/${rel_modulefile}"
local -r src_releasefile="${src_prefix}/${PSI_MODULES_ROOT}/${rel_releasefile}"
local -r target_modulefile="${target_prefix}/${PSI_MODULES_ROOT}/${rel_modulefile}"
local -r target_releasefile="${target_prefix}/${PSI_MODULES_ROOT}/${rel_releasefile}"
local -r src_modulefile="${src_prefix}/${rel_modulefile}"
local -r src_releasefile="${src_prefix}/${rel_releasefile}"
local -r target_modulefile="${target_prefix}/${rel_modulefile}"
local -r target_releasefile="${target_prefix}/${rel_releasefile}"
# create target directory for module- and release-file
if [[ -e "${src_modulefile}" ]] || [[ -e "${src_releasefile}" ]]; then
......@@ -161,17 +165,6 @@ sync_module() {
$DRY rsync --links --perms --recursive \
"${src_releasefile}" "${target_releasefile}" || return $?
fi
# if modulefile is a sym-link, sync link target file
#if [[ -L "${src_modulefile}" ]]; then
# local canonical_fname=$(readlink -f "${src_modulefile}")
# local src_template=$(dirname "${canonical_fname}")
# local modulename=$(basename "${src_template}")
# local target_template="${target_prefix}/${PSI_TEMPLATES_DIR}/${modulename}"
# $DRY rsync --links --perms --recursive --delete \
# "${src_template}/" \
# "${target_template}"
#fi
}
#
......@@ -181,15 +174,15 @@ sync_module() {
# $2: target prefix of Pmodule environment
#
sync_config() {
src="$1/${PSI_CONFIG_DIR}/"
dst="$2/${PSI_CONFIG_DIR}/"
src="$1/${PMODULES_CONFIG_DIR}/"
dst="$2/${PMODULES_CONFIG_DIR}/"
$DRY rsync --recursive --links --perms --delete \
"${src}" "${dst}" || die 1 "Error: synch operation failed!"
sed -i.bak "s/PMODULES_VERSION=\(.*\)/PMODULES_VERSION=${PMODULES_VERSION}/" "${dst}/environment.bash"
echo
src="$1/${PSI_TEMPLATES_DIR}/"
dst="$2/${PSI_TEMPLATES_DIR}/"
src="$1/${PMODULES_TEMPLATES_DIR}/"
dst="$2/${PMODULES_TEMPLATES_DIR}/"
$DRY rsync --recursive --links --perms --delete \
"${src}" "${dst}" || die 1 "Error: synch operation failed!"
echo
......@@ -271,11 +264,11 @@ subcommand_init() {
echo "
Attempting to create a minimal module environment from the
environment at '${PSI_PREFIX}'
environment at '${PMODULES_ROOT}'
"
init_pmodules_environment() {
local -r src_prefix="${PSI_PREFIX}"
local -r src_prefix="${PMODULES_ROOT}"
local -r target_prefix=$1
local src=''
local dst=''
......@@ -292,21 +285,16 @@ environment at '${PSI_PREFIX}'
echo
echo "Syncing configuration ..."
sync_config "${PSI_PREFIX}" \
sync_config "${PMODULES_ROOT}" \
"${target_prefix}" || die 1 "Error: configuration synchronization failed!"
dst="${target_prefix}/${PSI_MODULES_ROOT}/"
echo "Creating root directory '${dst}' for module hierarchy ..."
$DRY mkdir -p "${dst}"
echo
echo "Syncing Pmodules ${PMODULES_VERSION} from '${src_prefix}' to '${target_prefix}'..."
sync_module "Tools/Pmodules/${PMODULES_VERSION}" \
"${src_prefix}" \
"${target_prefix}" || die 1 "Error: sync Pmodules failed!"
echo