PSI siteconfig for Tcl Env.Modules added

This commit is contained in:
2026-05-01 13:28:35 +02:00
parent 734d2e1655
commit 285bb96a92
2 changed files with 474 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
#%Module5.0
# This file defines the initial module command configuration, the default
# modulefiles search path and modulefiles you want to load by default for all
# users. It should contains lines of module command like 'module config conf
# val', 'module use path' and 'module load mod'
# ensure that module command is still defined in sub-shells
#module config set_shell_startup 1
# enable environment variable quarantine mechanism
#module config quarantine_support 1
# enable shell debugging properties silencing
#module config silent_shell_debug 1
# enable default modulepaths
#module use --append {/afs/psi.ch/group/HPCE/Modules//modulefiles}
module use base
# restore user's default collection if it exists, otherwise load a predefined
# default module list
#if {[is-saved default]} {
# module restore
#} else {
# module load <LIST MODULES TO LOAD HERE>
#}
+447
View File
@@ -0,0 +1,447 @@
#!/usr/bin/env tclsh
set ::MODULEFILES_DIR "modulefiles"
array set ::g_OlInfo {}
set ::g_OlInfo(none:layout) {none}
set ::g_OlInfo(none:type) {n}
set ::g_OlInfo(none:modulefiles_root) {/zzzzzzzzzzzz}
set ::g_OlInfo(none:len_modroot) {1}
set ::g_OlInfo(:layout) {}
set ::g_UsedOverlays [list]
set ::g_UsedGroups [list]
set ::g_Groups [list]
set ::g_HideTags [list]
proc overlay-define {name type layout install_root {modulefiles_root {}}\
{def_groups {}} } {
#puts stderr "define overlay: $name"
if { $modulefiles_root eq {} } {
set modulefiles_root $install_root
}
if { ![file isdirectory $install_root] } {
reportErrorAndExit\
"Install root '$install_root' for overlay '$name' does not exist!"
}
if { ![file isdirectory $modulefiles_root] } {
reportErrorAndExit\
"Modulefiles root '$modulefiles_root' for overlay '$name' does not exist!"
}
set ::g_OlInfo($name:type) $type
set ::g_OlInfo($name:layout) $layout
set ::g_OlInfo($name:install_root) $install_root
set ::g_OlInfo($name:modulefiles_root) [file split $modulefiles_root]
set ::g_OlInfo($name:len_modroot) [llength $::g_OlInfo($name:modulefiles_root)]
set ::g_OlInfo($name:def_groups) $def_groups
# we need a mapping group/label -> directory with modulefiles
# in Pmodules this is defined via group names
# directories with the same label are merged
set dirs [list]
set patterns [list\
[file join * modulefiles]\
[file join Compiler modulefiles * *]\
[file join HDF5_serial modulefiles * *]\
[file join MPI modulefiles * * * *]\
[file join HDF5 modulefiles * * * * * *]]
foreach pattern $patterns {
foreach dir [glob -nocomplain -types {d}\
[file join {*}$::g_OlInfo($name:modulefiles_root)\
$pattern]] {
set ::g_Dir2Overlay($dir) $name
set group [lindex [file split $dir] end-1]
if {$group ni $::g_Groups} {
lappend ::g_Groups $group
}
modulepath-label $dir "$group ($name)"
}
}
}
proc overlay-get-moddirs { pos ol_name } {
if {![info exists ::g_OlInfo($ol_name:type)]} {
reportErrorAndExit "Overlay '$ol_name' does not exist!"
}
set moddirs [list]
set modulepath [split $::env(MODULEPATH) $::tcl_platform(pathSeparator)]
if { $pos eq {remove} } {
# remove all directories belonging to overlay
foreach dir $modulepath {
if {[info exists ::g_Dir2Overlay($dir)]} {
if {$::g_Dir2Overlay($dir) eq $ol_name} {
lappend moddirs $dir
}
}
}
} else {
# if no overlay is loaded, add default groups of overlay to MODULEPATH,
# otherwise only groups which are used (and also in the overlay)
if { $::g_UsedOverlays eq {} } {
set groups $::g_OlInfo($ol_name:def_groups)
} else {
set groups $::g_UsedGroups
}
foreach group $groups {
set dir [file join {*}$::g_OlInfo($ol_name:modulefiles_root)\
$group modulefiles]
if { [file isdirectory $dir] && $dir ni $modulepath } {
lappend moddirs $dir
}
}
}
return $moddirs
}
proc module-addgroup { group } {
set itrp [getCurrentModfileInterpName]
set fpmod [interp eval $itrp {set ::ModulesCurrentModulefile}]
set fp_mod [file split $fpmod]
set ol [_find_overlay $fp_mod]
if {$ol eq {none}} {
return
} elseif { $::g_OlInfo(${ol}:layout) ne "Pmodules" } {
return
}
if {[info exists ::g_moduleHideFullPath($fpmod)]} {
return
}
set mod [file join [lindex $fp_mod end-1] [lindex $fp_mod end]]
set GROUP [string toupper $group]
# replace '-' with '_' in group name
# ('-' is invalid in variable names in most prog. languages)
regsub -- "-" ${GROUP} "_" GROUP
setenv ${GROUP} [lindex $fp_mod end-1]
setenv ${GROUP}_VERSION [lindex $fp_mod end]
set rel_modulefile [lrange $fp_mod $::g_OlInfo($ol:len_modroot) end]
set variant [lrange $rel_modulefile 2 end]
set idx [lsearch $::g_UsedOverlays $ol]
set overlays [lrange $::g_UsedOverlays 0 $idx]
foreach overlay [lreverse $overlays] {
if {$overlay eq {none}} {
continue
}
set dir [file join \
{*}$::g_OlInfo($overlay:modulefiles_root) \
$group \
$::MODULEFILES_DIR \
{*}$variant]
if { ![file isdirectory $dir] } {
continue
}
set l [list]
foreach {name version} $variant {
lappend l $name/$version
}
modulepath-label $dir "$group ($overlay:$l)"
interp eval $itrp prepend-path MODULEPATH $dir
}
}
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
}
proc _find_overlay { fp_mod } {
foreach ol_name $::g_UsedOverlays {
set len $::g_OlInfo($ol_name:len_modroot)
if {$::g_OlInfo($ol_name:modulefiles_root) eq [lrange $fp_mod 0 $len-1]} {
return $ol_name
}
}
return {none}
}
proc _pmodules_setenv { PREFIX name version } {
if { ![file isdirectory "$PREFIX"] } {
return
}
if { ! [info exist ::dont-setenv] } {
set dont-setenv {}
}
set NAME [string toupper $name]
regsub -all -- "-" ${NAME} "_" NAME
set defaults [dict create\
"${NAME}_VERSION" [list setenv 0 $version]\
"${NAME}_PREFIX" [list setenv 1 $PREFIX]\
"${NAME}_DIR" [list setenv 1 $PREFIX]\
"${NAME}_HOME" [list setenv 1 $PREFIX]\
"${NAME}_INCLUDE_DIR" [list setenv 1 $PREFIX/include]\
"${NAME}_LIBRARY_DIR" [list setenv 1 $PREFIX/lib]\
"${NAME}_LIBRARY_DIR" [list setenv 1 $PREFIX/lib64]\
"PATH" [list prepend-path 1 $PREFIX/bin\
$PREFIX/sbin]\
"MANPATH" [list prepend-path 1 $PREFIX/share/man]\
"C_INCLUDE_PATH" [list prepend-path 1 $PREFIX/include]\
"CPLUS_INCLUDE_PATH" [list prepend-path 1 $PREFIX/include]\
"LIBRARY_PATH" [list prepend-path 1 $PREFIX/lib\
$PREFIX/lib64]\
"LD_LIBRARY_PATH" [list prepend-path 1 $PREFIX/lib\
$PREFIX/lib64]\
"PKG_CONFIG_PATH" [list prepend-path 1 $PREFIX/lib/pkgconfig\
$PREFIX/share/pkgconfig]\
"CMAKE_MODULE_PATH" [list prepend-path 1 $PREFIX/lib/cmake\
$PREFIX/share/cmake\
$PREFIX/share/${name}/cmake]\
]
set itrp [getCurrentModfileInterpName]
dict for {key value} $defaults {
if { $key in ${dont-setenv} } {
continue
}
set items [lassign $value procedure is_dir]
foreach item $items {
if { $is_dir && ![file isdirectory "$item"] } {
continue
}
interp eval $itrp $procedure $key $item
}
}
}
rename evaluateModulefile __evaluateModulefile
proc evaluateModulefile {itrp mod_file vr_spec_list} {
array set vars {}
set fp_mod [file split $mod_file]
# name and version of module
set vars(P) [lindex $fp_mod end-1]
set vars(V) [lindex $fp_mod end]
set vars(V_RELEASE) {}
lassign [split $vars(V) _] v suffix
lassign [split $v -] vars(V_PKG) vars(V_RELEASE)
lassign [split $vars(V_PKG) .] vars(V_MAJOR) vars(V_MINOR) vars(V_PATCHLVL)
set ol [_find_overlay $fp_mod]
if {$::g_OlInfo(${ol}:layout) eq {Pmodules} } {
set rel_modulefile [lrange $fp_mod $::g_OlInfo($ol:len_modroot) end]
set vars(GROUP) [lindex $rel_modulefile 0]
set variant [lrange $rel_modulefile 2 end]
set prefix "[file split $::g_OlInfo(${ol}:install_root)] $vars(GROUP) [lreverse_n $variant 2]"
set vars(PREFIX) [file join {*}$prefix]
_pmodules_setenv $vars(PREFIX) $vars(P) $vars(V)
set dir [file dirname $mod_file]
set depinfo [file join $dir ".deps-$vars(V)"]
if {[file exists $depinfo]} {
set fp [open $depinfo r]
set mods [list]
while { [gets $fp line] >= 0 } {
lappend mods $line
}
close $fp
if {[llength $mods] > 0} {
set itrp [getCurrentModfileInterpName]
interp eval $itrp prereq-all $mods
}
}
}
foreach key [array names vars] {
if {$vars($key) ne {}} {
interp eval $itrp set ::$key $vars($key)
}
}
__evaluateModulefile $itrp $mod_file $vr_spec_list
}
rename runModuleUse _runModuleUse
proc runModuleUse {cmd mode pos args} {
set optlist [list]
set pathlist [list]
foreach arg $args {
switch -glob -- $arg {
-* {
lappend optlist $arg
}
deprecated -
unstable {
set tag [string index $arg 0]
module remove-path MODULES_HIDE_TAG_$tag 0 1
if {$cmd eq {use}} {
module prepend-path MODULES_HIDE_TAG_$tag 0
} else {
module prepend-path MODULES_HIDE_TAG_$tag 1
}
return
}
default {
if { [info exists ::g_OlInfo($arg:type)] } {
if {[info exists ::env(LOADEDMODULES)] &&\
$::env(LOADEDMODULES) ne ""} {
reportErrorAndExit "Overlays can only be added or removed if no modules are loaded"
}
lappend pathlist {*}[overlay-get-moddirs $pos $arg]
if {$pathlist eq {}} {
return
}
} elseif {$arg in $::g_Groups} {
foreach ol $::g_UsedOverlays {
set dir [file join {*}$::g_OlInfo($ol:modulefiles_root)\
$arg modulefiles]
if {[file isdirectory $dir]} {
lappend pathlist $dir
}
}
} else {
if {[file isdirectory $arg]} {
lappend pathlist $arg
} else {
reportErrorAndExit "Argument '$arg' is neither a directory, release stage or overay!"
}
}
}
}
}
if {$pathlist eq {}} {
puts stderr {Used overlays:}
foreach ol $::g_UsedOverlays {
if {$ol ne {none}} {
puts stderr " $ol"
}
}
puts stderr {Used release stages:}
puts stderr { stable}
if {{u} ni $::g_HideTags} {
puts stderr { unstable}
}
if {{d} ni $::g_HideTags} {
puts stderr { deprecated}
}
}
_runModuleUse $cmd $mode $pos {*}$optlist {*}$pathlist
}
rename getModuleHidingLevel _getModuleHidingLevel
proc getModuleHidingLevel {mod fpmod {update 1}} {
if {[string match {*/.config-*} $mod]} {return 2}
if {[string match {*/.deps-*} $mod]} {return 2}
if {[string match {*/.release-*} $mod]} {return 2}
# if full path module has been hidden, this hidden level is the base level
# value we will return
set baselvl -1
set modroot [lindex [file split $mod] 0]
if {$fpmod ne {}} {
if {[info exists ::g_moduleHideFullPath($fpmod)]} {
set baselvl $::g_moduleHideFullPath($fpmod)
} else {
set fp_mod [file split $fpmod]
set ol_mod [_find_overlay $fp_mod]
if {$::g_OlInfo($ol_mod:layout) eq {Pmodules}} {
set grp_mod [lindex $fp_mod $::g_OlInfo($ol_mod:len_modroot)]
if {[info exists ::g_moduleHideOverlay($modroot)]} {
# maybe hidden
lassign $::g_moduleHideOverlay($modroot) ol_hid grp
if {$::g_OlInfo($ol_hid:type) eq {h}} {
if {$grp eq $grp_mod} {
set i [lsearch -exact $::g_UsedOverlays $ol_mod]
set j [lsearch -exact $::g_UsedOverlays $ol_hid]
if { $i > $j} {
return 2
}
}
}
} else {
set ::g_moduleHideOverlay($modroot) "$ol_mod $grp_mod"
}
}
}
}
foreach tag [getMatchingTagList $mod $fpmod] {
if {$tag in $::g_HideTags} {
return 1
}
}
# look if mod matches one of the hidden module specs applying to mod root
if {[info exists ::g_moduleHideRoot($modroot)]} {
for {set lvl 2} {$lvl > -1} {incr lvl -1} {
# no need to search anymore if we have reached same hiding level as
# one defined on full path module designation
if {$lvl == $baselvl} {
break
}
foreach hmodspec [lindex $::g_moduleHideRoot($modroot) $lvl] {
if {[modEq $hmodspec $mod eqstart 1 0 1 {}]} {
return $lvl
}
}
}
}
return $baselvl
}
proc module-maintainer {args} {
lset args 0 "Maintainer: [lindex $args 0]"
lappend ::g_help_lines [join $args]
}
proc module-license {args} {
lset args 0 "License: [lindex $args 0]"
lappend ::g_help_lines [join $args]
}
proc module-url {args} {
lset args 0 "Url: [lindex $args 0]"
lappend ::g_help_lines [join $args]
}
set modulerc_extra_vars {\
P {} V {}\
V_MAJOR {} V_MINOR {} V_PATCHLVL {} V_RELEASE {} V_PKG {}\
PREFIX {}\
GROUP {}\
}
set modulefile_extra_cmds {\
module-addgroup module-addgroup\
module-maintainer module-maintainer\
module-license module-license\
module-url module-url\
overlay-define overlay-define\
}
# initialize
if {[info exists ::env(MODULES_HOSTCONFIG)]} {
source $::env(MODULES_HOSTCONFIG)
} else {
overlay-define base n Pmodules /opt/psi {} {Tools Programming}
}
# get used overlays and groups from MODULEPATH
foreach dir [split $::env(MODULEPATH) $::tcl_platform(pathSeparator)] {
if { [info exists ::g_Dir2Overlay($dir)] } {
set ol_name $::g_Dir2Overlay($dir)
set group [lindex [file split $dir] end-1]
} else {
set ol_name none
set group none
}
if { $ol_name ni $::g_UsedOverlays } {
lappend ::g_UsedOverlays $ol_name
}
if { $group ni $::g_UsedGroups } {
lappend ::g_UsedGroups $group
}
}
foreach {tag value} [array get ::env MODULES_HIDE_TAG_*] {
set tag [string range $tag [string length {MODULES_HIDE_TAG_}] end]
if {$value > 0} {
lappend ::g_HideTags $tag
}
}
# Local Variables:
# tcl-indent-level: 3
# End: