Environment Modules¶
Welcome to the Environment Modules documentation portal. The Environment Modules package provides for the dynamic modification of a user's environment via modulefiles.
The Modules package is a tool that simplifies shell initialization and lets users easily modify their environment during a session using modulefiles.
Each modulefile contains the information needed to configure the shell for
an application. Once the Modules package is initialized, the environment
can be modified on a per-module basis using the module command
which interprets modulefiles. Typically modulefiles instruct the
module command to alter or set shell environment variables such as
PATH
, MANPATH
, etc. modulefiles may be shared by many
users on a system and users may have their own collection to supplement or
replace the shared modulefiles.
Modules can be loaded and unloaded dynamically and atomically, in an clean fashion. All popular shells are supported, including bash, ksh, zsh, sh, csh, tcsh, fish, cmd, as well as some scripting languages such as tcl, perl, python, ruby, cmake and r.
Modules are useful in managing different versions of applications. Modules can also be bundled into meta-modules that will load an entire suite of different applications.
Note
Modules presented here are ones that modify the shell or script execution environment. They should not be confused with language-specific modules (e.g., Perl modules, Python modules or R modules) that add specific capabilities to scripts.
Quick examples¶
Here is an example of loading a module on a Linux machine under bash.
$ module load gcc/9.4.0
$ which gcc
$ /usr/local/gcc/9.4.0/linux-x86_64/bin/gcc
Now we'll switch to a different version of the module
$ module switch gcc gcc/10
$ which gcc
/usr/local/gcc/10.3.0/linux-x86_64/bin/gcc
And now we'll unload the module altogether
$ module unload gcc
$ which gcc
gcc not found
Now we'll log into a different machine, using a different shell (tcsh).
% module load gcc/10.3
% which gcc
/usr/local/gcc/10.3.0/linux-aarch64/bin/gcc
Note that the command line is exactly the same, but the path has automatically configured to the correct architecture.
Installing Modules on Unix¶
This document is an overview of building and installing Modules on a Unix system.
Requirements¶
Modules consists of one Tcl script so to run it from a user shell the only
requirement is to have a working version of tclsh
(version 8.5 or later)
available on your system. tclsh
is a part of Tcl
(http://www.tcl-lang.org/software/tcltk/).
To install Modules from a distribution tarball or a clone of the git
repository, a build step is there to tailor the modulecmd.tcl
and the
initialization scripts to the chosen installation configuration and create the
documentation files. This build step requires the tools to be found on your
system:
- bash
- make
- sed
- runtest
When also installing Modules Tcl extension library (enabled by default), these additional tools are needed:
- grep
- gcc
- tcl-devel >= 8.5
When installing from a distribution tarball, documentation is pre-built and scripts to configure Modules Tcl extension library build are already generated. Thus no additional software is required. When installing from a clone of the git repository or from a git archive export, documentation and scripts to prepare for compilation have to be built and the following tools are required:
- autoconf
- automake
- autopoint
- python
- sphinx >= 1.0
Get Modules¶
Modules can usually be installed with the package manager of your Unix system.
It it is available by default on most Linux distributions, on OS X and
FreeBSD either
under the name of modules
or environment-modules
.
If you want to install Modules from sources, tarballs from all Modules' releases can be retrieved from one of the following link:
- https://github.com/cea-hpc/modules/releases/
- https://sourceforge.net/projects/modules/files/Modules/
For instance to download then unpack the last release of Modules:
$ curl -LJO https://github.com/cea-hpc/modules/releases/download/v5.3.0/modules-5.3.0.tar.gz $ tar xfz modules-5.3.0.tar.gz
Installation instructions¶
The simplest way to build and install Modules is:
$ ./configure $ make $ make install
Some explanation, step by step:
cd
to the directory containing the package's source code. Your system must have the above requirements installed to properly build scripts, and documentation if build occurs from a clone of the git repository.- Type
./configure
to adapt the installation for your system. At this step you can choose the installation paths and the features you want to enable in the initialization scripts (see Build and installation options section below for a complete overview of the available options) - Type
make
to adapt scripts to the configuration, build Tcl extension library if enabled and build documentation if working from git repository. - Optionally, type
make test
to run the test suite. - Type
make install
to install modulecmd.tcl, initialization scripts and documentation. - Optionally, type
make testinstall
to run the installation test suite. - You can remove the built files from the source code directory by typing
make clean
. To also remove the files thatconfigure
created, typemake distclean
.
A default installation process like described above will install Modules
under /usr/local/Modules
. You can change this with the --prefix
option. By default, /usr/local/Modules/modulefiles
will be setup as
the default directory containing modulefiles. --modulefilesdir
option enables to change this directory location. For example:
$ ./configure --prefix=/usr/share/Modules \
--modulefilesdir=/etc/modulefiles
See Build and installation options section to discover all ./configure
option available.
Note
GNU Make is excepted to be used for this build and installation
process. On non-Linux systems, the gmake
should be called instead of
make
.
Configuration¶
Once installed you should review and adapt the configuration to make it fit your needs. The following steps are provided for example. They are not necessarily mandatory as it depends of the kind of setup you want to achieve.
Enable Modules initialization at shell startup. An easy way to get module function defined and its associated configuration setup at shell startup is to make the initialization scripts part of the system-wide environment setup in
/etc/profile.d
. To do so, make a link in this directory to the profile scripts that can be found in your Modules installation init directory:$ ln -s PREFIX/init/profile.sh /etc/profile.d/modules.sh $ ln -s PREFIX/init/profile.csh /etc/profile.d/modules.csh
These profile scripts will automatically adapt to the kind of
sh
orcsh
shell you are running.Another approach may be to get the Modules initialization script sourced from the shell configuration startup file. For instance following line could be added to the end of the
~/.bashrc
file if running Bash shell:source PREFIX/init/bash
Beware that shells have multiple ways to initialize depending if they are a login shell or not and if they are launched in interactive mode or not.
Define module paths to enable by default. Edit
initrc
configuration file in the directory designated by the--etcdir
option or editmodulespath
in the same directory.If you use
modulespath
configuration file, add one line mentioning each modulefile directory:/path/to/regular/modulefiles /path/to/other/modulefiles
If you use
initrc
configuration file, add one line mentioning each modulefile directory prefixed by themodule use
command:module use /path/to/regular/modulefiles module use /path/to/other/modulefiles
In case both configuration files
initrc
andmodulespath
are present, Modules initialization process will first evaluatemodulespath
theninitrc
.By default, the modulepaths specified on the
--with-modulepath
installation option are automatically defined for use ininitrc
(or inmodulespath
if the--enable-modulespath
installation option has been set).Note
If you have set
--with-initconf-in
toinitdir
to install the Modules initialization configurations in the configuration directory designated by the--initdir
option, the configuration filesinitrc
andmodulespath
are respectively namedmodulerc
and.modulespath
.Define modulefiles to load by default. Edit
initrc
configuration file. Modulefiles to load cannot be specified inmodulespath
file. Add there all the modulefiles you want to load by default at Modules initialization time.Add one line mentioning each modulefile to load prefixed by the
module load
command:module load foo module load bar
By default, the modules specified on the
--with-loadedmodules
installation option are automatically defined for load ininitrc
.Alternatively, if users have module collections saved in their
HOME
directory, you may prefer restoring their default collection when Modules initializes rather loading the default module list:if {[is-saved default]} { module restore } else { module load foo module load bar }
In fact you can add to the
initrc
configuration file any kind of supported module command, likemodule config
commands to tune module's default behaviors. This configuration way is recommended over directly modifying the shell initialization scripts.
See the Configuration options section to discover all Modules
config
options available, their default value and the installation
options linked to them.
If you go through the above steps you should have a valid setup tuned to your needs. After that you still have to write modulefiles to get something to load and unload in your newly configured Modules setup. In case you want to achieve a specific setup, some additional steps may be required:
In case the configuration you expect cannot be achieved through the
initrc
configuration file, you may review and tune the initialization scripts. These files are located in the directory designated by the--initdir
option. Beware that these scripts could be overwritten when upgrading to a newer version of Modules, so configuration should be done through theinitrc
file as far as possible.If you want to alter the way the
modulecmd.tcl
script operates, thesiteconfig.tcl
script may be used. This Tcl file is located in the directory designated by the--etcdir
option. Every time the module command is called, it executes themodulecmd.tcl
script which in turns sources thesiteconfig.tcl
script during its startup phase. The site-specific configuration script could override default configuration values and more largely could supersede all procedures defined inmodulecmd.tcl
to obtain specific behaviors.Prior running the module sub-command specified as argument, the
modulecmd.tcl
script evaluates the global run-command files. These files are either therc
file in the directory designated by the--etcdir
option, the file designated in theMODULERCFILE
environment variable or the user-specific RC file located in$HOME/.modulerc
. The RC files are modulefiles (limited to a subset of the modulefile Tcl commands) that could define global module aliases, virtual modules or module properties such as tags, forbidding rules, etc.Note
Run-command files are intended to set parameters for modulefiles, not to configure the module command itself.
To learn more about siteconfig and run-command files, see the Modulecmd startup section in module reference manual. You may also look at the available setup recipes to get concrete deployment examples of these files.
Build and installation options¶
Options available at the ./configure
installation step are described
below. These options enable to choose the installation paths and the
features to enable or disable. You can also get a description of these
options by typing ./configure --help
.
Fine tuning of the installation directories (the default value for each option is displayed within brackets):
-
--bindir
=DIR
¶ Directory for executables reachable by users [
PREFIX/bin
]
-
--datarootdir
=DIR
¶ Base directory to set the man and doc directories [
PREFIX/share
]
-
--docdir
=DIR
¶ Directory to host documentation other than man pages like README, license file, etc [
DATAROOTDIR/doc
]
-
--etcdir
=DIR
¶ Directory for the executable configuration scripts [
PREFIX/etc
]New in version 4.1.
-
--initdir
=DIR
¶ Directory for the per-shell environment initialization scripts [
PREFIX/init
]
-
--libdir
=DIR
¶ Directory for object code libraries like libtclenvmodules.so [
PREFIX/lib
]
-
--libexecdir
=DIR
¶ Directory for executables called by other executables like modulecmd.tcl [
PREFIX/libexec
]
-
--mandir
=DIR
¶ Directory to host man pages [
DATAROOTDIR/man
]
-
--modulefilesdir
=DIR
¶ Directory of main modulefiles also called system modulefiles [
PREFIX/modulefiles
]New in version 4.0.
-
--nagelfardatadir
=DIR
¶ Directory to host Nagelfar linter addon files [
DATAROOTDIR/nagelfar
]New in version 5.2.
-
--prefix
=PREFIX
¶ Installation root directory [
/usr/local/Modules
]
-
--vimdatadir
=DIR
¶ Directory to host Vim addon files [
DATAROOTDIR/vim/vimfiles
]New in version 4.3.
Optional Features (the default for each option is displayed within
parenthesis, to disable an option replace enable
by disable
for
instance --disable-set-manpath
):
-
--enable-advanced-version-spec
¶ Activate the advanced module version specifiers which enables to finely select module versions by specifying after the module name a version constraint prefixed by the
@
character. This option also allows to specify module variants. (default=yes)This installation option defines the default value of the
advanced_version_spec
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.4.
Changed in version 5.0: Configuration option default set to
yes
-
--enable-append-binpath
¶ Append rather prepend binary directory to the PATH environment variable when the
--enable-set-binpath
option is enabled. (default=no)New in version 4.2.
-
--enable-append-manpath
¶ Append rather prepend man page directory to the MANPATH environment variable when the
--enable-set-manpath
option is enabled. (default=no)New in version 4.2.
-
--enable-auto-handling
¶ Set modulecmd.tcl to automatically apply automated modulefiles handling actions, like loading the pre-requisites of a modulefile when loading this modulefile. (default=yes)
This installation option defines the default value of the
auto_handling
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.2.
Changed in version 5.0: Configuration option default set to
yes
-
--enable-avail-indepth
¶ When performing an
avail
sub-command, include in search results the matching modulefiles and directories and recursively the modulefiles and directories contained in these matching directories when enabled or limit search results to the matching modulefiles and directories found at the depth level expressed by the search query if disabled. (default=yes)This installation option defines the default value of the
avail_indepth
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--enable-color
¶ Control if output should be colored by default or not. A value of
yes
equals to theauto
color mode.no
equals to thenever
color mode. (default=yes)This installation option defines the default value of the
color
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
Changed in version 5.0: Configuration option default set to
yes
-
--enable-doc-install
¶ Install the documentation files in the documentation directory defined with the
--docdir
option. This feature has no impact on manual pages installation. Disabling documentation file installation is useful in case of installation process handled via a package manager which handles by itself the installation of this kind of documents. (default=yes)New in version 4.0.
-
--enable-example-modulefiles
¶ Install some modulefiles provided as example in the system modulefiles directory defined with the
--modulefilesdir
option. (default=yes)New in version 4.0.
-
--enable-extended-default
¶ Allow to specify module versions by their starting part, i.e. substring separated from the rest of the version string by a
.
character. (default=yes)This installation option defines the default value of the
extended_default
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.4.
Changed in version 5.0: Configuration option default set to
yes
-
--enable-implicit-default
¶ Define an implicit default version, for modules with none explicitly defined, to select when the name of the module to evaluate is passed without the mention of a specific version. When this option is disabled the name of the module passed for evaluation should be fully qualified elsewhere an error is returned. (default=yes)
This installation option defines the default value of the
implicit_default
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--enable-implicit-requirement
¶ Implicitly define a prereq or a conflict requirement toward modules specified respectively on
module load
ormodule unload
commands in modulefile. (default=yes)This installation option defines the default value of the
implicit_requirement
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
-
--enable-libtclenvmodules
¶ Build and install the Modules Tcl extension library which provides optimized Tcl commands for the modulecmd.tcl script. (default=yes)
New in version 4.3.
Enable check of the version specified right after Modules magic cookie (i.e.,
#%Module
file signature) in modulefiles, which defines the minimal version of the Modules tool to use in order to evaluate the modulefile. (default=yes)This installation option defines the default value of the
mcookie_version_check
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
-
--enable-ml
¶ Define the ml command, a handy frontend to the module command, when Modules initializes. (default=yes)
This installation option defines the default value of the
ml
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.5.
-
--enable-modulespath
, --enable-dotmodulespath
¶ Set the module paths defined by
--with-modulepath
option in amodulespath
file (following C version fashion) within the initialization directory defined by the--etcdir
option rather than within theinitrc
file. Or respectively, if option--with-initconf-in
has been set toinitdir
, in a.modulespath
file within the configuration directory defined by the--initdir
option rather than within themodulerc
file. (default=no)New in version 4.0.
Changed in version 4.3: Option
--enable-modulespath
added
-
--enable-multilib-support
¶ Support multilib systems by looking in modulecmd.tcl at an alternative location where to find the Modules Tcl extension library depending on current machine architecture. (default=no)
New in version 4.6.
-
--enable-nagelfar-addons
¶ Install the Nagelfar linter addon files (syntax databases and plugins to lint modulefiles and modulercs) in the Nagelfar addons directory defined with the
--nagelfardatadir
option. (default=yes)New in version 5.2.
-
--enable-new-features
¶ Enable all new features that are disabled by default due to the substantial behavior changes they imply on Modules 5. This option does not enable other configuration option currently. (default=no)
New in version 4.7.
Changed in version 5.0: Configuration option has been reset following major version change as
--enable-auto-handling
,--enable-color
,--with-icase=search
,--enable-extended-default
and--enable-advanced-version-spec
are set by default on Modules 5.
-
--enable-quarantine-support
¶ Generate code in module function definition to add support for the environment variable quarantine mechanism (default=no)
This installation option defines the default value of the
quarantine_support
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.1.
Changed in version 5.0: Configuration option default set to
no
-
--enable-set-binpath
¶ Prepend binary directory defined by the
--bindir
option to the PATH environment variable in the shell initialization scripts. (default=yes)New in version 4.0.
-
--enable-set-manpath
¶ Prepend man page directory defined by the
--mandir
option to the MANPATH environment variable in the shell initialization scripts. (default=yes)New in version 4.0.
-
--enable-set-shell-startup
¶ Set when module function is defined the shell startup file to ensure that the module function is still defined in sub-shells. (default=no)
This installation option defines the default value of the
set_shell_startup
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
Changed in version 5.0: Configuration option default set to
no
-
--enable-silent-shell-debug-support
¶ Generate code in module function definition to add support for silencing shell debugging properties (default=no)
This installation option defines the default value of the
silent_shell_debug
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.2.
Changed in version 5.0: Configuration option default set to
no
-
--enable-versioning
¶ Append Modules version to installation prefix and deploy a
versions
modulepath shared between all versioning enabled Modules installation. A modulefile corresponding to Modules version is added to the shared modulepath and enables to switch from one Modules version to another. (default=no)
-
--enable-vim-addons
¶ Install the Vim addon files in the Vim addons directory defined with the
--vimdatadir
option. (default=yes)New in version 4.3.
-
--enable-wa-277
¶ Activate workaround for issue #277 related to Tcsh history mechanism which does not cope well with default module alias definition. Note that enabling this workaround solves Tcsh history issue but weakens shell evaluation of the code produced by modulefiles. (default=no)
This installation option defines the default value of the
wa_277
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--enable-windows-support
¶ Install all required files for Windows platform (module, ml and envml command batch file and
cmd.cmd
initialization script). (default=no)New in version 4.5.
Optional Packages (the default for each option is displayed within
parenthesis, to disable an option replace with
by without
for
instance --without-modulepath
):
-
--with-avail-output
=LIST
¶ Specify the content to report on avail sub-command regular output in addition to the available module names. Elements accepted in LIST are:
modulepath
,alias
,dirwsym
,sym
,tag
,key
,variant
andvariantifspec
(elements in LIST are separated by:
). The order of the elements in LIST does not matter. (default=modulepath:alias:dirwsym:sym:tag:variantifspec:key
)This installation option defines the default value of the
avail_output
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
Changed in version 5.3: Element
variant
addedChanged in version 5.3: Element
variantifspec
added and set by default
-
--with-avail-terse-output
=LIST
¶ Specify the content to report on avail sub-command terse output in addition addition to the available module names. Elements accepted in LIST are:
modulepath
,alias
,dirwsym
,sym
,tag
,key
,variant
andvariantifspec
(elements in LIST are separated by:
). The order of the elements in LIST does not matter. (default=modulepath:alias:dirwsym:sym:tag:variantifspec
)This installation option defines the default value of the
avail_terse_output
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
Changed in version 5.3: Element
variant
addedChanged in version 5.3: Element
variantifspec
added and set by default
-
--with-bashcompletiondir
=DIR
¶ Directory for Bash completion scripts. When this option is not set Bash completion script for Modules is installed in the initialization script directory and is sourced from Modules Bash initialization script. (default=)
New in version 5.1.
-
--with-bin-search-path
=PATHLIST
¶ List of paths to look at when searching the location of tools required to build and configure Modules (default=
/usr/bin:/bin:/usr/local/bin
)New in version 4.2.
-
--with-dark-background-colors
=SGRLIST
¶ Default color set to apply if terminal background color is defined to
dark
. SGRLIST follows the same syntax than used inLS_COLORS
. Each element in SGRLIST is an output item associated to a Select Graphic Rendition (SGR) code. Elements in SGRLIST are separated by:
. Output items are designated by keys.Items able to be colorized are: highlighted element (
hi
), debug information (db
), trace information (tr
) tag separator (se
); Error (er
), warning (wa
), module error (me
) and info (in
) message prefixes; Modulepath (mp
), directory (di
), module alias (al
), module variant (va
), module symbolic version (sy
) and moduledefault
version (de
).Module tags can also be colorized. The key to set in the color palette to get a graphical rendering of a tag is the tag name or the tag abbreviation if one is defined for tag. The SGR code applied to a tag name is ignored if an abbreviation is set for this tag thus the SGR code should be defined for this abbreviation to get a graphical rendering. Each basic tag has by default a key set in the color palette, based on its abbreviated string: auto-loaded (
aL
), forbidden (F
), hidden and hidden-loaded (H
), loaded (L
), nearly-forbidden (nF
), sticky (S
), super-sticky (sS
) and keep-loaded (kL
).For a complete SGR code reference, see https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters. (default=
hi=1:db=2:tr=2:se=2:er=91:wa=93:me=95:in=94:mp=1;94:di=94:al=96:va=93:sy=95:de=4:cm=92:aL=100:L=90;47:H=2:F=41:nF=43:S=46:sS=44:kL=30;48;5;109
)This installation option defines the default value of the
colors
configuration option whenterm_background
configuration option equalsdark
.colors
could be changed after installation with theconfig
sub-command.New in version 4.3.
Changed in version 4.6: Output item for trace information (
tr
) addedChanged in version 4.7: Output items for module tags auto-loaded (
aL
), forbidden (F
), hidden and hidden-loaded (H
), loaded (L
), nearly-forbidden (nF
), sticky (S
) and super-sticky (sS
) addedChanged in version 4.8: Output item for module variant (
va
) addedChanged in version 5.1: Output item for keep-loaded module tag (
kL
) added
-
--with-editor
=BIN
¶ Name or full path of default editor program to use to open modulefile through the
edit
sub-command. (default=vi
)This installation option defines the default value of the
editor
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.8.
-
--with-fishcompletiondir
=DIR
¶ Directory for Fish completion scripts. When this option is not set Fish completion script for Modules is installed in the initialization script directory and is sourced from Modules Fish initialization script. (default=)
New in version 5.1.
-
--with-icase
=VALUE
¶ Apply a case insensitive match to module specification on
avail
,whatis
andpaths
sub-commands (when set tosearch
) or on all module sub-commands and modulefile Tcl commands for the module specification they receive as argument (when set toalways
). Case insensitive match is disabled when this option is set tonever
. (default=search
)This installation option defines the default value of the
icase
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.4.
Changed in version 5.0: Configuration option default set to
search
-
--with-initconf-in
=VALUE
¶ Location where to install Modules initialization configuration files. Either
initdir
oretcdir
(default=etcdir
)New in version 4.1.
Changed in version 5.0: Configuration option default set to
etcdir
-
--with-light-background-colors
=SGRLIST
¶ Default color set to apply if terminal background color is defined to
light
. Expect the same syntax than described for--with-dark-background-colors
. (default=hi=1:db=2:tr=2:se=2:er=31:wa=33:me=35:in=34:mp=1;34:di=34:al=36:va=33:sy=35:de=4:cm=32:aL=107:L=47:H=2:F=101:nF=103:S=106:sS=104:kL=48;5;109
)This installation option defines the default value of the
colors
configuration option whenterm_background
configuration option equalslight
.colors
could be changed after installation with theconfig
sub-command.New in version 4.3.
Changed in version 4.6: Output item for trace information (
tr
) addedChanged in version 4.7: Output items for module tags auto-loaded (
aL
), forbidden (F
), hidden and hidden-loaded (H
), loaded (L
), nearly-forbidden (nF
), sticky (S
) and super-sticky (sS
) addedChanged in version 4.8: Output item for module variant (
va
) addedChanged in version 5.1: Output item for keep-loaded module tag (
kL
) added
-
--with-list-output
=LIST
¶ Specify the content to report on list sub-command regular output in addition to the loaded module names. Elements accepted in LIST are:
header
,idx
,variant
,sym
,tag
andkey
(elements in LIST are separated by:
). The order of the elements in LIST does not matter. (default=header:idx:variant:sym:tag:key
)This installation option defines the default value of the
list_output
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
Changed in version 4.8: Element
variant
added and set by default
-
--with-list-terse-output
=LIST
¶ Specify the content to report on list sub-command terse output in addition to the loaded module names. Elements accepted in LIST are:
header
,idx
,variant
,sym
,tag
andkey
(elements in LIST are separated by:
). The order of the elements in LIST does not matter. (default=header
)This installation option defines the default value of the
list_terse_output
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
Changed in version 4.8: Element
variant
added
-
--with-loadedmodules
=MODLIST
¶ Default modulefiles to load at Modules initialization time. Each modulefile in this list should be separated by
:
. Defined value is registered in theinitrc
configuration file or in themodulerc
file if--with-initconf-in
is set toinitdir
. (default=)New in version 4.0.
-
--with-locked-configs
=CONFIGLIST
¶ Ignore environment variable superseding value for the listed configuration options. Accepted option names in CONFIGLIST are
extra_siteconfig
andimplicit_default
(each option name should be separated by whitespace character). (default=)This installation option defines the default value of the
locked_configs
configuration option which cannot not be changed after installation.New in version 4.3.
-
--with-modulepath
=PATHLIST
¶ Default path list to setup as the default modulepaths. Each path in this list should be separated by
:
. Defined value is registered in theinitrc
ormodulespath
configuration file, depending on the--enable-modulespath
option. These files are respectively calledmodulerc
and.modulespath
if--with-initconf-in
is set toinitdir
. The path list value is read at initialization time to populate the MODULEPATH environment variable. By default, this modulepath is composed of the directory set for the system modulefiles (default=PREFIX/modulefiles
orBASEPREFIX/$MODULE_VERSION/modulefiles
if versioning installation mode enabled)New in version 4.0.
-
--with-moduleshome
¶ Location of the main Modules package file directory (default=
PREFIX
)This installation option defines the default value of the
home
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.4.
-
--with-nearly-forbidden-days
=VALUE
¶ Define the number of days a module is considered nearly forbidden prior reaching its expiry date. VALUE should be an integer comprised between 0 and 365. (default=
14
)This installation option defines the default value of the
nearly_forbidden_days
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.6.
-
--with-pager
=BIN
¶ Name or full path of default pager program to use to paginate informational message output (can be superseded at run-time by environment variable) (default=
less
)This installation option and
--with-pager-opts
define the default value of thepager
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.1.
-
--with-pager-opts
=OPTLIST
¶ Settings to apply to default pager program (default=
-eFKRX
)This installation option and
--with-pager
define the default value of thepager
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.1.
-
--with-python
=BIN
¶ Name or full path of Python interpreter command to set as shebang for helper scripts. (default=
python
)New in version 4.5.
-
--with-quarantine-vars
=<VARNAME[=VALUE] ...>
¶ Environment variables to put in quarantine when running the module command to ensure it a sane execution environment (each variable should be separated by space character). A value can eventually be set to a quarantine variable instead of emptying it. (default=)
This installation option defines the default value of the
MODULES_RUN_QUARANTINE
andMODULES_RUNENV_<VAR>
environment variables which could be changed after installation with theconfig
sub-command onrun_quarantine
configuration option.New in version 4.1.
-
--with-search-match
=VALUE
¶ When searching for a module with
avail
sub-command, match query string against module name start (starts_with
) or any part of module name string (contains
). (default=starts_with
)This installation option defines the default value of the
search_match
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--with-tag-abbrev
=ABBRVLIST
¶ Define the abbreviation to use when reporting each module tag. Each element in ABBRVLIST is a tag name associated to an abbreviation string (elements in ABBRVLIST are separated by
:
). (default=auto-loaded=aL:loaded=L:hidden=H:hidden-loaded=H:forbidden=F:nearly-forbidden=nF:sticky=S:super-sticky=sS:keep-loaded=kL
)This installation option defines the default value of the
tag_abbrev
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
Changed in version 5.1: Abbreviation for
keep-loaded
tag added
-
--with-tag-color-name
=TAGLIST
¶ Define the tags whose graphical rendering should be applied over their name instead of over the name of the module they are attached to. Each element in TAGLIST is a tag name or abbreviation (elements in TAGLIST are separated by
:
). (default=)This installation option defines the default value of the
tag_color_name
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.7.
-
--with-tcl
¶ Directory containing the Tcl configuration script
tclConfig.sh
. Useful to compile Modules Tcl extension library if this file cannot be automatically found in default locations.
-
--with-tclinclude
¶ Directory containing the Tcl header files. Useful to compile Modules Tcl extension library if these headers cannot be automatically found in default locations.
-
--with-tclsh
=BIN
¶ Name or full path of Tcl interpreter shell (default=
tclsh
)New in version 4.0.
-
--with-tcl-linter
=BIN
¶ Name or full path of program to use to lint modulefile through the
lint
sub-command. (default=nagelfar.tcl
)This installation option and
--with-tcl-linter-opts
define the default value of thetcl_linter
configuration option which could be changed after installation with theconfig
sub-command.New in version 5.2.
-
--with-tcl-linter-opts
=OPTLIST
¶ Settings to apply to Tcl linter program (default=)
This installation option and
--with-tcl-linter
define the default value of thetcl_linter
configuration option which could be changed after installation with theconfig
sub-command.New in version 5.2.
-
--with-terminal-background
=VALUE
¶ The terminal background color that determines the color set to apply by default between the
dark
background colors or thelight
background colors (default=dark
)This installation option defines the default value of the
term_background
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--with-unload-match-order
=VALUE
¶ When unloading a module if multiple loaded modules match the request, unload module loaded first (
returnfirst
) or module loaded last (returnlast
) (default=returnlast
)This installation option defines the default value of the
unload_match_order
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--with-variant-shortcut
=SHORTCUTLIST
¶ Define the shortcut characters that could be used to specify variant names. Each element in SHORTCUTLIST is a variant name associated to a shortcut character (e.g.,
foo=%
). Shortcuts cannot exceed a length of 1 character and cannot be alphanumeric characters ([A-Za-z0-9]) or characters with already a special meaning ([+~/@=-]). Elements in SHORTCUTLIST are separated by:
. (default=)This installation option defines the default value of the
variant_shortcut
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.8.
-
--with-verbosity
=VALUE
¶ Specify default message verbosity. accepted values are
silent
,concise
,normal
,verbose
,verbose2
,trace
,debug
anddebug2
. (default=normal
)This installation option defines the default value of the
verbosity
configuration option which could be changed after installation with theconfig
sub-command.New in version 4.3.
-
--with-zshcompletiondir
=DIR
¶ Directory for Zsh completion scripts. When this option is not set Zsh completion script for Modules is installed in the initialization script directory and
FPATH
is set in Zsh initialization script to point to this location. (default=)New in version 5.1.
Configuration options¶
Options available through the config
sub-command are described
below. In addition to their default value, the related installation option,
environment variable and command-line switch are listed for each configuration
option. This table also describes if each configuration option needs to be set
prior or during Modules initialization and if it can be modified after
installation.
Installing Modules on Windows¶
This document is an overview of building and installing Modules on a Windows platform.
Requirements¶
Modules consists of one Tcl script so to run it from a user shell the only
requirement is to have a working version of tclsh
(version 8.5 or later)
available on your system. tclsh
is a part of Tcl.
A specific distribution zipball is provided to install Modules on a Windows platform. Content of this distribution zipball is ready for use and does not require a specific build step. All scripts and documentation found in this zipball are pre-built so there is no specific tools are required to install Modules from the Windows-specific distribution zipball.
Installation instructions¶
- Install a Tcl binary distribution for Windows like ActiveTcl or Magicsplat Tcl/Tk for Windows. Follow instructions provided with the chosen distribution to install it.
Once installed, verify that the
tclsh
command is correctly found in definedPATH
by typing the following command from a Windowscmd
shell (windows
string should be obtained as result):> echo puts $tcl_platform(platform) | tclsh windows
Download Modules specific distribution zipball for Windows from SourceForge or GitHub. Such distribution archives are available for Modules release starting version
4.5.0
and can be distinguished from the source tarball by the-win
suffix in their name.
- Unpack downloaded zip file then enter deflated directory and execute the
INSTALL.bat
script file found in it. This script installs files by default inC:\Program Files\Environment Modules\
directory and adds thebin
directory in this installation location to the system-widePATH
environment variable.
Note
INSTALL.bat
script may require to be run with administrator
rights to perform installation correctly.
Once installed, verify that the
module
command is correctly found in definedPATH
by typing the following command from a Windowscmd
shell:> module -V Modules Release 4.4.1 (2020-01-03)
Installation location can be adapted by running the INSTALL.bat
script
from a cmd
console shell and passing desired installation target as
argument. For instance to install Modules in C:\EnvironmentModules
directory:
> INSTALL.bat C:\EnvironmentModules
Modules installation is now operational and you can setup your modulefiles. By
default, the modulefiles
directory in installation directory is defined as
a modulepath and contains few modulefile examples:
> module avail
------- C:/Program Files/Environment Modules/modulefiles --------
module-git module-info null
Documentation of the module and ml commands and
modulefile syntax can be found in the doc
directory in
installation directory.
New features¶
This document describes the major changes occurring between versions of Modules. It provides an overview of the new features and changed behaviors that will be encountered when upgrading.
v5.3¶
Module cache¶
A module cache file can be created under each modulepath directory with new
cachebuild
sub-command. Cache file is named .modulecache
and
contains in one file all modulefiles and modulercs found in modulepath
directory.
When cache file is available, module search mechanism uses this file rather walking through the content of modulepath directory. I/O operations are saved this way which reduces search processing time.
When searching for available modules without cache, each file contained in enabled modulepaths is opened to check if it is a modulefile or not. Such checks lead to a large number of I/O operations on large module setup like in the below example where a total of 1051 modulefiles are available:
$ module -o "" avail -t | wc -l 1051 $ syscall_list=access,close,getdents64,newfstatat,openat,read $ strace -f -e $syscall_list -c $MODULES_CMD bash avail % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 31.09 0.003776 2 1424 9 openat 28.56 0.003469 2 1649 3 newfstatat 14.08 0.001710 1 1421 close 11.85 0.001439 3 460 getdents64 10.88 0.001321 0 1505 read 3.54 0.000430 4 107 5 access ------ ----------- ----------- --------- --------- ---------------- 100.00 0.012145 1 6566 17 total
After building cache file for every enabled modulepaths in this example setup, a lot of I/O operations are saved when searching for available modules:
$ module cachebuild Creating /path/to/modulefiles/.modulecache Creating /path/to/modulefiles.2/.modulecache Creating /path/to/modulefiles.3/.modulecache $ module config cache_buffer_bytes 1000000 $ strace -f -e $syscall_list -c $MODULES_CMD bash avail % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 70.19 0.000544 2 255 read 13.16 0.000102 2 38 9 openat 8.90 0.000069 1 35 close 6.06 0.000047 1 31 2 newfstatat 1.68 0.000013 1 11 2 access ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000775 2 370 13 total
A significant execution time drop may be noticed, especially if modulepath directories are stored on heavily loaded network filesystem.
To further optimize I/O operation count, the cache_buffer_bytes
configuration option can be set like in the above example to use fewer number
of read
operation to load cache file content.
To build cache file, user should be granted write access on modulepath directory. Modulefiles or directories that are not accessible for everyone are not recorded in cache. An indication is saved instead to test these limited access elements when cache is loaded to determine if they are available to currently running user.
Cache file can be ignored with --ignore-cache
command line switch or
more permanently with ignore_cache
configuration option.
Cache file is valid indefinitely by default but cache_expiry_secs
configuration option can be used to define the number of seconds a cache file
is considered valid after being generated. Expired cache file is ignored.
Cache file of enabled modulepaths can be deleted all at once with
cacheclear
sub-command.
Querying available module variants¶
A new mechanism named Extra match search is introduced to evaluate modulefiles during a module search to find those matching an extra query on a variant value, a dependency or an environment variable definition.
During this specific evaluation, modulefiles are interpreted in scan mode to collect the different Tcl modulefile commands they use. Special care should be given when writing modulefiles to ensure they cope with such evaluation mode.
Extra match search mechanism is available on avail
,
whatis
and paths
sub-commands.
With this new mechanism, it is possible to list all available variant defined in modulefiles with their associated values:
$ module config avail_output modulepath:alias:dirwsym:sym:tag:key:variant $ module config variant_shortcut toolchain=% $ module avail --------------------- /path/to/modulefiles --------------------- bar/1.0{%a,b} foo/1.0{%a} qux/1.0{%a,b} bar/2.0{%b} foo/2.0{%a,b,c} qux/2.0{%b,c} Key: modulepath {%value}={toolchain=value} default-version {variant=value}
You can also search for modules defining a specific variant value:
$ module avail %a --------------------- /path/to/modulefiles --------------------- bar/1.0{%a,b} foo/1.0{%a} foo/2.0{%a,b,c} qux/1.0{%a,b} Key: modulepath {%value}={toolchain=value} default-version {variant=value}
Note
As extra match search implies additional modulefile evaluations, it is advised to build and use Module cache to improve search speed.
Two new elements, variant
and variantifspec
, are added to the allowed
value list of avail_output
and avail_terse_output
configuration options. The latter is set in the default value list of both
options. When variant
is set, variants and their possible values are
reported along module they are associated to. When variantifspec
is set,
available variants are reported only if a variant is specified in search
query.
$ module config --reset avail_output $ module config avail_output Modules Release 5.3.0 (2023-05-14) - Config. name ---------.- Value (set by if default overridden) --------------- avail_output modulepath:alias:dirwsym:sym:tag:variantifspec:key $ module avail foo --------------------- /path/to/modulefiles --------------------- foo/1.0 foo/2.0 Key: modulepath $ module avail foo %a --------------------- /path/to/modulefiles --------------------- foo/1.0{%a} foo/2.0{%a,b,c} Key: modulepath {%value}={toolchain=value} default-version {variant=value}
Extra specifiers¶
Extra specifiers are introduced to query content of modulefiles. They can be
specified with element:name syntax as part of module specification on module
search commands (avail
, paths
and and whatis
).
Extra specifiers trigger Extra match search mechanism when found in module specification. Available modulefiles are evaluated in scan mode to collect the different Tcl modulefile commands they use.
$ module avail variant:toolchain --------------------- /path/to/modulefiles --------------------- bar/1.0 bar/2.0 foo/1.0 foo/2.0 qux/1.0 qux/2.0
In the above example, all modulefiles defining a toolchain
variant are
returned.
Most Tcl modulefile commands can be queried with extra specifiers:
variant
, setenv
, unsetenv
, append-path
, prepend-path
,
remove-path
, pushenv
, complete
, uncomplete
, set-alias
,
unset-alias
, set-function
, unset-function
, chdir
, family
,
prereq
, prereq-any
, prereq-all
, depends-on
, always-load
,
load
, load-any
, try-load
, switch
, switch-on
,
switch-off
, conflict
and unload
. Commands that handle environment
variables may be aliased envvar
. Commands that define a module requirement
may be aliased require
and those that define a module incompatibility may
be aliased incompat
.
When several extra specifiers are set in query, modules returned are those
matching both conditions. In the following example, all modulefiles
interacting with PATH
environment variable and requiring foo
module are returned.
$ module avail envvar:PATH require:foo --------------------- /path/to/modulefiles --------------------- bar/1.0 bar/2.0
Extra specifiers related to module requirement or incompatibility may leverage
the Advanced module version specifiers syntax. On following example,
modulefiles returned are those defining a requirement on foo
module with
version higher or equal to 1.2
and variant toolchain=a
selected.
$ module avail "require:foo@1.2: toolchain=a" --------------------- /path/to/modulefiles --------------------- bar/1.0
Note
Module aliases or symbolic versions used either in modulefile definitions or as extra specifier values are not resolved.
Append or subtract elements to current option value¶
For command-line switches and configuration options whose value is a
colon-separated list, it is now possible to append or subtract elements to the
current value. With a +
prefix elements are appended and with a -
prefix elements are subtracted.
This new feature applies to --output
/-o
command-line
switches and avail_output
, avail_terse_output
,
list_output
, list_terse_output
, colors
,
protected_envvars
, shells_with_ksh_fpath
,
tag_abbrev
, tag_color_name
, variant_shortcut
configuration options.
For instance, to output available foo modules without modulepath and tag information:
$ module -o -modulepath:tag avail foo foo/1.0 foo/2.0
On following example, terse output mode of list sub-command is permanently updated to report variant information:
$ module config list_terse_output Modules Release 5.3.0 (2023-05-14) - Config. name ---------.- Value (set by if default overridden) --------------- list_terse_output header $ module config list_terse_output +variant $ module config list_terse_output Modules Release 5.3.0 (2023-05-14) - Config. name ---------.- Value (set by if default overridden) --------------- list_terse_output header:variant (env-var)
v5.2¶
This new version is backward-compatible with previous version 5 release. It fixes bugs but also introduces new functionalities that are described in this section. See the 5.2 release notes for a complete list of the changes between Modules v5.1 and v5.2.
Optional requirements¶
The --optional
option has been added to the prereq
,
prereq-all
, depends-on
and always-load
modulefile
commands to indicate that specified requirement is optional. An automatic
load attempt is also performed for optional requirements. If requirement is
not found or cannot be loaded, the dependency is yet considered satisfied as
it is optional.
$ module show foo ------------------------------------------------------------------- /path/to/modulefiles/foo: prereq --optional bar ------------------------------------------------------------------- $ module load foo Loading foo Loading requirement: bar
If the optional requirement is unloaded or loaded afterward, the dependent
module is automatically reloaded thanks to the auto_handling
mechanism.
$ module unload bar Unloading bar Unloading dependent: foo Reloading dependent: foo $ module list Currently Loaded Modulefiles: 1) foo $ module load bar Loading bar Unloading dependent: foo Reloading dependent: foo
Modules loaded by other modules with the module try-load
command are now considered optional requirements. Dependent module can be
loaded without the try-load modules, but now it gets automatically reloaded
if try-load module is loaded afterward, to take it into account.
Linting modulefiles¶
Static analysis of modulefile, modulerc and global/user rc is now possible
with lint
sub-command. It relies on an external program defined with
tcl_linter
configuration option. Modules or files specified on the
command-line are resolved then passed to the Tcl linter program.
$ cat /path/to/modulefiles/foo/1.0 #%Module if {"str" eq} { else { } $ module lint foo/1.0 Linting /path/to/modulefiles/foo/1.0 ERROR line 2: Could not complete statement. One close brace would complete the first line One close brace would complete at end of line 4. One close brace would complete the script body at line 5. Assuming completeness for further processing. ERROR line 2: Bad expression: missing operand at _@_ in expression ""str" eq_@_" WARNING line 3: Unknown command "else" NOTICE line 4: Close brace not aligned with line 3 (1 0)
Nagelfar is the Tcl linter recommended for Modules and set by default. This
default can be changed at installation time with --with-tcl-linter
and --with-tcl-linter-opts
options. It can also be configured later
on through tcl_linter
config option.
Specific syntax databases and plugins for Nagelfar are added by Modules to
precisely lint modulefile commands syntax in addition to regular Tcl syntax.
The installation of these specific files is controlled with
--enable-nagelfar-addons
option (enabled by default). Their
location is controlled by the --nagelfardatadir
option.
$ module lint bar@:1 /path/to/modulefiles/.modulerc Linting /path/to/modulefiles/.modulerc ERROR line 35: Wrong number of arguments (3) to "module-alias" ERROR line 41: Wrong number of arguments (3) to "module-virtual" Linting /path/to/modulefiles/bar/1.2 WARNING line 19: Unknown command "unk" $ module lint ~/.modulerc Linting /home/user/.modulerc WARNING line 2: Command "setenv" should not be be used in global rc file
lint
sub-command outputs messages returned by the Tcl linter
program. Nagelfar produces NOTICE, WARNING and ERROR messages. If linter does
not report a thing, lint
sub-command will be silent, unless if the
--verbose
/-v
is set.
$ module lint /path/to/modulefiles/bar/.version bar/1.4 $ module lint -v /path/to/modulefiles/bar/.version bar/1.4 Linting /path/to/modulefiles/bar/.version Linting /path/to/modulefiles/bar/1.4
When no file is specified to lint
sub-command, all the global/user
rc files and all the modulefiles and modulercs from enabled modulepaths are
analyzed. If the --all
/-a
option is set, all hidden
modulefiles are also linted.
$ module lint Linting /home/user/.modulerc WARNING line 2: Command "setenv" should not be be used in global rc file Linting /path/to/modulefiles/.modulerc ERROR line 35: Wrong number of arguments (3) to "module-alias" ERROR line 41: Wrong number of arguments (3) to "module-virtual" Linting /path/to/modulefiles/bar/1.2 WARNING line 19: Unknown command "unk" ...
To use Nagelfar as Tcl linter for Modules, this open source tool has to be
installed on your system. When installing from tarball distribution, make sure
nagelfar.tcl command is found through a PATH
lookup or
that tcl_linter
option is set to its full path location.
Nagelfar is also made available as a RPM package in EPEL and Fedora
repositories.
mod-to-sh sub-command¶
New sub-command is added to translate modulefile into shell code:
mod-to-sh
. It evaluates modulefiles passed as argument and produces
code for specified shell.
$ cat /path/to/modulefiles/foo #%Module setenv FOO value set-function foo {echo foo} $ module mod-to-sh bash foo FOO=value; export FOO; foo () { echo foo; }; export -f foo;
Designated modulefiles are evaluated as if they were loading. But instead of producing shell code that is evaluated in current shell session, module command outputs this shell code.
$ cat /path/to/modulefiles/bar #%Module setenv BAR othervalue set-alias bar {echo bar} $ module mod-to-sh fish foo bar set -xg FOO value; set -xg BAR othervalue; alias bar echobar; function foo; echo foo; end; $ module list No Modulefiles Currently Loaded.
All shells supported by modulecmd.tcl
script are supported by
mod-to-sh
.
$ module mod-to-sh python foo bar
import os
os.environ['FOO'] = 'value'
os.environ['BAR'] = 'othervalue'
Initial environment¶
When Modules initializes, it evaluates the initrc
and
modulespath
configuration files to enable default modulepaths and load
default modules. Initial environment corresponds to the environment state
after this initialization.
Initial environment is now saved in an environment variable
(__MODULES_LMINIT
) in current shell session to remember what are the
initial modulepaths and initial modules with their tags and variants if any.
reset
sub-command is introduced, in a similar fashion than on
Lmod, to restore the initial environment. Here, reset
relies on
the collection mechanism based and the content of
__MODULES_LMINIT
. Currently enabled modulepaths and loaded modules
are respectively unused and unloaded to use the modulepaths and load the
modules with tags and variants as described by initial environment.
$ module list Currently Loaded Modulefiles: 1) foo/1.0 2) bar/1.0 $ module switch bar/1.0 qux/1.0 $ module reset Unloading qux/1.0 Loading bar/1.0
restore
sub-command has been adapted to reinitialize the environment
to its initial state when no collection name is provided and no default
collection exists or if __init__
virtual collection name is provided.
It is possible to view the content of the initial environment with
saveshow
sub-command. It is displayed when no argument is provided
and no collection exists or if __init__
name is provided.
$ module saveshow __init__ ------------------------------------------------------------------- initial environment: module use --append /path/to/modulefiles module load foo/1.0 module load bar/1.0 -------------------------------------------------------------------
Users have the ability to define what is their initial environment state and
thus adapt the behavior of reset
sub-command with
reset_target_state
configuration option. Default value is
__init__
and it corresponds to the behavior described above. When set to
__purge__
, a purge
command is performed when resetting. Any
other value corresponds to the name of a collection to restore.
$ module config reset_target_state __purge__ $ module reset Unloading bar/1.0 Unloading foo/1.0
Stashing environment¶
The ability to stash current environment is added with the introduction of the
stash
sub-command. When called current environment is saved in a
stash collection then initial environment is restored.
$ module list Currently Loaded Modulefiles: 1) bar/2.0 2) foo/2.0 $ module stash Unloading foo/2.0 Unloading bar/2.0 $ module list No Modulefiles Currently Loaded.
Sub-commands are added to specifically handle stash collections. Their names
are prefixed with stash, like stashlist
to list existing stash
collections or stashshow
to display their content.
$ module stashlist Stash collection list: 0) stash-1665377597432 1) stash-1664946764252 $ module stashshow ------------------------------------------------------------------- /home/user/.module/stash-1665377597432: module use --append /path/to/modulefiles module load bar module load foo -------------------------------------------------------------------
Stash collections can be designated on sub-commands by their collection name
or stash index. Most recent stash collection has index 0
, the one after is
designated with index 1
, and so on. When no stash collection is specified,
most recent one is assumed.
$ module stashshow 1 ------------------------------------------------------------------- /home/user/.module/stash-1664946764252: module use --append /path/to/modulefiles module load foobar -------------------------------------------------------------------
Stash collections are restored with the stashpop
sub-command. It
changes the user environment to match the stash definition, then it deletes
the stash collection file.
$ module stashpop Loading bar/2.0 Loading foo/2.0 $ module stashlist Stash collection list: 0) stash-1664946764252
Stash collections can be deleted one by one with stashrm
sub-command
or all together with stashclear
.
$ module stashrm $ module stashlist No stash collection.
Siteconfig hook variables¶
Several Tcl variables are introduced for Site-specific configuration
script to define specific commands and variables in the evaluation context of
modulefiles and modulercs. These commands and variables setup in
siteconfig.tcl
can be used in modulefile or modulerc. Sites can easily
extend modulefile and modulerc syntax with specific elements.
modulefile_extra_cmds
variable defines a list of commands to expose
in the modulefile evaluation context and the associated procedure to run when
this command is called. This variable has to be defined in
siteconfig.tcl
located for instance at /etc/environment-modules/siteconfig.tcl
.
In the following example modulefile_extra_cmds
is used to define
the sys
command and bound it to the sys
procedure that is also defined
in siteconfig.tcl
.
proc sys {mode} {
switch -- $mode {
name { return myhost-$::tcl_platform(machine) }
default { error "Unknown mode '$mode'" }
}
}
set modulefile_extra_cmds {sys sys}
Once siteconfig.tcl
is setup, the sys
command can be called by
modulefiles. In the following example it is used to determine the application
path.
$ cat /path/to/modulefiles/foo/1.2 #%Module append-path PATH /path/to/apps/foo-1.2/[sys name]/bin $ module show foo/1.2 ------------------------------------------------------------------- /path/to/modulefiles/foo/1.2: append-path PATH /path/to/apps/foo-1.2/myhost-x86_64/bin -------------------------------------------------------------------
modulerc_extra_cmds
follows the same approach than
modulefile_extra_cmds
and makes specific commands available during
modulerc evaluation.
modulefile_extra_vars
variable defines a list of variables to
expose in the modulefile evaluation context and their associated value. This
variable has to be defined in siteconfig.tcl
.
In the following example modulefile_extra_vars
is used to define
the APP_ROOT
variable with /path/to/apps
as value.
set modulefile_extra_vars {APP_ROOT /path/to/apps}
Once siteconfig.tcl
is setup, the APP_ROOT
variable can be used in
modulefiles.
$ cat /path/to/modulefiles/bar/2.1 #%Module append-path PATH $APP_ROOT/bar-2.1/[sys name]/bin $ module show bar/2.1 ------------------------------------------------------------------- /path/to/modulefiles/bar/2.1: append-path PATH /path/to/apps/bar-2.1/myhost-x86_64/bin -------------------------------------------------------------------
modulerc_extra_vars
follows the same approach than
modulefile_extra_vars
and makes specific variables available during
modulerc evaluation.
v5.1¶
This new version is backward-compatible with previous version 5 release. It fixes bugs but also introduces new functionalities that are described in this section. See the 5.1 release notes for a complete list of the changes between Modules v5.0 and v5.1.
Control output redirection¶
Since version 4.0, the module function is initialized differently on sh, bash, ksh, zsh and fish shells when their session is found interactive. In such situation module redirects its output from stderr to stdout. Once initialized the redirection behavior is inherited in sub-sessions.
The redirect_output
configuration option is introduced in version
5.1, to supersede the default behavior set at initialization time.
$ module load unknown >/dev/null $ module config redirect_output 0 $ module load unknown >/dev/null ERROR: Unable to locate a modulefile for 'unknown'
The --redirect
and --no-redirect
command-line switches are
also added to change the output redirection behavior for a single command:
$ module load unknown --redirect >/dev/null $ module load unknown --no-redirect >/dev/null ERROR: Unable to locate a modulefile for 'unknown'
Change modulefile command behavior¶
Depending on the evaluation mode of the modulefile (e.g. load, unload,
display, etc) commands have different behavior. Most common example is the
setenv
command that sets an environment variable when modulefile is
loaded and unsets it when it is unloaded. A different behavior may be wished
sometimes for commands. This is why options are introduced for some modulefile
commands to control what happens on particular evaluation mode.
The --return-value
option is added to the getenv
and
getvariant
modulefile commands to ensure that the value of the
designated environment variable or variant is returned even if modulefile is
evaluated in display mode:
$ cat /path/to/modulefiles/foo/1.0 #%Module5.1 if {[getenv --return-value VAR] eq {}} { setenv VAR value } $ module display foo/1.0 ------------------------------------------------------------------- /path/to/modulefiles/foo/1.0: setenv VAR value -------------------------------------------------------------------
--remove-on-unload
, --append-on-unload
, --prepend-on-unload
and
--noop-on-unload
options are added to the remove-path
and
module unuse
modulefile commands to control the behavior
applied when modulefile is unloaded. With these options it is possible for
instance to restore the paths unset at load time or to set other paths:
$ module display bar/1.0 ------------------------------------------------------------------- /path/to/modulefiles/bar/1.0: module unuse --prepend-on-unload /path/to/dir1 module use /path/to/dir2 ------------------------------------------------------------------- $ module use Search path for module files (in search order): /path/to/dir1 /path/to/modulefiles $ module bar/1.0 $ module use Search path for module files (in search order): /path/to/dir2 /path/to/modulefiles $ module unload bar/1.0 $ module use Search path for module files (in search order): /path/to/dir1 /path/to/modulefiles
Following the same trend, the --unset-on-unload
and --noop-on-unload
options are added to the unsetenv
modulefile command to be able to
choose between unsetting variable, setting a value or performing no operation
when modulefile is unloaded.
Reducing number of I/O operations¶
A new configuration option named mcookie_check
is introduced to
control the verification made to files to determine if they are modulefiles.
By default this configuration option is set to always
and when searching
for modulefiles within enabled modulepaths each file below these directories
is opened to check if it starts with the Modules magic cookie (i.e.,
#%Module
file signature).
These historical checks lead to a large number of I/O operations on large module setup like in the below example where a total of 1098 modulefiles are available:
$ module -o "" avail -t | wc -l 1098 $ module config mcookie_check always $ strace -f -e open,openat,read,close -c $MODULES_CMD bash avail ... % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 44.29 0.044603 25 1734 166 open 34.15 0.034389 16 2056 close 11.87 0.011949 24 483 5 openat 9.69 0.009761 4 2146 read ------ ----------- ----------- --------- --------- ---------------- 100.00 0.100702 6419 171 total
For each file, 3 I/O operations (open
, read
and close
) are
achieved to determine if it is a modulefile and include it in search results.
When modulefiles are located in a shared filesystem concurrently accessed by
hundreds of users, a module avail
command may take some time to finish.
When setting the mcookie_check
configuration option to the eval
value, files are not checked anymore when searching for modulefiles, only when
evaluating them. All files under modulepaths are considered modulefiles, so
the content of these directories must be carefully checked to use this
mcookie_check
mode which lead to a significant reduction of I/O
operations:
$ module config mcookie_check eval $ strace -f -e open,openat,read,close -c $MODULES_CMD bash avail ... % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 30.56 0.013717 14 944 close 28.76 0.012911 21 612 156 open 26.41 0.011857 24 483 5 openat 14.26 0.006403 6 1034 read ------ ----------- ----------- --------- --------- ---------------- 100.00 0.044888 3073 161 total
A substantial reduction of execution time may be noticed depending on the
storage setup used to host the modulepath directories. A special care should
be given to the content of these directories to ensure they only contain
modulefiles (see MODULES_MCOOKIE_CHECK
).
See the Reduce I/O load cookbook recipe to learn additional features of Modules that could be leveraged to lower the number of I/O operations.
Shell command completion¶
New modulefile commands complete
and uncomplete
are added to
get the ability to respectively define and unset command completion. bash,
tcsh and fish shells are supported.
> module display foo ------------------------------------------------------------------- /path/to/modulefiles/foo/1.0: append-path PATH /path/to/foo-1.0/bin complete fish foo {-s V -l version --description 'Command version'} complete fish foo {-s h -l help --description 'Command help'} ------------------------------------------------------------------- > module load foo > foo -<TAB> -h --help (Command help) -V --version (Command version)
sh-to-mod
sub-command and source-sh
modulefile command have
also been updated to track shell completion changes.
$ module sh-to-mod bash /path/to/foo-1.0/share/setup-env.sh #%Module complete bash foo {-o default -F _foo} append-path PATH /path/to/foo-1.0/bin set-function _foo { ...bash completion code...}
Lmod Tcl modulefile support¶
With this new version, Modules now supports Tcl modulefiles written for Lmod, the alternative module implementation developed in Lua. Such modulefiles can be safely evaluated by Modules without raising error.
Support has been added for the following modulefile commands introduced by
Lmod: depends-on
, prereq-any
, always-load
,
module load-any
, pushenv
, require-fullname
and family
.
The Compatibility with Lmod Tcl modulefile section in the modulefile man page describes the differences existing between the two implementations.
Note that when processing a family
command, the
LMOD_FAMILY_<NAME>
environment variable is defined by Modules to
be compatible with existing modulefiles or scripts relying on such variable.
More tagging capabilities¶
The new --tag
option helps to define extra tags onto a loading
module. These tags comes in addition to those inherited from the module state
or those associated with the module-tag
modulefile command.
The --tag
option is available on load
, load-any
,
switch
and try-load
sub-commands and on
always-load
, depends-on
, module
, prereq
,
prereq-all
and prereq-any
modulefile commands.
Informational messages of module evaluation have been updated to mention in
module denomination the tags applying to it, as it is done in list
sub-command output:
$ module load -v --tag=sticky:bar foo/1.0 Loading foo/1.0 <bar>
In case the designated module is already loaded, the additional tags are added to the list of tags already applied to this module.
$ module list Currently Loaded Modulefiles: 1) foo/1.0 $ module load -v --tag=sticky:bar foo/1.0 Tagging foo/1.0 <bar>
The keep-loaded
tag is introduced in this version. It avoids an
auto-loaded module to get automatically unloaded when its dependent modules
are unloaded. This new tag can be set with the module-tag
modulefile
command or when module is loaded with the always-load
modulefile
command. Default tag_abbrev
configuration option has been updated
to add the kL
abbreviation for keep-loaded
tag. Default dark and light
color palettes have been updated too.
$ module show bar/1.0 ------------------------------------------------------------------- /path/to/modulefiles/bar/1.0: always-load foo/1.0 ------------------------------------------------------------------- $ module load bar/1.0 Loading bar/1.0 Loading requirement: foo/1.0 $ module unload bar/1.0 $ module list Currently Loaded Modulefiles: 1) foo/1.0 Key: auto-loaded keep-loaded
When saving a collection, the tags defined with --tag
option are
recorded to set them again when collection is restored. Tags resulting from
module load state, like auto-loaded
and keep-loaded
, are also
recorded.
$ module load --tag=sticky bar/1.0 Loading bar/1.0 Loading requirement: foo/1.0 $ module save $ module saveshow ------------------------------------------------------------------- /home/user/.module/default: module use --append /path/to/modulefiles module load --tag=auto-loaded:keep-loaded foo module load --tag=sticky bar -------------------------------------------------------------------
The collection_pin_tag
configuration option is added to record in
collection all tags set on loaded modules. This configuration option is
disabled by default.
Note
Collection saved now starts with a #%Module5.1
file signature if
--tag
option is recorded in it. Such collection could only be
handled by Modules version 5.1 and above.
v5.0¶
With this new major version the module experience has been updated to benefit by default from all the advanced behaviors and features developed over the Modules 4 versions. Modules 5.0 also introduces some breaking changes to improve the consistency of the whole solution. See the 5.0 release notes for a complete list of the changes between Modules v4.8 and v5.0. The changes document gives an in-depth view of the modified behaviors.
Upgraded default configuration¶
Release after release, new advanced features were added on Modules 4. They were set off by default to avoid breaking change during the version 4 cycle. With the move to a new major release, these features are set on to improve by default usages for everybody. These features enabled by default are:
Automated module handling mode which provides the automatic dependency resolution when loading and unloading modules
$ module load foo/1.0 Loading foo/1.0 Loading requirement: bar/1.0
Extended default that enables to select a module when the first number in its version is specified
$ module load -v foo/1 Loading foo/1.2.3
Advanced module version specifiers, an improved syntax to designate module version in range or list and module variant
$ module load foo@:2.2 %gcc11 Loading foo/2.1{%gcc11} Loading requirement: bar/1.2{-debug:%gcc11}
Colored output to graphically enhance parts of the produced output to improve readability
$ ml av ------------------ /path/to/modulefiles ------------------ bar/1.0 bar/2.0 foo/1.0 foo/2.0 foo/2.2 Key: modulepath module-alias sticky default-version forbidden
Specify modules in a case insensitive manner search that matches modules using a different character case than the one expressed in search query
$ ml av liba ------------------ /path/to/modulefiles ------------------ LibA/1.0 LibA/2.0
Some other features that were enabled by default during the Modules 4 cycle
have been turned off as they may not be useful for basic usages. Among other
things setting off the following features makes the definition of the
module function simpler. Even if off by default, these features
can now be enabled once Modules is installed through the initrc
configuration file.
- Set shell startup files to ensure the module command is defined
once shell has been initialized. See the
set_shell_startup
configuration option to activate. - Quarantine mechanism that protects the module command
run-time environment from side effect coming from the current environment
definition. See the
quarantine_support
configuration option to activate. - Silent shell debug which disables the debugging property set on current
shell session for the duration of the module command. See the
silent_shell_debug
configuration option to activate.
Removing compatibility version¶
The ability to co-install version 3.2 of Modules along newer version is
discontinued. The installation option --enable-compat-version
,
switchml shell function and MODULES_USE_COMPAT_VERSION
environment variables are thus removed.
The interesting features of Modules 3.2 that were missing in the
initial Modules 4 release in 2017 have been reintroduced progressively (like
clear
sub-command or --icase
search). With Modules 5.0,
the refresh
sub-command is even changed to the behavior it had on
Modules 3.2. So it is a good time for the big jump.
If you are still using Modules 3.2, please refer to the Changes between versions document that describes the differences of this version compared to the newer releases.
Improving Modules initialization¶
Modules initialization files are now installed by default in the etc
directory designated by the --etcdir
installation option. The
initialization configuration file is named initrc
in this directory,
and the modulepath-specific configuration file is named modulespath
.
When both files exist, now they are both evaluated instead of just the
modulespath
file.
Modules magic cookie (i.e., #%Module
file signature) is now required at
the start of initrc
. An error is produced if the magic cookie is
missing or if the optional version number placed after the cookie string is
higher than the version of the modulecmd.tcl
script in use.
Note that initrc
configuration file can host more than
module use
and module load
commands.
module configuration can also be achieved with this file through
the use of module config
commands.
Modules initialization has been enhanced for situations where a module environment is found already defined. In this case the loaded modules are automatically refreshed which is useful to re-apply the non-persistent environment configuration (i.e., shell alias and function that are not exported to the sub-shell). For instance when starting a sub-shell session it ensures that the loaded environment is fully inherited from parent shell:
$ ml show foo/1.0 ------------------------------------------------------------------- /path/to/modulefiles/foo/1.0: set-alias foo {echo foo} ------------------------------------------------------------------- $ ml foo/1.0 $ alias foo alias foo='echo foo' $ bash $ ml Currently Loaded Modulefiles: 1) foo/1.0 $ alias foo alias foo='echo foo'
Simplifying path-like variable reference counting¶
The reference counting mechanism used for path-like environment variable enables to determine if a path entry has been added several times (by several loaded modules for instance) to know whether or not this path entry should be unset when unloading a module. Entry is not removed if multiple loaded modules rely on it.
The mechanism is not applied anymore to the Modules-specific path variables
(like LOADEDMODULES
) as an element entry in these variables cannot
be added multiple times without duplication. For instance, a given module name
and version cannot be added twice in LOADEDMODULES
as this module is
only loaded once. With this change a thinner environment is produced by
module. An exception is made for MODULEPATH
environment
variable where the mechanism still applies.
$ $MODULES_CMD bash load foo/2.0
_LMFILES_=/path/to/modulefiles/foo/2.0; export _LMFILES_;
LOADEDMODULES=foo/2.0; export LOADEDMODULES;
__MODULES_LMTAG=foo/2.0&mytag; export __MODULES_LMTAG;
test 0;
Reference counting mechanism has also been simplified for entries in path-like
variable that are only referred once. For such entries no entry is set in the
reference counting variable (which are now called
__MODULES_SHARE_<VAR>
). A reference count entry is set only if the
entry in the path-like variable is referred more than one time.
$ ml foo/3.0 $ echo $PATHVAR /path/to/dir1 $ echo $__MODULES_SHARE_PATHVAR $ ml bar/1.0 $ echo $PATHVAR /path/to/dir1 $ echo $__MODULES_SHARE_PATHVAR /path/to/dir1:2 $ ml -foo/3.0 $ echo $PATHVAR /path/to/dir1 $ echo $__MODULES_SHARE_PATHVAR $
When the use
and unuse
module sub-commands are not called
during a modulefile evaluation, the reference counter associated with each
entry in MODULEPATH
environment variable is ignored. In such
context, a module use
will not increase the reference counter
of a path entry already defined and a module unuse
will
remove specified path whatever its reference counter value. Same change applies
for append-path
, prepend-path
and remove-path
module sub-commands when called from the command-line.
$ echo $MODULEPATH /path/to/modulefiles $ echo $__MODULES_SHARE_MODULEPATH /path/to/modulefiles:2 $ ml use /path/to/modulefiles $ echo $__MODULES_SHARE_MODULEPATH /path/to/modulefiles:2 $ ml unuse /path/to/modulefiles $ echo $MODULEPATH $ echo $__MODULES_SHARE_MODULEPATH $
v4.8¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.8 release notes for a complete list of the changes between Modules v4.7 and v4.8.
Editing modulefiles¶
edit
sub-command is introduced to give the ability to open
modulefiles in a text editor. Modulefiles can be specified like with any other
sub-command: using regular, symbolic or aliased names or using advanced
version specifiers.
$ ml edit foo
edit
sub-command resolves the path toward the designated modulefile
then call configured text editor to open this modulefile with it. Below, the
modulefile is opened with the vi
command:
#%Module
module-whatis [module-info name]
setenv PATH /path/to/foo-1.0/bin
~
~
~
"/path/to/modulefiles/foo/1.0" 3L, 42B 1,1 All
The editor
configuration option controls the editor command to use.
This option can be configured at installation time with the
--with-editor
installation option. If not set, editor
configuration option is set by default to vi
.
editor
configuration option can be changed with the
config
sub-command. Which sets the MODULES_EDITOR
environment variable.
The VISUAL
or the EDITOR
environment variables override
the default value of editor
configuration option but are overridden
by the MODULES_EDITOR
environment variable.
Using version range in version list¶
The Advanced module version specifiers mechanism has been improved to allow the use of version range (@:version, @vers1:vers2 or @version:) within version list (@version1,version2,...).
It is now possible to write for instance mod@:1.2,1.4:1.6,1.8:
to
designate all versions of module mod, except versions 1.3 and 1.7.
This improvement is available where the advanced version specifier syntax is supported. Thus it can be either used from the command-line or when writing modulefiles, for instance to hide or tag modules or to declare requirements.
Try module load with no complain if not found¶
Add the try-load
sub-command that tries to load the modulefile
passed as argument, like the load
sub-command, but does not raise an
error if this modulefile cannot be found.
$ module load unknown ERROR: Unable to locate a modulefile for 'unknown' $ echo $? 1 $ module try-load unknown $ echo $? 0 $ module list No Modulefiles Currently Loaded.
This sub-command first introduced by the Lmod project is added to Modules
to improve the compatibility between the two module
implementations.
try-load
is also available within modulefile context to continue the
evaluation of a modulefile in case no module is found in its attempt to load
another modulefile
$ module display foo/1.0 ------------------------------------------------------------------- /path/to/modulefiles/foo/1.0: module try-load unknown/1.0 ------------------------------------------------------------------- $ module load foo/1.0 $ module list Currently Loaded Modulefiles: 1) foo/1.0
Module variants¶
Module variants is a new mechanism that allows to pass arguments to evaluated modulefiles in order to achieve different environment variable or module requirement setup with a single modulefile.
Variant specification relies on the Advanced module version specifiers mechanism, which leverages the variant syntax of the Spack package manager:
$ module config advanced_version_spec 1 $ module load -v bar/1.2 toolchain=a -debug Loading bar/1.2{-debug:toolchain=a}
Variants are defined in modulefile with the variant
command, which
defines the variant type and its accepted values:
#%Module4.8
variant toolchain a b c
variant --boolean --default off debug
# select software build depending on variant values
set suffix -[getvariant toolchain]
if {$ModuleVariant(debug)} {
append suffix -dbg
}
prepend-path PATH /path/to/bar-1.2$suffix/bin
prepend-path LD_LIBRARY_PATH /path/to/bar-1.2$suffix/lib
The bar/1.2 modulefile defines a toolchain
variant, which accepts the
a
, b
and c
values, and a debug
Boolean variant, which is set
off
by default. Once these two variants are declared, their value
specified on module designation are instantiated in the ModuleVariant
array variable which could also be queried with the getvariant
modulefile command. Selected variant values enable to define a specific
installation build path for the bar/1.2 software.
If a variant is not specified when designating module and if this variant is not declared with a default value, an error is obtained:
$ module purge $ module load bar@1.2 Loading bar/1.2 ERROR: No value specified for variant 'toolchain' Allowed values are: a b c
Once module is loaded, selected variants are reported on the list
sub-command output:
$ module load bar@1.2 toolchain=b $ module list Currently Loaded Modulefiles: 1) bar/1.2{-debug:toolchain=b} Key: {-variant}={variant=off} {variant=value}
Note
The default value of the --with-list-output
installation
option has been updated to include variant information.
Variant specification could be used where the Advanced module version specifiers is supported. For instance a module may express a dependency over a specific module variant:
$ module show foo/2.1 toolchain=c ------------------------------------------------------------------- /path/to/modulefiles/foo/2.1: variant toolchain a b c prereq bar@1.2 toolchain={toolchain} prepend-path PATH /path/to/foo-2.1-{toolchain}/bin prepend-path LD_LIBRARY_PATH /path/to/foo-2.1-{toolchain}/lib -------------------------------------------------------------------
In this example, foo/2.1 module depends on bar/1.2 and the same toolchain variant should be selected for both modules in order to load two software builds that are compatible between each other.
$ module purge $ module config auto_handling 1 $ module load foo/2.1 toolchain=a Loading foo/2.1{toolchain=a} Loading requirement: bar/1.2{-debug:toolchain=a}
Variant shortcuts¶
The variant_shortcut
configuration option is added to define
shortcut characters for easily specifying variants. Instead of writing the
variant name to specify it in module designation (e.g., name=value), the
shortcut associated to this variant could be used (i.e., <shortcut>value):
$ module purge $ module config variant_shortcut toolchain=% $ module load foo/2.1 %a Loading foo/2.1{%a} Loading requirement: bar/1.2{-debug:%a}
Configured shortcuts are also used to report the loaded variant on
list
sub-command output (shortcuts are explained in key section):
$ module list Currently Loaded Modulefiles: 1) bar/1.2{-debug:%a} 2) foo/2.1{%a} Key: auto-loaded {-variant}={variant=off} {%value}={toolchain=value} {variant=value}
v4.7¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.7 release notes for a complete list of the changes between Modules v4.6 and v4.7.
Determining module implementation and version¶
New Modules variables are introduced to determine during the evaluation of a
modulefile or a modulerc what module implementation is currently in use. The
ModuleTool
variable corresponds to the name of the module
implementation and is set to Modules
for this project. The
ModuleToolVersion
variable corresponds to the version number of the
implementation (e.g. 4.7.0
).
With these new variables it is possible to precisely know what module command is in use then adapt modulefile code to handle a specific behavior or leverage a new feature.
The modulefile command versioncmp
is also introduced to provide a
simple way to compare two version strings and return if first version string
is less than, equal to or greater than second one.
if {[info exists ModuleTool] && $ModuleTool eq {Modules}
&& [versioncmp $ModuleToolVersion 4.7] >= 0} {
# here some code specific for Modules 4.7 and later versions
}
The ModuleTool
and ModuleToolVersion
variables and the
versioncmp
modulefile command are supported by the Lmod project
starting version 8.4.8
.
Symbolic version to designate module loaded version¶
When the Advanced module version specifiers is enabled, the loaded
symbolic version may be used to designate the currently loaded version of
specified module.
$ ml display foo@loaded ------------------------------------------------------------------- /path/to/modulefiles/foo/1.0: module-whatis foo/1.0 -------------------------------------------------------------------
If no version of specified module can be found loaded, an error is returned.
$ ml display foo@loaded ERROR: No loaded version found for 'foo' module
Module tags¶
Module tags are piece of information that can be associated to individual modulefiles. Tags could be purely informational or may lead to specific behaviors.
Module tags may be inherited from the module state set by a modulefile command
or consequence of a module action. Tags may also be associated to modules by
using the new module-tag
modulefile command.
Module tags are reported along the module they are associated to on
avail
and list
sub-command results. Tags could be reported
either:
- along the module name, all tags set within angle brackets, each tag
separated from the others with a colon character (e.g.,
foo/1.2 <tag1:tag2>
).
$ cat /path/to/modulefiles/foo/.modulerc #%Module module-tag mytag foo module-tag othertag foo/1.0 $ ml av --------------- /path/to/modulefiles --------------- foo/1.0 <mytag:othertag> foo/2.0 <mytag> $ ml foo/1.0 $ ml Currently Loaded Modulefiles: 1) foo/1.0 <mytag:othertag>
- graphically rendered over the module name for each tag associated to a
Select Graphic Rendition (SGR) code in the color palette (see
MODULES_COLORS
)
$ # set SGR code to report 'mytag' with blue background color $ ml config colors "hi=1:di=94:L=90;47:mytag=102" $ ml av --------------- /path/to/modulefiles --------------- foo/1.0 <othertag> foo/2.0 $ ml Currently Loaded Modulefiles: 1) foo/1.0 <othertag>
The tag_abbrev
configuration option is available to define
abbreviated strings for module tags and then use these abbreviations instead
of tag names when reporting tags on avail
and list
command
results.
$ # add abbreviation for 'othertag' tag $ ml config tag_abbrev loaded=L:othertag=oT $ ml av --------------- /path/to/modulefiles --------------- foo/1.0 <oT> foo/2.0 $ ml Currently Loaded Modulefiles: 1) foo/1.0 <oT>
When a SGR code is set for a tag in the color palette, this graphical
rendition is applied by default over the module name and the tag name or its
abbreviation is not displayed. If tag name or abbreviation is added to the
tag_color_name
configuration option, graphical rendering is applied
to the tag name or abbreviation rather than over the module name they are
attached to.
$ # add SGR code for 'oT' tag and set rendition over tag name $ ml config colors "hi=1:di=94:L=90;47:mytag=44:oT=41" $ ml config tag_color_name oT $ ml av --------------- /path/to/modulefiles --------------- foo/1.0 <oT> foo/2.0 $ ml Currently Loaded Modulefiles: 1) foo/1.0 <oT>
Tags inherited from module state, consequence of a module action or set by
using module-tag
but that have a special meaning currently are:
Tag | Description | Set with | Abbr. | Color |
---|---|---|---|---|
auto-loaded | Module has been loaded automatically | Inherited | aL |
mod/1.0
|
forbidden | Module cannot be loaded | Inherited from
module-forbid |
F |
mod/1.0
|
hidden | Module is not visible
on avail |
Inherited from
module-hide |
H |
mod/1.0
|
hidden-loaded | See Hiding loaded modules | Inherited from
module-hide |
H |
mod/1.0
|
loaded | Module is currently loaded | Inherited | L |
mod/1.0
|
nearly-forbidden | Module will soon not be able to load anymore | Inherited from
module-forbid |
nL |
mod/1.0
|
sticky | See Sticky modules | module-tag |
S |
mod/1.0
|
super-sticky | See Sticky modules | module-tag |
sS |
mod/1.0
|
Hiding loaded modules¶
The --hidden-loaded
option has been added to the module-hide
modulefile command and it indicates that designated hidden modules remain
hidden after being loaded.
$ cat /path/to/modulefiles/foo/1.0 #%Module module load bar $ cat /path/to/modulefiles/bar/.modulerc #%Module4.7 module-hide --soft --hidden-loaded bar
In this example, foo depends on bar which is set soft hidden and hidden once loaded. As a consequence, automated load of bar module will not be reported and bar/1.0 will not appear in loaded module list by default:
$ ml foo $ ml Currently Loaded Modulefiles: 1) foo/1.0
However bar/1.0 is loaded. Hidden loaded modules can be unveiled with the
--all
/-a
option set on the list
sub-command.
hidden-loaded
tag (abbreviated by default to H
when colored output is
disabled) applies to such modules.
$ ml -a Currently Loaded Modulefiles: 1) bar/1.0 2) foo/1.0
To also get the informational messages about hidden loaded module automated
load or unload, the new verbosity level verbose2
can be used (with
-vv
option for instance):
$ ml purge $ ml -vv foo Loading bar/1.0 Loading foo/1.0 Loading requirement: bar/1.0
Sticky modules¶
Module stickiness is introduced, in a similar fashion than on the Lmod project, to allow to glue modules to the loaded environment. A sticky module cannot be unloaded, unless if the unload action is forced or if the module reloads after being unloaded.
A modulefile is declared sticky by applying it the sticky
tag with the
module-tag
modulefile command.
$ cat /path/to/modulefiles/foo/.modulerc #%Module4.7 module-tag sticky foo/1.0 $ ml Currently Loaded Modulefiles: 1) foo/1.0 $ ml -foo Unloading foo/1.0 ERROR: Unload of sticky module 'foo/1.0' skipped $ ml Currently Loaded Modulefiles: 1) foo/1.0 $ ml --force -foo Unloading foo/1.0 WARNING: Unload of sticky module 'foo/1.0' forced $ ml No Modulefiles Currently Loaded.
Modulefile can also be defined super-sticky
by applying the corresponding
module tag. Super-sticky module cannot be unloaded even if the unload action
is forced. It can only be unloaded if the module reloads afterward.
$ cat /path/to/modulefiles/bar/.modulerc #%Module4.7 module-tag super-sticky bar/1.0 $ ml Currently Loaded Modulefiles: 1) bar/1.0 $ ml purge Unloading bar/1.0 ERROR: Unload of super-sticky module 'bar/1.0' skipped $ ml purge -f Unloading bar/1.0 ERROR: Unload of super-sticky module 'bar/1.0' skipped $ ml Currently Loaded Modulefiles: 1) bar/1.0
Modulefiles targeted by a sticky
or a super-sticky
tag are colored on
avail
and list
sub-command outputs to indicate such tag
applies. If colored output is disabled a tag abbreviation is reported along
module designation (respectively S
and sS
).
In case the stickiness applies to the generic module name (and does not target a specific module version or version-set), one version of the sticky or super-sticky module can be swapped by another version of this same module:
$ cat /path/to/modulefiles/baz/.modulerc #%Module4.7 module-tag sticky baz $ ml Currently Loaded Modulefiles: 1) baz/2.0 $ ml switch baz/1.0 $ ml Currently Loaded Modulefiles: 1) baz/1.0
Explaining avail/list output¶
A Key section is added at the end of the avail
and list
sub-commands output to give hints on the meaning of the graphical rendition
applied to elements or what the elements set in parentheses or chevrons along
module name stand for.
$ ml av ------------------ /path/to/modulefiles ------------------ foo/1.0 <oT> foo/2.0 foo/3.0 Key: loaded default-version sticky <oT>=othertag modulepath module-alias <module-tag>
Configuring avail/list output¶
New configuration options are introduced to control what content to output in
addition to modules names on the regular and terse output modes of the
avail
and list
sub-commands.
These new configuration options named avail_output
,
avail_terse_output
, list_output
and
list_terse_output
can be updated using the config
sub-command or set at installation time respectively with the
--with-avail-output
, --with-avail-terse-output
,
--with-list-output
and --with-list-terse-output
configure options.
The four options accept a colon separated list of elements as value. Accepted
elements for the avail
-related options are: modulepath
,
alias
, dirwsym
, sym
, tag
and key
. Accepted elements for
the list
-related options are: header
, idx
, sym
, tag
and key
.
In the following example, default output configuration for the avail
sub-command is checked then module tags and key section are removed to get a
simpler output:
$ ml config avail_output Modules Release 4.7.0 (2021-02-19) - Config. name ---------.- Value (set by if default overridden) --------------- avail_output modulepath:alias:dirwsym:sym:tag:key $ ml av ------------------ /path/to/modulefiles ------------------ bar/1.0 bar/2.0 foo/1.0 foo/2.0 foo/2.2 Key: modulepath module-alias sticky default-version forbidden $ ml config avail_output modulepath:alias:dirwsym:sym $ ml av ------------------ /path/to/modulefiles ------------------ bar/1.0 bar/2.0 foo/1.0 foo/2.0 foo/2.2
The --output
/-o
switches are added to define a specific
output configuration for the duration of the associated command line. The
following example shows how to limit the content reported on a module
list
to the loaded index and the symbolic versions in addition to
the module names:
$ ml Currently Loaded Modulefiles: 1) bar/1.0 2) foo/2.0 Key: default-version sticky $ ml -o idx:sym 1) bar/1.0 2) foo/2.0
When the new configuration options command line switches are set to an empty value, the module names are the sole information reported:
$ ml -t -o ""
bar/1.0
foo/2.0
In case the modulepath
element is withdrawn from the avail
sub-command output configuration, the available modules from all enabled
modulepaths are reported as a single list:
$ ml av --------------- /path/to/other/modulefiles --------------- baz/1.0 baz/2.0 ------------------ /path/to/modulefiles ------------------ bar/1.0 bar/2.0 foo/1.0 foo/2.0 foo/2.2 Key: modulepath module-alias sticky default-version forbidden $ ml av --output=alias:tag bar/1.0 baz/1.0 foo/1.0 foo/2.2 bar/2.0 baz/2.0 foo/2.0
Note
The avail_report_dir_sym
and avail_report_mfile_sym
locked
configuration options have been removed. Their behaviors can now be
obtained by respectively adding the dirwsym
and sym
elements to the
avail_output
or avail_terse_output
configuration
options.
v4.6¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.6 release notes for a complete list of the changes between Modules v4.5 and v4.6.
sh-to-mod sub-command¶
The sh-to-mod
sub-command is added to output as a modulefile content
the environment changes done by the evaluation of a shell script passed as
argument. sh-to-mod
is especially useful for software providing a
shell script for their enablement in shell session: it can convert these
scripts into modulefiles.
Say for instance, a foo software has been installed and it provides a
foo-setup.sh
script to activate foo software in user environment:
$ cat /path/to/foo-1.2/foo-setup.sh
#!/bin/sh
export FOOENV="$1"
export PATH=/path/to/foo-1.2/bin:$PATH
alias foo='foobin -q -l'
Calling module sh-to-mod
on this shell script outputs the environment
changes it performs as a modulefile content:
$ module sh-to-mod sh /path/to/foo-1.2/foo-setup.sh arg1
#%Module
prepend-path PATH /path/to/foo-1.2/bin
set-alias foo {foobin -q -l}
setenv FOOENV arg1
Changes on environment variables, shell aliases, shell functions and current working directory are tracked. The following shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.
sh-to-mod
acts as a full replacement for the standalone
createmodule.sh and createmodule.py scripts. However
those two scripts are currently still provided for compatibility purpose.
source-sh modulefile command¶
The source-sh
modulefile command is introduced to source environment
changes done by the evaluation of a shell script passed as argument. With
newly introduced sh-to-mod
sub-command resulting environment changes
done by script are output as modulefile commands. source-sh
applies
those modulefile commands as if they were directly written in loading
modulefile.
source-sh
is useful for software providing a shell script for their
enablement. If you want to enable such software with module yet
using shell script provided by software for this task, just write a modulefile
using source-sh
command to call the shell script.
Keeping the same example used to describe sh-to-mod
sub-command:
foo software provides a foo-setup.sh
script for its activation. Create a
modulefile foo/1.2
that calls this script:
$ cat /path/to/modulefiles/foo/1.2
#%Module4.6
source-sh sh /path/to/foo-1.2/foo-setup.sh arg1
Displaying this modulefile indicates the environment changes done by script:
$ module display foo/1.2 ------------------------------------------------------------------- /path/to/modulefiles/foo/1.2: prepend-path PATH /path/to/foo-1.2/bin set-alias foo {foobin -q -l} setenv FOOENV arg1 -------------------------------------------------------------------
Loading the modulefile applies the environment changes seen above:
$ module load -v foo/1.2 Loading foo/1.2 $ echo $FOOENV arg1 $ alias foo alias foo='foobin -q -l'
Track of these changes is kept in user environment to be able to undo them when modulefile is unloaded:
$ module unload -v foo/1.2 Unloading foo/1.2 $ echo $FOOENV $ alias foo bash: alias: foo: not found
Changes on environment variables, shell aliases, shell functions and current working directory are tracked. The following shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.
Querying user's name and groups membership¶
Two new sub-commands are introduced for the module-info
modulefile
command: username
and usergroups
. They respectively fetch the name of
the user currently running modulecmd.tcl
or the name of all the groups
this user is member of.
These two new modulefile commands can help to adapt code to specific users or groups. Like for instance to instantiate a modulefile for each group the user is member of:
$ cat /path/to/modulefiles/foo/.modulerc #%Module4.6 foreach grp [module-info usergroups] { module-virtual foo/$grp .common } $ id -G -n grp1 grp2 grp3 $ module avail --------------- /path/to/modulefiles --------------- foo/grp1 foo/grp2 foo/grp3
username
and usergroups
sub-commands of module-info
modulefile command are only supported on Unix platform.
Hiding modules¶
The newly introduced module-hide
modulefile command enables to
dynamically hide modulefiles, module aliases or symbolic versions specified to
it:
$ cat /path/to/modulefiles/bar/.modulerc #%Module4.6 module-version bar/1.0 old # hide 'old' symbolic version module-hide bar/old # hide all version 2 and above module-hide bar@2: $ cat /path/to/modulefiles/.modulerc #%Module4.6 # hide all versions of foo module module-hide foo
module-hide
commands should be placed in module rc files and can
leverage the Advanced module version specifiers syntax as shown in the
above example.
Hidden modules are excluded from available module search or module selection unless query refers to hidden module by its exact name:
$ ml av --------------- /path/to/modulefiles --------------- bar/1.0 bar/2.0 $ module load -v foo ERROR: Unable to locate a modulefile for 'foo' $ module load -v foo/1.0 Loading foo/1.0 $ module avail bar/old --------------- /path/to/modulefiles --------------- bar/1.0(old)
module-hide
command accepts a --soft
option to apply a lighter of
hiding to modules:
$ cat /path/to/modulefiles/qux/.modulerc
#%Module4.6
# softly hide all qux modules
module-hide --soft qux
The soft hiding mode enables to hide modules from full availability listing yet keeping the ability to select such module for load without having to use module exact name:
$ ml av --------------- /path/to/modulefiles --------------- bar/1.0 bar/2.0 $ ml av qux --------------- /path/to/modulefiles --------------- qux/1.0 qux/2.0 $ module load -v qux Loading qux/2.0
Alternatively, a --hard
option can be set on module-hide
command
to ensure designated modules do not unveil even if referred by their exact
name:
$ cat /path/to/modulefiles/qux/.modulerc #%Module4.6 # softly hide all qux modules module-hide --soft qux # set highest version of qux hard hidden module-hide --hard qux/3.0 $ ml av qux/3.0 $ ml qux/3.0 ERROR: Unable to locate a modulefile for 'qux/3.0'
Some users or groups can be set unaffected by hiding mechanism with
the --not-user
or --not-group
options:
$ cat /path/to/modulefiles/quuz/.modulerc
#%Module4.6
# hiding does not apply to grp1 and grp2 groups
module-hide --not-group {grp1 grp2} quuz
$ id --groups --name grp1 grp7 $ ml av quuz --------------- /path/to/modulefiles --------------- quuz/1.0 quuz/2.0 $ ml -v quuz Loading quuz/2.0
Hiding mechanism can also be set effective only before or after a given date
time with the --before
and --after
options. Accepted date time format
is YYYY-MM-DD[THH:MM]
.
$ cat /path/to/modulefiles/fum/.modulerc
#%Module4.6
# hide only before a given date
module-hide --hard --before 2020-09-01T12:00 fum/1.0
# hide only after a given date
module-hide --hard --after 2020-09-01 fum/2.0
$ date Fri 04 Sep 2020 06:21:48 AM CEST $ ml av fum --------------- /path/to/modulefiles --------------- fum/1.0
Hidden modules can be included in available module searches if option
--all
/-a
is set on avail
, aliases
,
whatis
or search
sub-commands. Hard hidden modules are
unaffected by this option and stay hidden.
$ ml av -a --------------- /path/to/modulefiles --------------- bar/1.0(old) foo/1.0 fum/1.0 quuz/2.0 qux/2.0 bar/2.0 foo/2.0 quuz/1.0 qux/1.0
Forbidding use of modules¶
The module-forbid
modulefile command is added to dynamically forbid
the evaluation of modulefiles it specifies. When forbidden, a module cannot be
loaded and an access error is returned when an attempt is made to evaluate it.
$ cat /path/to/modulefiles/foo/.modulerc #%Module4.6 module-forbid foo@1: $ ml foo/1.0 ERROR: Access to module 'foo/1.0' is denied $ ml No Modulefiles Currently Loaded.
module-forbid
statements can be coupled with module-hide
statements to hide modules in addition to forbid their use.
module-forbid
supports the --not-user
, --not-group
,
--before
and --after
options to still allow some users or forbid
modules before or after a given date time.
An additional error message can be defined with the --message
option
to guide for instance users when they try to evaluate a forbidden module:
$ cat /path/to/modulefiles/bar/.modulerc #%Module4.6 module-forbid --message {Software bar/1.0 is decommissioned, please now use\ bar/2.0} --after 2020-09-01 bar/1.0 $ ml bar/1.0 ERROR: Access to module 'bar/1.0' is denied Software bar/1.0 is decommissioned, please now use bar/2.0
When an evaluated module will soon be forbidden, a message is returned to the
user to warn him/her of the near limit. An additional warning message can
also be defined here with the --nearly-message
option to guide users.
$ cat /path/to/modulefiles/qux/.modulerc #%Module4.6 module-forbid --nearly-message {Version 1.0 will soon expire, please now use\ version 2.0} --after 2020-09-15 qux/1.0 $ date Tue 08 Sep 2020 06:49:43 AM CEST $ ml qux/1.0 Loading qux/1.0 WARNING: Access to module will be denied starting '2020-09-15' Version 1.0 will soon expire, please now use version 2.0
The range of time the nearly forbidden warning appears can be controlled
with the nearly_forbidden_days
configuration option, whose value
equals to the number of days prior the module starts to be forbidden. This
configuration is set to 14
(days) by default and this value can be
controlled at configure
time with
--with-nearly-forbidden-days
option. When the
nearly_forbidden_days
configuration is set through the
config
sub-command, the MODULES_NEARLY_FORBIDDEN_DAYS
environment variable is set.
Tracing module execution¶
The trace
verbosity is introduced between the verbose
and debug
levels to report details on module searches, resolutions, selections and
evaluations. Trace mode can be enabled by setting the verbosity
config to the trace
value or by using the -T
/--trace
command-line switches.
To specifically render trace messages, the tr
key is added to the color
palette with a default value of 2
(decreased intensity).
$ ml -T foo Evaluate modulerc: '/path/to/modulefiles/.modulerc' Get modules: {foo} matching 'foo' in '/path/to/modulefiles' Resolve: 'foo' into 'bar' Get modules: {bar bar/1.0} matching 'bar' in '/path/to/modulefiles' Select module: 'bar/1.0' (/path/to/modulefiles/bar/1.0) matching 'bar/1.0' Loading bar/1.0 Evaluate modulefile: '/path/to/modulefiles/bar/1.0' as 'bar/1.0'
v4.5¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.5 release notes for a complete list of the changes between Modules v4.4 and v4.5.
ml command¶
The ml
command is added to Modules. ml
is a frontend to the module
command that reduces the number of characters to type to trigger module
actions.
With no argument provided ml
is equivalent to module list
, ml foo
corresponds to module load foo
and ml -foo
means module unload
foo
:
$ ml foo $ ml Currently Loaded Modulefiles: 1) foo/2 $ ml -foo $ ml No Modulefiles Currently Loaded.
Multiple modules to either load or unload can be combined on a single command. The unloads are first processed then the loads.
ml
accepts all command-line switches and sub-commands accepted by
module
command:
$ ml avail -t foo
foo/1
foo/2
This handy interface has been originally developed by the Lmod project. Having this command line interface also supported on Modules helps to provide a similar user experience whatever the module implementation used.
JSON format output¶
The -j
and --json
command line switches are added for the avail
,
list
, savelist
, whatis
and search
module sub-commands. When
set, the output result of these sub-commands is rendered in JSON format:
$ module avail --json bar | python -mjson.tool { "/path/to/modulefiles": { "bar/2.3": { "name": "bar/2.3", "pathname": "/path/to/modulefiles/bar/2.3", "symbols": [ "default" ], "type": "modulefile" }, "bar/3.4": { "name": "bar/3.4", "pathname": "/path/to/modulefiles/bar/3.4", "symbols": [], "type": "modulefile" } } } $ ml whatis -j foo/1.2.3 | python -mjson.tool { "/path/to/modulefiles": { "foo/1.2.3": { "name": "foo/1.2.3", "whatis": [ "The foo/1.2.3 modulefile" ] } } }
Improved Windows support¶
A new option to the ./configure
script named
--enable-windows-support
is introduced to install additional files
relative to the enablement of Modules on the Windows platform. When set, this
option installs module.cmd
, ml.cmd
and envml.cmd
scripts in
bindir
and initialization script cmd.cmd
in initdir
. With these
four files the Modules installation may be used from either a Unix or a
Windows platform.
module.cmd
, ml.cmd
and envml.cmd
scripts respectively provide the
module
, ml
and envml
commands for Windows cmd
terminal shell,
relying on modulecmd.tcl
script which was already able to produce shell
code for this Windows shell. Initialization script cmd.cmd
adds the
directory of module.cmd
, ml.cmd
and envml.cmd
to PATH
.
These Windows-specific files are relocatable: module.cmd
, ml.cmd
and
envml.cmd
scripts expect to find initialization script cmd.cmd
in the
init
directory next to them (to setup Modules-specific variables in
current environment) and cmd.cmd
expects modulecmd.tcl
to be found in
libexec
directory and the 3 commands in bin
directory next to it.
Starting from this 4.5
release a distribution zipball is published to
install Modules on Windows. This zip archive ships an install and an uninstall
scripts (INSTALL.bat
and UNINSTALL.bat
). The zipball can be built
locally from Modules sources by running make dist-win
.
The Installing Modules on Windows document describes how to install Modules on Windows from the distribution zipball.
Error stack trace¶
Error messages will now embed a stack trace for unknown errors to help localize the root cause of issues. This change applies to modulefile evaluation:
Loading foo/1.2 Module ERROR: add-path cannot handle path equals to separator string while executing "append-path PATH :" (file "/path/to/modulefiles/foo/1.2" line 24) Please contact <root@localhost>
A stack trace is also returned when an unknown error occurs in
modulecmd.tcl
script, which facilitates issue report and analysis:
$ module load bar ERROR: invalid command name "badcommand" while executing "badcommand" (procedure "module" line 14) invoked from within "module load bar" ("eval" body line 1) invoked from within "eval $execcmdlist" Please report this issue at https://github.com/cea-hpc/modules/issues
Automatic default and latest symbolic versions¶
When the implicit default mechanism and the Advanced module version
specifiers are both enabled, a default
and a latest
symbolic
versions are automatically defined for each module name.
This new feature gives the ability to select the highest version available for a module, without knowing beforehand this version name:
$ module load -v foo@latest Loading foo/1.10
The symbolic versions are automatically defined unless a symbolic version, an
alias or a regular module version already exists for these default
or
latest
version names.
v4.4¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.4 release notes for a complete list of the changes between Modules v4.3 and v4.4.
Warning
Modules configuration option handling has been reworked
internally to provide a unified way for all options to get initialized,
retrieved or set. Existing site-specific configuration script should be
reviewed to make use of the new getConf
, setConf
, unsetConf
and lappendConf
procedures to manipulate configuration options.
Specify modules in a case insensitive manner¶
The ability to match module name in a case insensitive manner has been added.
This feature can be enabled at different level with the following values set
to the icase
configuration option:
never
: a case sensitive match is applied in any casessearch
: a case insensitive match is applied to theavail
,whatis
andpaths
sub-commandsalways
: a case insensitive match is applied to search contexts and also to the other module sub-commands and modulefile Tcl commands for the module specification they receive as argument.
It can help for instance to load a module without knowing the case used to name its relative modulefile:
$ module config icase always $ module load -v mysoftware Loading MySoftware/1.0
Insensitive case match activation can be controlled at configure time with
the --with-icase
option, which could be passed any of the above activation
levels. This option could be superseded with the MODULES_ICASE
environment
variable, which could be set through the config sub-command with the
icase
option. Command-line switch --icase supersedes in turns any
other icase configurations. When this command-line switch is passed, icase
mode equals always
.
Extended default¶
The extended default mechanism has been introduced to help selecting a module
when only the first numbers in its version are specified. Starting portion of
the version, part separated from the rest of the version string by a .
character, could be used to refer to a more precise version number.
This mechanism is activated through the new configuration option
extended_default
. It enables to refer to a module named foo/1.2.3
as
foo/1.2
or foo/1
:
$ module config extended_default 1 $ module load -v foo/1 Loading foo/1.2.3
When multiple versions match partial version specified and only one module
should be selected, the default version (whether implicitly or explicitly
defined) among matches is returned. The following example shows that
foo/1.1.1
, the foo module default version, is selected when it matches
query. Elsewhere the highest version (also called the latest version or the
implicit default) among matching modules is returned:
$ module av foo --------------- /path/to/modulefiles --------------- foo/1.1.1(default) foo/1.2.1 foo/1.10 foo/1.1.10 foo/1.2.3 $ module load -v foo/1.1 Loading foo/1.1.1 $ module purge $ module load -v foo/1.2 Loading foo/1.2.3 $ module purge $ module load -v foo/1 Loading foo/1.1.1
In case implicit_default
option is disabled and no explicit default is
found among matches, an error is returned:
$ module config implicit_default 0 $ module load -v foo/1.2 ERROR: No default version defined for 'foo/1.2'
When it is enabled, extended default applies everywhere a module could be specified, which means it could be used with any module sub-command or any modulefile Tcl command receiving a module specification as argument. It may help for instance to declare dependencies between modules:
$ module show bar/3 ---------------------------------------------------------- /path/to/modulefiles/bar/3.4: prereq foo/1.2 ---------------------------------------------------------- $ module load --auto bar/3 Loading bar/3.4 Loading requirement: foo/1.2.3
Extended default activation can be controlled at configure time with the
--enable-extended-default
option. This option could be superseded with the
MODULES_EXTENDED_DEFAULT
environment variable, which could be set through
the config sub-command with the extended_default
option.
Advanced module version specifiers¶
The ability to specify finer constraints on module version has been added to
Modules. It enables to filter the module selection to a given version list or
range by specifying after the module name a version constraint prefixed by the
@
character.
This new feature leverages the version specifier syntax of the Spack package manager as this syntax covers all the needs for a fine-grained selection of module versions. It copes very well with command-line typing, by avoiding characters having a special meaning on shells. Moreover the users of Spack that also are users of Modules may already be familiar with this syntax.
The mechanism introduced here is called advanced module version specifier
and it can be activated through the new configuration option
advanced_version_spec
. Constraints can be expressed to refine the
selection of module version to:
- a single version with the
@version
syntax, for instancefoo@1.2.3
syntax will select modulefoo/1.2.3
- a list of versions with the
@version1,version2,...
syntax, for instancefoo@1.2.3,1.10
will match modulesfoo/1.2.3
andfoo/1.10
- a range of versions with the
@version1:
,@:version2
and@version1:version2
syntaxes, for instancefoo@1.2:
will select all versions of modulefoo
greater than or equal to1.2
,foo@:1.3
will select all versions less than or equal to1.3
andfoo@1.2:1.3
matches all versions between1.2
and1.3
including1.2
and1.3
versions
This new feature enables for instance to list available versions of module
foo
higher or equal to 1.2
:
$ module config advanced_version_spec 1 $ module av foo --------------- /path/to/modulefiles --------------- foo/1.1.1(default) foo/1.2.1 foo/1.10 foo/1.1.10 foo/1.2.3 $ module av foo@1.2: --------------- /path/to/modulefiles --------------- foo/1.2.1 foo/1.2.3 foo/1.10
Then choose to load for instance a version higher than or equal to 1.2
and
less than or equal to 1.3
. Default version is selected if it corresponds
to a version included in the range, elsewhere the highest version (also called
latest version or implicit default) is selected:
$ module load -v foo@1.2:1.3 Loading foo/1.2.3
In case implicit_default
option is disabled and no explicit default is
found among version specifier matches, an error is returned:
$ module config implicit_default 0 $ module load -v foo@1.2:1.3 ERROR: No default version defined for 'foo@1.2:1.3'
When advanced module version specifier is enabled, it applies everywhere a module could be specified, which means it could be used with any module sub-command or any modulefile Tcl command receiving a module specification as argument. It may help for instance to declare smoother dependencies between modules:
$ module show bar@:2 ---------------------------------------------------------- /path/to/modulefiles/bar/2.3: prereq foo@1.1.10,1.2.1 ---------------------------------------------------------- $ module load --auto bar@:2 Loading bar/2.3 Loading requirement: foo/1.2.1
Advanced specification of single version or list of versions may benefit from the activation of the Extended default mechanism (range of versions natively handles abbreviated versions):
$ module config extended_default 1 $ module load -v foo@1.2 Loading foo/1.2.3 $ module unload -v foo @1.2,1.5 Unloading foo/1.2.3
Advanced module version specifier activation can be controlled at configure
time with the --enable-advanced-version-spec
option. This option could be
superseded with the MODULES_ADVANCED_VERSION_SPEC
environment variable,
which could be set through the config sub-command with the
advanced_version_spec
option.
v4.3¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.3 release notes for a complete list of the changes between Modules v4.2 and v4.3.
Modulepath rc file¶
A .modulerc
file found at the root of an enabled modulepath directory is
now evaluated when modulepath is walked through to locate modulefiles. This
modulepath rc file gives for instance the ability to define module alias whose
name does not correspond to any module directory in this modulepath. Thus this
kind of module alias would not be found unless if it is defined at the
modulepath global scope.
Further I/O operations optimization¶
Additional work has been performed to save a significant number of filesystem I/O operations made to search and evaluate modulefiles.
When fully read, the content of a modulefile is now cached in memory to avoid new I/O operations in case this modulefile should be read one more time during the same module command evaluation.
Except for path
, paths
, list
, avail
and aliases
module
commands always fully read a modulefile whether its full content is needed or
just its header to verify its validity. This way modulefiles are only read
once on commands that first check modulefile validity then read again valid
files to get their full content.
Last but not least, Modules Tcl extension library is introduced to extend the
Tcl language in order to provide more optimized I/O commands to read a file or
a directory content than native Tcl commands do. This library is built and
enabled in modulecmd.tcl
script with --enable-libtclenvmodules
configure argument (it is enabled by default). As this library is written in
C, it must be compiled and --with-tcl
or --with-tclinclude
configure
arguments may be used to indicate where to find Tcl development files.
Modules Tcl extension library greatly reduces the number of filesystem I/O
operations by removing unneeded ioctl
, fcntl
and lstat
system
calls done (by Tcl open
command) to read each modulefile. Directory
content read is also improved by fetching hidden and regular files in one
pass. Moreover .modulerc
and .version
read access is tested only if
these files are found in the directory.
Colored output¶
The ability to graphically enhance some part of the produced output has been added to improve readability. Among others, error, warning and info message prefixes can be colored as well as modulepath, module alias and symbolic version.
Color mode can be set to never
, auto
or always
. When color mode is
set to auto
, output is colored only if the standard error output channel
is attached to a terminal.
Default color mode could be controlled at configure time with the
--enable-color
and the --disable-color
option, which respectively
correspond to the auto
and never
color mode. This default mode could
be superseded with the CLICOLOR
, CLICOLOR_FORCE
and MODULES_COLOR
environment variables and the --color
command-line switch.
Color to apply to each element can be controlled with the MODULES_COLORS
environment variable or the --with-dark-background-colors
and
--with-light-background-colors
configure options. These variable and
options take as value a colon-separated list in the same fashion LS_COLORS
does. In this list, output item that should be highlighted is designated by
a key which is associated to a Select Graphic Rendition (SGR) code.
The MODULES_TERM_BACKGROUND
environment variable and the
--with-terminal-background
configure option help Modules to determine if
the color set for dark background or the color set for light background should
be used to color output in case no specific color set is defined with the
MODULES_COLORS
variable.
Output items able to be colorized and their relative key are: highlighted
element (hi
), debug information (db
), tag separator (se
); Error
(er
), warning (wa
), module error (me
) and info (in
) message
prefixes; Modulepath (mp
), directory (di
), module alias (al
),
module symbolic version (sy
), module default
version (de
) and
modulefile command (cm
).
For instance the default color set for a terminal with dark background is defined to:
hi=1:db=2:se=2:er=91:wa=93:me=95:in=94:mp=1;94:di=94:al=96:sy=95:de=4:cm=92
When colored output is enabled and a specific graphical rendition is defined
for module default version, the default
symbol is omitted and instead
the defined graphical rendition is applied to the relative modulefile. When
colored output is enabled and a specific graphical rendition is defined for
module alias, the @
symbol is omitted.
CLICOLOR
and CLICOLOR_FORCE
environment variables are also honored to
define color mode. The never
mode is set if CLICOLOR
equals to 0
.
If CLICOLOR
is set to another value, it corresponds to the auto
mode.
The always
mode is set if CLICOLOR_FORCE
is set to a value different
than 0
. Color mode set with these two variables is superseded by mode set
with MODULES_COLOR
environment variable.
Configure modulecmd with config sub-command¶
The config sub-command has been added to module
to help getting or
setting the modulecmd.tcl options. With no additional command-line
argument, this sub-command reports the current value of all existing options
with a mention to indicate if this value has been overridden from a
command-line switch or from an environment variable.
See the description of this sub-command in the module man page for a complete reference on existing configuration options.
Most of the options can be altered by passing the option name and a value to the sub-command. Setting an option by this mean overrides its default value, set at installation time in modulecmd.tcl script, by defining the environment variable which supersedes this default.:
$ module config auto_handling 1 $ module config auto_handling Modules Release 4.3.0 (2019-07-26) - Config. name ---------.- Value (set by if default overridden) --------------- auto_handling 1 (env-var)
Setting options with module config
could be done in the Modules
initialization RC file to change default value of options when module
command is initialized.
When command-line switch --reset
and an option name is passed to the
config sub-command, it restores default value for configuration option by
unsetting related environment variable.
With command-line switch --dump-state
, the config sub-command reports,
in addition to currently set options, the current state of modulecmd.tcl
script and Modules-related environment variables. Providing the output of the
module config --dump-state
command when submitting an issue to the Modules
project will help to analyze the situation.
Control module command verbosity¶
The ability to control message verbosity has been added so module
command
can be configured whether it should display more or less information.
Available verbosity levels from the least to the most verbose are:
silent
: turn off error, warning and informational messages but does not affect module command output result.concise
: enable error and warning messages but disable informational messages.normal
: turn on informational messages, like a report of the additional module evaluations triggered by loading or unloading modules, aborted evaluation issues or a report of each module evaluation occurring during a restore or source sub-commands.verbose
: add additional informational messages, like a systematic report of the loading or unloading module evaluations.debug
: print debugging messages about module command execution.
Default verbosity level can be controlled at configure time with the
--with-verbosity
option, which could be passed any of the above level
names. This default verbosity level could be superseded with the
MODULES_VERBOSITY
environment variable, which could be set through the
config sub-command with the verbosity
option. Command-line switches
--silent, --verbose and --debug supersede in turns any other
verbosity configuration to respectively set module command silent, verbose or
in debug mode.
Other new sub-commands, command-line switches and environment variables¶
- The avail sub-command gets two new command-line switches: --indepth and --no-indepth. These options control whether search results should recursively include or not modulefiles from directories matching search query. Shell completion scripts have been updated to complete available modulefiles in the no in depth mode.
- The MODULES_AVAIL_INDEPTH environment variable defines if the avail sub-command should include or exclude by default the modulefiles from directories matching search query. Its value is superseded by the use of the --indepth and --no-indepth command-line switches.
- The clear sub-command, which was available on Modules version 3.2, has been reintroduced. This sub-command resets the Modules runtime information but does not apply further changes to the environment at all. This sub-command now leverages the --force command-line switch to skip its confirmation dialog.
- The MODULES_SITECONFIG environment variable defines an additional
siteconfig script which is loaded if it exists after the siteconfig script
configured at build time in
modulecmd.tcl
. This ability is enabled by default and could be disabled with configure option--with-locked-configs=extra_siteconfig
. - The MODULES_UNLOAD_MATCH_ORDER environment variable sets whether the
firstly or the lastly loaded module should be selected for unload when
multiple loaded modules match unload request. Configure option
--with-unload-match-order
defines this setting which can be superseded by the environment variable. By default, lastly loaded module is selected and it is recommended to keep this behavior when used modulefiles express dependencies between each other. - The MODULES_IMPLICIT_DEFAULT environment variable sets whether an
implicit default version should be defined for modules with no default
version explicitly defined. When enabled, which is the default behavior, a
module version is automatically selected (latest one) when the generic
name of the module is passed. When implicit default is disabled and no
default version is explicitly defined for a module, the name of this module
to evaluate should be fully qualified elsewhere an error is returned.
Configure option
--enable-implicit-default
defines this setting which can be superseded by the environment variable. This superseding mechanism can be disabled with configure option--with-locked-configs=implicit_default
. - The MODULES_SEARCH_MATCH environment variable defines the matching style
to perform when searching for available modules. With starts_with value,
modules whose name begins by search query string are returned. When search
match style is set to contains, modules returned are those whose fully
qualified name contains search query string. Configure option
--with-search-match
defines this setting which can be superseded by the environment variable, which in turns can be superseded by the --starts-with and --contains command-line switches of avail module sub-command. - The MODULES_SET_SHELL_STARTUP environment variable controls whether or
not shell startup file should be set to ensure
module
command is defined once shell has been initialized. When enabled, theENV
andBASH_ENV
environment variables are set, whenmodule
function is defined, to the Modules bourne shell initialization script. Configure options--enable-set-shell-startup
and--disable-set-shell-startup
define this setting which can be superseded by the environment variable. - When initializing the
module
command in a shell session, initialization configuration files stored in the defined configuration directory are taken into account if present instead of the configuration files stored in the initialization script directory. When they are stored in the configuration directory, these configuration files are namedinitrc
andmodulespath
instead of respectivelymodulerc
and.modulespath
. The location of the installation of those files can be controlled with configure option--with-initconf-in
, which acceptsetcdir
andinitdir
values. - The MODULES_WA_277 environment variable helps to define an alternative
module
alias on Tcsh shell when set to 1. It workarounds an issue on Tcsh history mechanism occurring with defaultmodule
command alias: erroneous history entries are recorded each time themodule
command is called. However the alternative definition of the module alias weakens shell evaluation of the code produced by modulefiles. Characters with special meaning for Tcsh shell (like { and }) may not be used anymore in shell alias definition elsewhere the evaluation of the code produced by modulefiles will return a syntax error.
v4.2¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.2 release notes for a complete list of the changes between Modules v4.1 and v4.2.
Modulefile conflict constraints consistency¶
With the conflict modulefile command, a given modulefile can list the other modulefiles it conflicts with. To load this modulefile, the modulefiles it conflicts with cannot be loaded.
This constraint was until now satisfied when loading the modulefile declaring
the conflict but it vanished as soon as this modulefile was loaded. In the
following example a
modulefile declares a conflict with b
:
$ module load b a WARNING: a cannot be loaded due to a conflict. HINT: Might try "module unload b" first. $ module list Currently Loaded Modulefiles: 1) b $ module purge $ module load a b $ module list Currently Loaded Modulefiles: 1) a 2) b
Consistency of the declared conflict is now ensured to satisfy this
constraint even after the load of the modulefile declaring it. This is
achieved by keeping track of the conflict constraints of the loaded
modulefiles in an environment variable called MODULES_LMCONFLICT
:
$ module load a b ERROR: WARNING: b cannot be loaded due to a conflict. HINT: Might try "module unload a" first. $ module list Currently Loaded Modulefiles: 1) a
An environment variable is used to keep track of this conflict information to
proceed the same way than used to keep track of the loaded modulefiles with
the LOADEDMODULES
environment variable.
In case a conflict constraint toward a modulefile is set by an already loaded modulefile, loading the conflicting modulefile will lead to a load evaluation attempt in order for this modulefile to get the chance to solve the constraint violation. If at the end of the load evaluation, the conflict has not been solved, modulefile load will be discarded.
Warning
On versions 4.2.0
and 4.2.1
, a conflict constraint set by
an already loaded modulefile forbade the load of the conflicting
modulefile. This has been changed starting version 4.2.2
to better cope
with behaviors of previous Modules version: an evaluation attempt of the
conflicting modulefile is made to give it the opportunity to solve this
conflict by using module unload modulefile command.
Modulefile prereq constraints consistency¶
With the prereq modulefile command, a given modulefile can list the other modulefiles it pre-requires. To load this modulefile, the modulefiles it pre-requires must be loaded prior its own load.
This constraint was until now satisfied when loading the modulefile declaring
the prereq but, as for the declared conflict, it vanished as soon as
this modulefile was loaded. In the following example c
modulefile declares
a prereq on a
:
$ module load c WARNING: c cannot be loaded due to missing prereq. HINT: the following module must be loaded first: a $ module list No Modulefiles Currently Loaded. $ module load a c $ module list Currently Loaded Modulefiles: 1) a 2) c $ module unload a $ module list Currently Loaded Modulefiles: 1) c
Consistency of the declared prereq is now ensured to satisfy this
constraint even after the load of the modulefile declaring it. This is
achieved, like for the conflict consistency, by keeping track of the prereq
constraints of the loaded modulefiles in an environment variable called
MODULES_LMPREREQ
:
$ module load a c $ module list Currently Loaded Modulefiles: 1) a 2) c $ module unload a ERROR: WARNING: a cannot be unloaded due to a prereq. HINT: Might try "module unload c" first. $ module list Currently Loaded Modulefiles: 1) a 2) c
By-passing module defined constraints¶
The ability to by-pass a conflict or a prereq constraint defined by
modulefiles is introduced with the --force
command line switch (-f
for
short notation) for the load, unload and switch sub-commands.
With this new command line switch, a given modulefile is loaded even if it
conflicts with other loaded modulefiles or even if the modulefiles it
pre-requires are not loaded. Some example reusing the same modulefiles a
,
b
and c
than above:
$ module load b $ module load --force a WARNING: a conflicts with b $ module list Currently Loaded Modulefiles: 1) b 2) a $ module purge $ module load --force c WARNING: c requires a loaded $ module list Currently Loaded Modulefiles: 1) c
--force
also enables to unload a modulefile required by another loaded
modulefiles:
$ module load a c $ module list Currently Loaded Modulefiles: 1) a 2) c $ module unload --force a WARNING: a is required by c $ module list Currently Loaded Modulefiles: 1) c
In a situation where some of the loaded modulefiles have unsatisfied constraints corresponding to the prereq and conflict they declare, the save and reload sub-commands do not perform and return an error.
Automated module handling mode¶
An automatic management of the dependencies between modulefiles has been added and it is called automated module handling mode. This new mode consists in additional actions triggered when loading or unloading a modulefile to satisfy the constraints it declares.
When loading a modulefile, following actions are triggered:
- Requirement Load (ReqLo): load of the modulefiles declared as a prereq of the loading modulefile.
- Dependent Reload (DepRe): reload of the modulefiles declaring a prereq onto loaded modulefile or declaring a prereq onto a modulefile part of this reloading batch.
When unloading a modulefile, following actions are triggered:
- Dependent Unload (DepUn): unload of the modulefiles declaring a non-optional prereq onto unloaded modulefile or declaring a non-optional prereq onto a modulefile part of this unloading batch. A prereq modulefile is considered optional if the prereq definition order is made of multiple modulefiles and at least one alternative modulefile is loaded.
- Useless Requirement Unload (UReqUn): unload of the prereq modulefiles
that have been automatically loaded for either the unloaded modulefile, an
unloaded dependent modulefile or a modulefile part of this useless
requirement unloading batch. Modulefiles are added to this unloading batch
only if they are not required by any other loaded modulefiles.
MODULES_LMNOTUASKED
environment variable helps to keep track of these automatically loaded modulefiles and to distinguish them from modulefiles asked by user. - Dependent Reload (DepRe): reload of the modulefiles declaring a conflict or an optional prereq onto either the unloaded modulefile, an unloaded dependent or an unloaded useless requirement or declaring a prereq onto a modulefile part of this reloading batch.
In case a loaded modulefile has some of its declared constraints unsatisfied (pre-required modulefile not loaded or conflicting modulefile loaded for instance), this loaded modulefile is excluded from the automatic reload actions described above.
For the specific case of the switch sub-command, where a modulefile is unloaded to then load another modulefile. Dependent modulefiles to Unload are merged into the Dependent modulefiles to Reload that are reloaded after the load of the switched-to modulefile.
This automated module handling mode integrates concepts (like the Dependent Reload mechanism) of the Flavours extension, which was designed for Modules compatibility version. As a whole, automated module handling mode can be seen as a generalization and as an expansion of the Flavours concepts.
This new feature can be controlled at build time with the
--enable-auto-handling
configure option. This default configuration can be
superseded at run-time with the MODULES_AUTO_HANDLING
environment variable
or the command line switches --auto
and --no-auto
.
By default, automated module handling mode is disabled and will stay so until the next major release version (5.0) where it will be enabled by default. This new feature is currently considered experimental and the set of triggered actions will be refined over the next feature releases.
Consistency of module load/unload commands in modulefile¶
With the module load modulefile command, a given modulefile can automatically load a modulefile it pre-requires. Similarly with the module unload modulefile command, a given modulefile can automatically unload a modulefile it conflicts with.
Both commands imply additional actions on the loaded environment (loading or unloading extra modulefiles) that should cope with the constraints defined by the loaded environment.
Additionally module load and module unload modulefile commands express themselves constraints on loaded environment that should stay satisfied to ensure consistency.
To ensure the consistency of module load modulefile command once the
modulefile defining it has been loaded, this command is assimilated to a
prereq command. Thus the defined constraint is recorded in the
MODULES_LMPREREQ
environment variable. Same approach is used for module
unload modulefile command which is assimilated to a conflict command.
Thus the defined constraint is recorded in the MODULES_LMCONFLICT
environment variable.
To ensure the consistency of the loaded environment, the additional actions of the module load and module unload modulefile commands have been adapted in particular situations:
- When unloading modulefile, module load command will unload the modulefile it targets only if no other loaded modulefile requires it and if this target has not been explicitly loaded by user.
- When unloading modulefile, module unload command does nothing as the relative conflict registered at load time ensure environment consistency and will forbid conflicting modulefile load.
Please note that loading and unloading results may differ than from previous Modules version now that consistency is checked:
- Modulefile targeted by a module load modulefile command may not be able to load due to a registered conflict in the currently loaded environment. Which in turn will break the load of the modulefile declaring the module load command.
- Modulefile targeted by a module unload modulefile command may not be able to unload due to a registered prereq in the loaded environment. Which in turn will break the load of the modulefile declaring the module unload command.
- If automated module handling mode is enabled, module load modulefile command is interpreted when unloading modulefile as part of the Useless Requirement Unload (UReqUn) mechanism not through modulefile evaluation. As a consequence, an error occurring when unloading the modulefile targeted by the module load command does not break the unload of the modulefile declaring this command. Moreover unload of the module load targets is done in the reverse loaded order, not in the module load command definition order.
Modulefile alias and symbolic modulefile name consistency¶
With the module-alias and module-version modulefile commands, alternative names can be given to a modulefile. When these names are used to load for instance a modulefile, they are resolved to the modulefile they target which is then processed for the load action.
Until now, the alias and symbolic version names were correctly resolved for
the load and unload actions and also for the querying sub-commands
(like avail or whatis). However this alternative name information
vanishes once the modulefile it resolves to is loaded. As a consequence there
was no consistency over these alternative designations. In the following
example f
modulefile declares a conflict on e
alias which resolves to
d
modulefile:
$ module load e $ module list Currently Loaded Modulefiles: 1) d $ module info-loaded e $ module load f $ module list Currently Loaded Modulefiles: 1) d 2) f
Consistency of the alternative names set on a modulefile with module-alias
and module-version commands is now ensured to enable modulefile commands
prereq, conflict, is-loaded and module-info loaded using these
alternative designations as argument. This consistency is achieved, like for
the conflict and prereq consistencies, by keeping track of the alternative
names of the loaded modulefiles in an environment variable called
MODULES_LMALTNAME
:
$ module load e $ module list Currently Loaded Modulefiles: 1) d $ module info-loaded e d $ module load f WARNING: f cannot be loaded due to a conflict. HINT: Might try "module unload e" first. $ module list Currently Loaded Modulefiles: 1) d
Environment variable change through modulefile evaluation context¶
All environment variable edition commands (setenv
, unsetenv
,
append-path
, prepend-path
and remove-path
) have been updated to:
- Reflect environment variable value change on the environment of the current
modulefile Tcl interpreter. So using
$env(VAR)
will return the currently defined value for environment variableVAR
, not the one found prior modulefile evaluation. - Clear environment variable content instead of unsetting it on the
environment of the current modulefile Tcl interpreter to avoid raising
error about accessing an undefined element in
$env()
. Code is still produced to purely unset environment variable in shell environment.
Exception is made for the whatis
evaluation mode: environment variables
targeted by variable edition commands are not set to the defined value in the
evaluation context during this whatis
evaluation. These variables are
only initialized to an empty value if undefined. This exception is made to
save performances on this global evaluation mode.
Express Modules compatibility of modulefile with versioned magic cookie¶
Any modulefile should start with the #%Module
file signature (also called
the Modules magic cookie) and sometimes a version number may be placed right
after this string. Until now this version number corresponded to a modulefile
format version but it was never checked.
Starting with this new Modules release, this version number reflects the
minimum version of Modules required to interpret the modulefile. If the
version number is set along the magic cookie string it is now checked and the
modulefile is interpreted only if Modules version is greater or equal to this
version number. For instance, if a modulefile begins with the #%Module4.3
string, it can only be evaluated by Modules version 4.3 and above. Elsewhere
the modulefile is ignored like files without the #%Module
magic cookie
set.
Improved module message report¶
Module sub-commands like load
, unload
or switch
, may perform
multiple load or unload modulefile evaluations in a row. Also these kind of
evaluation modes may sometimes trigger additional load or unload evaluations,
when for instance a modulefile contains a module load
command.
To improve the readability of the module messages produced relatively to a load or an unload evaluation, these messages are now stacked under a Loading or an Unloading message block that gathers all the messages produced for a given modulefile evaluation:
$ module load --no-auto foo
Loading foo/1.2
ERROR: foo/1.2 cannot be loaded due to missing prereq.
HINT: the following module must be loaded first: bar/4.5
In addition, foreground load
, unload
, switch
and restore
actions (i.e., asked on the command-line) now report a summary of the
additional load and unload evaluations that were eventually triggered in
the process:
$ module load --auto foo
Loading foo/1.2
Loading requirement: bar/4.5
New modulefile commands¶
2 new modulefile Tcl commands have been introduced:
- set-function: define a shell function on sh-kind and fish shells.
- unset-function: unset a shell function on sh-kind and fish shells.
v4.1¶
This new version is backward-compatible with previous version 4 releases. It fixes bugs but also introduces new functionalities that are described in this section. See the 4.1 release notes for a complete list of the changes between Modules v4.0 and v4.1.
Virtual modules¶
A virtual module stands for a module name associated to a modulefile. The modulefile is the script interpreted when loading or unloading the virtual module which appears or can be found with its virtual name.
The module-virtual modulefile command is introduced to give the ability to define these virtual modules. This new command takes a module name as first argument and a modulefile location as second argument:
module-virtual app/1.2.3 /path/to/virtualmod/app
With this feature it is now possible to dynamically define modulefiles depending on the context.
Extend module command with site-specific Tcl code¶
module
command can now be extended with site-specific Tcl
code. modulecmd.tcl
now looks at a siteconfig.tcl file in an
etcdir
defined at configure time (by default $prefix/etc
). If
it finds this Tcl script file, it is sourced within modulecmd.tcl
at the
beginning of the main procedure code.
siteconfig.tcl
enables to supersede any global variable or procedure
definitions made in modulecmd.tcl
with site-specific code. A module
sub-command can for instance be redefined to make it fit local needs
without having to touch the main modulecmd.tcl
.
Quarantine mechanism to protect module execution¶
To protect the module command run-time environment from side effect
coming from the current environment definition a quarantine mechanism
is introduced. This mechanism, sets within module function definition
and shell initialization script, modifies the modulecmd.tcl
run-time
environment to sanitize it.
The mechanism is piloted by environment variables. First of all
MODULES_RUN_QUARANTINE
, a space-separated list of environment variable
names. Every variable found in MODULES_RUN_QUARANTINE
will be set in
quarantine during the modulecmd.tcl
run-time. Their value will be set
empty or set to the value of the corresponding MODULES_RUNENV_<VAR>
environment variable if defined. Once modulecmd.tcl
is started it
restores quarantine variables to their original values.
MODULES_RUN_QUARANTINE
and MODULES_RUNENV_<VAR>
environment variables
can be defined at build time by using the following configure option:
--with-quarantine-vars='VARNAME[=VALUE] ...'
Quarantine mechanism is available for all supported shells except csh
and tcsh
.
Pager support¶
The informational messages Modules sends on the stderr channel may sometimes be quite long. This is especially the case for the avail sub-command when hundreds of modulefiles are handled. To improve the readability of those messages, stderr output can now be piped into a paging command.
This new feature can be controlled at build time with the --with-pager
and --with-pager-opts
configure options. Default pager command is set
to less
and its relative options are by default -eFKRX
. Default
configuration can be supersedes at run-time with MODULES_PAGER
environment
variables or command-line switches (--no-pager
, --paginate
).
Warning
On version 4.1.0
, the PAGER
environment variable was
taken in consideration to supersede pager configuration at run-time. Since
version 4.1.1
, PAGER
environment variable is ignored to avoid side
effects coming from the system general pager configuration.
Module function to return value in scripting languages¶
On Tcl, Perl, Python, Ruby, CMake and R scripting shells, module function was not returning value and until now an occurred error led to raising a fatal exception.
To make module
function more friendly to use on these scripting shells
it now returns a value. False in case of error, true if everything goes well.
As a consequence, returned value of a module sub-command can be checked. For instance in Python:
if module('load', 'foo'):
# success
else:
# failure
New modulefile commands¶
4 new modulefile Tcl commands have been introduced:
- is-saved: returns true or false whether a collection, corresponding to currently set collection target, exists or not.
- is-used: returns true or false whether a given directory is currently
enabled in
MODULEPATH
. - is-avail: returns true or false whether a given modulefile exists in currently enabled module paths.
- module-info loaded: returns the exact name of the modulefile currently loaded corresponding to the name argument.
Multiple collections, paths or modulefiles can be passed respectively to
is-saved
, is-used
and is-avail
in which case true is returned if
at least one argument matches condition (acts as a OR boolean operation). No
argument may be passed to is-loaded
, is-saved
and is-used
commands to return if anything is respectively loaded, saved or used.
If no loaded modulefile matches the module-info loaded
query, an empty
string is returned.
New module sub-commands¶
Modulefile-specific commands are sometimes wished to be used outside of a modulefile context. Especially for the commands managing path variables or commands querying current environment context. So the following modulefile-specific commands have been made reachable as module sub-commands with same arguments and properties as if called from within a modulefile:
- append-path
- prepend-path
- remove-path
- is-loaded
- info-loaded
The is-loaded
sub-command returns a boolean value. Small Python example:
if module('is-loaded', 'app'):
print 'app is loaded'
else:
print 'app not loaded'
info-loaded
returns a string value and is the sub-command counterpart
of the module-info loaded
modulefile command:
$ module load app/0.8 $ module info-loaded app app/0.8
v4.0¶
Major evolution occurs with this v4.0 release as the traditional module command implemented in C is replaced by the native Tcl version. This full Tcl rewrite of the Modules package was started in 2002 and has now reached maturity to take over the binary version. This flavor change enables to refine and push forward the module concept.
This document provides an outlook of what is changing when migrating from v3.2 to v4.0 by first describing the introduced new features. Both v3.2 and v4.0 are quite similar and transition to the new major version should be smooth. Slights differences may be noticed in a few use-cases. So the second part of the document will help to learn about them by listing the features that have been discontinued in this new major release or the features where a behavior change can be noticed.
New features¶
On its overall this major release brings a lot more robustness to the module command with now more than 4000 non-regression tests crafted to ensure correct operations over the time. This version 4.0 also comes with fair amount of improved functionalities. The major new features are described in this section.
Additional shells supported¶
Modules v4 introduces support for fish, lisp, tcl and R code output.
Non-zero exit code in case of error¶
All module sub-commands will now return a non-zero exit code in case of error whereas Modules v3.2 always returned zero exit code even if issue occurred.
Output redirect¶
Traditionally the module command output text that should be seen by the user on stderr since shell commands are output to stdout to change shell's environment. Now on sh, bash, ksh, zsh and fish shells, output text is redirected to stdout after shell command evaluation if shell is in interactive mode.
Filtering avail output¶
Results obtained from the avail sub-command can now be filtered to only get the default version of each module name with use of the --default or -d command line switch. Default version is either the explicitly set default version or the highest numerically sorted modulefile or module alias if no default version set.
It is also possible to filter results to only get the highest numerically sorted version of each module name with use of the --latest or -L command line switch.
Extended support for module alias and symbolic version¶
Module aliases are now included in the result of the avail, whatis
and apropos sub-commands. They are displayed in the module path
section where they are defined or in a global/user modulerc section for
aliases set in user's or global modulerc
file. A @ symbol is added
in parenthesis next to their name to distinguish them from modulefiles.
Search may be performed with an alias or a symbolic version-name passed as argument on avail, whatis and apropos sub-commands.
Modules v4 resolves module alias or symbolic version passed to unload command to then remove the loaded modulefile pointed by the mentioned alias or symbolic version.
A symbolic version sets on a module alias is now propagated toward the resolution path to also apply to the relative modulefile if it still correspond to the same module name.
Hiding modulefiles¶
Visibility of modulefiles can be adapted by use of file mode bits or file ownership. If a modulefile should only be used by a given subset of persons, its mode an ownership can be tailored to provide read rights to this group of people only. In this situation, module only reports the modulefile, during an avail command for instance, if this modulefile can be read by the current user.
These hidden modulefiles are simply ignored when walking through the modulepath content. Access issues (permission denied) occur only when trying to access directly a hidden modulefile or when accessing a symbol or an alias targeting a hidden modulefile.
Improved modulefiles location¶
When looking for an implicit default in a modulefile directory, aliases are now taken into account in addition to modulefiles and directories to determine the highest numerically sorted element.
Modules v4 resolves module alias or symbolic version when it points to a modulefile located in another modulepath.
Access issues (permission denied) are now distinguished from find issues
(cannot locate) when trying to access directly a directory or a modulefile
as done on load, display or whatis commands. In addition,
on this kind of access not readable .modulerc
or .version
files are
ignored rather producing a missing magic cookie error.
Module collection¶
Modules v4 introduces support for module collections. Collections describe a sequence of module use then module load commands that are interpreted by Modules to set the user environment as described by this sequence. When a collection is activated, with the restore sub-command, modulepaths and loaded modules are unused or unloaded if they are not part or if they are not ordered the same way as in the collection.
Collections are generated by the save sub-command that dumps the current
user environment state in terms of modulepaths and loaded modules. By default
collections are saved under the $HOME/.module
directory. Collections
can be listed with savelist sub-command, displayed with saveshow
and removed with saverm.
Collections may be valid for a given target if they are suffixed. In this
case these collections can only be restored if their suffix correspond
to the current value of the MODULES_COLLECTION_TARGET
environment
variable. Saving collection registers the target footprint by suffixing
the collection filename with .$MODULES_COLLECTION_TARGET
.
Path variable element counter¶
Modules 4 provides path element counting feature which increases a reference counter each time a given path entry is added to a given path-like environment variable. As consequence a path entry element is removed from a path-like variable only if the related element counter is equal to 1. If this counter is greater than 1, path element is kept in variable and reference counter is decreased by 1.
This feature allows shared usage of particular path elements. For instance,
modulefiles can append /usr/local/bin
to PATH
, which is not unloaded
until all the modulefiles that loaded it unload too.
Optimized I/O operations¶
Substantial work has been done to reduce the number of I/O operations
done during global modulefile analysis commands like avail or
whatis. stat
, open
, read
and close
I/O operations have
been cut down to the minimum required when walking through the modulepath
directories to check if files are modulefiles or to resolve module aliases.
Interpretation of modulefiles and modulerc are handled by the minimum required Tcl interpreters. Which means a configured Tcl interpreter is reused as much as possible between each modulefile interpretation or between each modulerc interpretation.
Sourcing modulefiles¶
Modules 4 introduces the possibility to source a modulefile rather loading it. When it is sourced, a modulefile is interpreted into the shell environment but then it is not marked loaded in shell environment which differ from load sub-command.
This functionality is used in shell initialization scripts once module
function is defined. There the etc/modulerc
modulefile is sourced to
setup the initial state of the environment, composed of module use
and module load commands.
Removed features and substantial behavior changes¶
Following sections provide list of Modules v3.2 features that are discontinued on Modules v4 or features with a substantial behavior change that should be taken in consideration when migrating to v4.
Package initialization¶
MODULESBEGINENV
environment snapshot functionality is not supported
anymore on Modules v4. Modules collection mechanism should be used instead to
save and restore sets of enabled modulepaths and loaded modulefiles.
Command line switches¶
Some command line switches are not supported anymore on v4.0. When still using them, a warning message is displayed and the command is ran with these unsupported switches ignored. Following command line switches are concerned:
--force
,-f
--human
--verbose
,-v
--silent
,-s
--create
,-c
--icase
,-i
--userlvl
lvl,-u
lvl
Module sub-commands¶
During an help sub-command, Modules v4 does not redirect output made on stdout in ModulesHelp Tcl procedure to stderr. Moreover when running help, version 4 interprets all the content of the modulefile, then call the ModulesHelp procedure if it exists, whereas Modules 3.2 only interprets the ModulesHelp procedure and not the rest of the modulefile content.
When load is asked on an already loaded modulefiles, Modules v4 ignores this new load order whereas v3.2 refreshed shell alias definitions found in this modulefile.
When switching on version 4 an old modulefile by a new one, no error is raised if old modulefile is not currently loaded. In this situation v3.2 threw an error and abort switch action. Additionally on switch sub-command, new modulefile does not keep the position held by old modulefile in loaded modules list on Modules v4 as it was the case on v3.2. Same goes for path-like environment variables: replaced path component is appended to the end or prepended to the beginning of the relative path-like variable, not appended or prepended relatively to the position hold by the swapped path component.
During a switch command, version 4 interprets the swapped-out modulefile
in unload mode, so the sub-modulefiles loaded, with module load
order in the swapped-out modulefile are also unloaded during the switch.
Modules 4 provides path element counting feature which increases a reference
counter each time a given path entry is added to a given environment
variable. This feature also applies to the MODULEPATH
environment
variable. As consequence a modulepath entry element is removed from the
modulepath enabled list only if the related element counter is equal to 1.
When unusing a modulepath if its reference counter is greater than 1,
modulepath is kept enabled and reference counter is decreased by 1.
On Modules 3.2 paths composing the MODULEPATH
environment variable
may contain reference to environment variable. These variable references
are resolved dynamically when MODULEPATH
is looked at during module
sub-command action. This feature has been discontinued on Modules v4.
Following Modules sub-commands are not supported anymore on v4.0:
clear
update
Modules specific Tcl commands¶
Modules v4 provides path element counting feature which increases a reference
counter each time a given path entry is added to a given environment
variable. As a consequence a path entry element is not always removed
from a path-like variable when calling to remove-path
or calling to
append-path
or append-path
at unloading time. The path element is
removed only if its related element counter is equal to 1. If this counter
is greater than 1, path element is kept in variable and reference counter
is decreased by 1.
On Modules v4, module-info mode returns during an unload sub-command
the unload
value instead of remove
on Modules v3.2. However if
mode is tested against remove
value, true will be returned. During a
switch sub-command on Modules v4, unload
then load
is returned
instead of switch1
then switch2
then switch3
on Modules
v3.2. However if mode is tested against switch
value, true will
be returned.
When using set-alias, Modules v3.2 defines a shell function when variables are in use in alias value on Bourne shell derivatives, Modules 4 always defines a shell alias never a shell function.
Some Modules specific Tcl commands are not supported anymore on v4.0. When still using them, a warning message is displayed and these unsupported Tcl commands are ignored. Following Modules specific Tcl commands are concerned:
module-info flags
module-info trace
module-info tracepat
module-info user
module-log
module-trace
module-user
module-verbosity
Further reading¶
To get a complete list of the differences between Modules v3.2 and v4, please read the Changes between versions document.
A significant number of issues reported for v3.2 have been closed on v4. List of these closed issues can be found at:
Release notes¶
This file describes changes in recent versions of Modules. It primarily documents those changes that are of interest to users and admins.
Modules 5.3.0 (2023-05-14)¶
- Add Module cache design notes.
- Add
cachebuild
sub-command to create cache for modulepaths enabled or specified on the command line. Cache files are named.modulecache
and stored at the root of modulepath directories. - Add
cacheclear
sub-command to delete cache file in all enabled modulepaths. - Use cache file if available rather search the content of modulepath
directories when searching for modules (e.g., during
avail
,load
,display
, etc). - Script: add cache-enabled version of avail, whatis and load tests on mb benchmark utility.
- Add the
ignore_cache
configuration option to ignore module cache file. Option is disabled by default and when set, it definesMODULES_IGNORE_CACHE
environment variable. - Add
--ignore-cache
command-line switch to enableignore_cache
configuration option and ignore module cache file for current execution. - Add
cache_buffer_bytes
configuration option to define buffer size when reading or writing cache files. Option is set to32768
by default. When set it definesMODULES_CACHE_BUFFER_BYTES
environment variable. - Add
cache_expiry_secs
configuration option that defines the number of seconds a cache file is considered valid after being generated. Option is set to0
by default which means cache files never expire. When option is set it definesMODULES_CACHE_EXPIRY_SECS
environment variable. - Modulefiles and directories that are not accessible by everyone are not recorded in cache file. A limited access directive is recorded instead to indicate these modulefiles have to be tested and directories have to be walked down to determine what the running user can access.
- Doc: update Reduce I/O load cookbook recipe with module cache description.
- Correctly apply extra tag set when loading a module whose variant has value automatically set. (fix issue #484)
- Catch collection directory creation error and report appropriate message. (fix issue #482)
- Fix
source-sh
andsh-to-mod
shell alias translation when used with new fish shell version (3.6). - Install: allow to build Modules from a short-depth git repository. (fix issue #486)
- Install: ensure git log format is not influenced by user's configuration in gitlog2changelog.py. (fix issue #487)
- Init: fix bash shell completion script to be able to complete full name of available modules. (fix issue #490)
- Install: move licence name to SPDX format in RPM spec file.
- Doc: add Extra match search design notes.
- Introduce extra match search mechanism that evaluates available modulefiles during a module search to find those matching an extra query on a variant value, a dependency or an environment variable definition. During this specific evaluation, modulefiles are interpreted in scan mode.
scan
string is returned bymodule-info mode
when queried during a scan modulefile evaluation.- Add the
variant
element in the allowed value list of theavail_output
andavail_terse_output
configuration options. When set, variants and their possible values are reported along the module they are associated to onavail
command output. Adding variant information to this output activates the extra match search mechanism that scan modulefiles to find variants they define. (fix issue #407) - Apply graphic rendition of default version (
de
SGR key) to default variant value on eitherlist
andavail
command output. - Apply either loaded or auto-loaded graphic rendition to the loaded variant
value on
avail
command output. - Update
avail
,paths
andwhatis
sub-commands to take into account variant set in module specification. Available modules are filtered with extra match search mechanism to only return those matching the variant specification. - Update
avail
,paths
andwhatis
sub-commands to accept module specification with just a variant set (no module name and version). Available modules are filtered with extra match search mechanism to only return those matching the variant specification. - Update
list
sub-command to accept module specification with just a variant set (no module name and version). Loaded modules are filtered to only return those matching the variant specification. - Highlight searched variant name and value (
hi
SGR key) on eitherlist
andavail
command output. - Doc: add Extra match search description in module man page.
- Introduce extra specifiers to query content of modulefiles. Extra
specifiers can be specified with element:name syntax as part of module
specification on module search commands (
avail
,paths
andwhatis
). For instance with themodule avail append-path:PATH
command, all modulefiles defining theappend-path
command onPATH
environment variable are returned. - Add
variant
extra specifier to query modulefile variant definitions. (fix issue #408) - Add
setenv
,unsetenv
,append-path
,prepend-path
,remove-path
andpushenv
extra specifiers to query modulefile environment variable definitions. The extra specifier aliasenvvar
may also be used to query any of these modulefile commands. - Add
complete
anduncomplete
extra specifiers to query modulefile shell completion definitions. - Add
set-alias
andunset-alias
extra specifiers to query modulefile shell alias definitions. - Add
set-function
andunset-function
extra specifiers to query modulefile shell function definitions. - Add
chdir
extra specifier to query modulefile current working directory change definitions. - Add
family
extra specifier to query modulefile family definitions. - Add
prereq
,prereq-any
,prereq-all
,depends-on
,always-load
,load
,load-any
,try-load
,switch
andswitch-on
extra specifiers to query modulefile requirement definitions. The extra specifier aliasrequire
may also be used to query any of these modulefile commands. - Add
conflict
,unload
,switch
andswitch-off
extra specifiers to query modulefile incompatibility definitions. The extra specifier aliasincompat
may also be used to query any of these modulefile commands. - Requirement and incompatibility extra specifiers accept module specification as value.
- Doc: add Extra specifier description in module man page.
- Mark loaded modules as qualified for refresh evaluation when they send
content to
stdout
orprestdout
channels withputs
modulefile command. (fix issue #488) - Add the
ignore_user_rc
configuration option to skip evaluation of user-specific module rc file. Option is disabled by default and when set, it definesMODULES_IGNORE_USER_RC
environment variable. - Add
--ignore-user-rc
command-line switch to enableignore_user_rc
configuration option and ignore user-specific module rc file for current execution. - Add the
variantifspec
element in the allowed value list of theavail_output
andavail_terse_output
configuration options. Set this new element in the default value list of both options. When set and if a variant is specified in search query, variants and their possible values are reported along the module they are associated to onavail
command output. - Accept value starting with
+
or-
characters on--output
/-o
command-line switches to indicate value should respectively be appended to or subtracted from current configuration option value. - Accept value starting with
+
or-
characters onavail_output
,avail_terse_output
,list_output
,list_terse_output
,colors
,protected_envvars
,shells_with_ksh_fpath
,tag_abbrev
,tag_color_name
,variant_shortcut
configuration options to indicate value should respectively be appended to or subtracted from current configuration option value. - Fix
switch
sub-command not to unload sticky module when switched-on module does not exist. (fix issue #492)
Modules 5.2.0 (2022-11-08)¶
- Introduce the
--optional
option onprereq
,prereq-all
,depends-on
andalways-load
modulefile commands. Expressed optional dependency is considered satisfied even if modulefile is not loaded. If optional requirement is loaded afterward, dependent module is automatically reloaded, unless if theauto_handling
configuration option is disabled. - A dependency expressed in modulefile with
module try-load
command is considered optional. Dependent module is automatically reloaded if the optional requirement is loaded afterward, unless if theauto_handling
configuration option is disabled. - Raise error in case of unknown or misplaced option set on
prereq
,prereq-all
,depends-on
oralways-load
modulefile commands. - Add the
--timer
command-line switch to report the total execution time of the module command. Also report the execution time of every internal procedure calls when mixed with--debug
option. - Init: move
PATH
setup (to locate Modules' binaries location) from shell initialization scripts to theautoinit
sub-command. (fix issue #462) - Init: move
MANPATH
setup (to locate Modules' man-pages) from shell initialization scripts to theautoinit
sub-command. (fix issue #462) - Init: move shell completion setup from shell initialization scripts to the
autoinit
sub-command. (fix issue #462) - Enclose installation path references in shell code produced by
autoinit
, in initialization scripts and Makefiles to guaranty correct evaluation in case these paths contain a space character. Note that the quarantine mechanism is not compatible with such installation paths. - Fix
source-sh
andsh-to-mod
when used with fish shell script ifregex-easyesc
fish option is enabled. (fix issue #463) - Add the
protected_envvars
configuration option to define a list of environment variables that cannot be modified by modulefile commands. When set,protected_envvars
definesMODULES_PROTECTED_ENVVARS
environment variable. (fix issue #429 with contribution from Adrien Cotte) - Introduce the
lint
sub-command to statically analyze syntax of modulefiles, modulerc and global/user rc. (fix issue #451) - Add the
tcl_linter
configuration option to define the program used to analyze files withlint
sub-command. This option is set tonagelfar.tcl
by default. When changed from default value, theMODULES_TCL_LINTER
environment variable is defined. Default value can be changed with--with-tcl-linter
and--with-tcl-linter-opts
installation options. - Add the
--enable-nagelfar-addons
installation option (enabled by default) to install specific syntax databases and plugins to lint modulefiles, modulerc and global/user rc with Nagelfar. These files are installed in the directory designated by the--nagelfardatadir
(DATAROOTDIR/nagelfar
by default). - Doc: add lint sub-command design notes.
- Install: use install command rather cp or mkdir to install Modules and guaranty consistent permission modes on deployed files.
- Also unset
pushenv
value stacks onclear
sub-command. - Doc: add mod-to-sh sub-command design notes.
- Introduce the
mod-to-sh
sub-command to translate designated modulefile(s) into code for specified shell. (fix issue #447) - Make
source
sub-command accepts modulefile specification as argument. If argument does not correspond to a file path, search it among available modulefiles. (fix issue #424) - Doc: clarify
set-alias
only define shell alias and not shell function. - Add the ability to filter the list of collections returned by
savelist
sub-command. Filtering pattern is matched in a case insensitive manner by default. - Add support for
--starts-with
and--contains
options onsavelist
sub-command. - Highlight all search patterns on
list
sub-command output instead of only the first one.. - Highlight all search patterns on
savelist
sub-command output. - Add support for
--all
option onsavelist
sub-command not to limit result to the collection matching currently definedcollection_target
. - Doc: add Shell support section in modulefile man page to describe how shells support the different kind of environment changes that can be defined in modulefiles.
- Record during
autoinit
sub-command the initial environment state in__MODULES_LMINIT
. Enabled modulepaths and loaded modulefiles throughmodulespath
andinitrc
initialization configuration files are recorded in this new environment variable. - Add
reset
sub-command to restore initial environment. It takes recorded environment in__MODULES_LMINIT
and restores it. - Initial environment is restored when collection name specified on
restore
sub-command equals__init__
. - When no argument is provided to
restore
sub-command and if default collection does not exist, initial environment is restored. - Initial environment content is displayed when collection name specified on
saveshow
sub-command equals__init__
. - When no argument is provided to
saveshow
sub-command and if default collection does not exist, initial environment content is displayed. - Add
reset_target_state
configuration option to determine behavior ofreset
sub-command. When set to__init__
(default value) initial environment is restored. When set to__purge__
, apurge
sub-command is performed. Any other value, corresponds to the name of a collection torestore
. When set,reset_target_state
definesMODULES_RESET_TARGET_STATE
environment variable. - Doc: add Initial environment design notes.
- Unload sticky modules on
restore
andreset
sub-commands to fully set environment in collection or initial state. - Testsuite: add lint testsuite to validate syntax of shell and Tcl scripts
of this project. This testsuite can be invoked with
make testlint
orscript/mt lint
. sh, bash and ksh scripts are checked with ShellCheck tool and tcl scripts are checked with Nagelfar. - Update
modulecmd.tcl
code and add Nagelfar inline comments to fix linter reports. - Script: add usage message and support for
-h
/--help
option on mrel, mpub, mt, mtreview, nglfar2ccov, mb and mlprof development utilities. - Doc: describe script/mt and script/mb utilities in Contributing guide.
- Fix ShellCheck error, warning and info reports over all sh, bash and ksh shell scripts. (fix issue #470 with contribution from Lukáš Zaoral)
- Init: update profile script for sh-like shells to only source sh or bash initialization script when BASH environment variable is found set. (fix issue #473)
- Add
stash
sub-command to save current environment and restore initial one. - Add
stashpop
sub-command to restore stash collection then delete this collection file. - Add
stashrm
sub-command to delete stash collection file. - Add
stashshow
sub-command to display stash collection file. - Add
stashclear
sub-command to delete all stash collection files. - Add
stashlist
sub-command to list all stash collection files. - Update
savelist
sub-command to filter out stash collections unless if--all
option is set. - Doc: ensure current user environment does not break logging system in Log module command recipe. (fix issue #475)
- Rename the default git branch from master to main to use inclusive terminology.
- Mark loaded modules that could benefit from a refresh evaluation in the
__MODULES_LMREFRESH
environment variable. - Optimize
refresh
sub-command to only evaluate loaded modules that defines volatile environment changes (shell completion, alias or function). (fix issue #477) - Add
modulefile_extra_cmds
hook variable that could be defined insiteconfig.tcl
file to define specific commands in modulefile interpreter context.modulefile_extra_cmds
is a list of command name and relative procedure pairs. (fix issue #286) - Add
modulefile_extra_vars
hook variable that could be defined insiteconfig.tcl
file to define specific variables in modulefile interpreter context.modulefile_extra_vars
is a list of variable name and value pairs. (fix issue #286) - Add
modulerc_extra_cmds
hook variable that could be defined insiteconfig.tcl
file to define specific commands in modulerc interpreter context.modulerc_extra_cmds
is a list of command name and relative procedure pairs. (fix issue #286) - Add
modulerc_extra_vars
hook variable that could be defined insiteconfig.tcl
file to define specific variables in modulerc interpreter context.modulerc_extra_vars
is a list of variable name and value pairs. (fix issue #286) - Doc: Add Site-specific configuration section in module man page.
- Doc: extend Collections section with examples in module man page.
Modules 5.1.1 (2022-05-31)¶
- Install: add rpmlint rc configuration file to filter false positive warning messages.
- Install: better guess
libdir64
andlibdir32
directory locations whenlibdir
does not end with 64 but contains 64. - Install: update RPM spec file to move libtclenvmodules in an
environment-modules directory under
libdir
. - Fix rendering of loading or unloading module designation when configured
color palette does not set the
hi
color key. (fix issue #455) - Remove the already loaded message displayed when verbosity level is higher
or equal to
verbose2
if new tags are applied to the loaded module. (fix issue #456) - Report a global known error when current working directory cannot be retrieved due to the removal of this directory. (fix issue #457)
- Update tags set through
prereq
command on all already loaded requirements. (fix issue #459) - Update module designation with the tags set by reloading dependent module. (fix issue #460)
- Install: include the
lib/config.guess
andlib/config.sub
scripts in distribution tarball if generated by autoreconf. - Install: call
git
command inMakefile
only if the definitions ofversion.inc
need to get built or refreshed.
Modules 5.1.0 (2022-04-30)¶
- Allow to declare
variant
with no list of accepted value. Such variant accepts any value specified. (fix issue #405) - Add the
redirect_output
configuration option to control on sh, bash, ksh, zsh and fish shells whether or not the output of the module function should be redirected from stderr to stdout. When set,redirect_output
definesMODULES_REDIRECT_OUTPUT
environment variable. - Introduce the
--redirect
/--no-redirect
command-line switches to supersede the value of theredirect_output
configuration option on sh, bash, ksh, zsh and fish shells. (fix issue #410) - Add the
--return-value
option to thegetenv
andgetvariant
modulefile commands to force to return the value of respectively designated environment variable or variant when modulefile is evaluated in display mode. (fix issue #422) - Introduce the
state
sub-command to display Modules states. - Add the
supported_shells
state to get the list of the shells that are supported bymodulecmd.tcl
through thestate
sub-command . (fix issue #426) - Filter out the variables intended for Modules private usage when processing
the environment changes made by a script evaluated by
sh-to-mod
sub-command orsource-sh
modulefile command. (fix issue #427) - Doc: add Control mode behaviors design notes.
- Doc: add Add new configuration option design notes.
- Set a Code of conduct for the project and its community based on the widely adopted Contributor Covenant.
- Doc: add Add new module sub-command design notes.
- Add the
--remove-on-unload
option to theremove-path
to also remove value when modulefile is unloaded. - Raise error when an unknown option is set on
module use
ormodule unuse
modulefile command. - Rework emitted debug messages to remove obvious ones and systematically report each modulefile command processed with their arguments.
- Add the
--append-on-unload
option to theremove-path
andmodule unuse
modulefile commands to append back when modulefile is unloaded the value removed at load time or a specific value set after this option. - Add the
--prepend-on-unload
option to theremove-path
andmodule unuse
modulefile commands to prepend back when modulefile is unloaded the value removed at load time or a specific value set after this option. - Add the
--noop-on-unload
option to theunsetenv
,remove-path
andmodule unuse
modulefile commands to perform no operation when modulefile is unloaded. - Add the
--unset-on-unload
option to theunsetenv
modulefile command to also unset environment variable when modulefile is unloaded. - Add the
--set-if-undef
option to thesetenv
modulefile command to set environment variable when modulefile is loaded only this variable is not yet defined. - Install: add the
--with-bashcompletiondir
,--with-fishcompletiondir
and--with-zshcompletiondir
installation options to install shell completion scripts in their system-wide location. (fix issue #428) - Doc: add Lmod Tcl modulefile compatibility design notes.
- Introduce the
add-property
,remove-property
andextensions
modulefile commands for compatibility with Lmod Tcl modulefiles. These commands are evaluated as a no-operation command. - Introduce the
prereq-any
modulefile command for compatibility with Lmod Tcl modulefiles.prereq-any
is an alias ofprereq
command. - Produce a clear error message when wrong number of argument is received by
prereq
command. - Doc: describe
ModulesVersion
in Modules Variables section in modulefile man page. - Set
ModuleVersion
as an alias overModulesVersion
modulefile variable for compatibility with Lmod Tcl modulefiles. - Doc: describe
reportError
andreportWarning
modulefile commands. - Add the
require-fullname
modulefile command for compatibility with Lmod Tcl modulefiles. This command aborts modulefile load evaluation if modulefile's name is not fully specified. - Add the
prereq-all
modulefile command, alias over theprereq
command which acts as an AND operation when multiple modulefiles are specified. - Add the
depends-on
modulefile command, alias over theprereq-all
command for compatibility with Lmod Tcl modulefiles. - Introduce the
keep-loaded
module tag that avoids an auto-loaded module to get automatically unloaded when its dependent modules are getting unloaded. Update defaulttag_abbrev
configuration option to add an abbreviation for the new tag (kL
) and default light and dark color palettes. - Add the
always-load
modulefile command for compatibility with Lmod Tcl modulefiles. This command loads designated modulefile and applies thekeep-loaded
tag to it. - Add the
load-any
sub-command andmodule load-any
modulefile command for compatibility with Lmod Tcl modulefiles. This command loads one modulefile from specified list. - Add support for
--not-req
option onmodule try-load
andmodule load-any
modulefile commands. - Doc: add Module magic cookie check design notes.
- Add the
mcookie_check
configuration option that control whether the magic cookie at the start of modulefile (i.e.,#%Module
file signature) need to get checked or not. When set toeval
the number of file checks is significantly reduced when walking through modulepaths to search for modulefiles. Default value for this option is overridden by theMODULES_MCOOKIE_CHECK
environment variable. - Doc: describe
puts
Tcl command and its specific feature when used in modulefile. - Create the
prestdout
channel forputs
modulefile command to be able to send content that will be evaluated in current shell session prior any other content. (fix issue #432) - Add the
family
modulefile command for compatibility with Lmod Tcl modulefiles. This command defines family name as a module alias over currently loading module and express a conflict over this name to ensure only one member of a family can be loaded in user environment.family
also defines theMODULES_FAMILY_<NAME>
andLMOD_FAMILY_<NAME>
environment variables. - Doc: add Reduce I/O load cookbook recipe.
- Add the ability to filter the list of loaded modules returned by
list
sub-command. Filtering pattern could be part of module name, symbolic version or alias and is matched in a case insensitive manner by default. It could also leverage the Advanced module version specifiers syntax. - Add support for
--starts-with
and--contains
options onlist
sub-command. - Doc: add Shell completion design notes.
- Introduce
complete
anduncomplete
modulefile commands to respectively enable and disable shell completion for a given command name. bash, tcsh and fish shells are supported. - Track shell completion changes of bash, tcsh and fish shell scripts on
sh-to-mod
sub-command andsource-sh
modulefile command. - Fix typos found in code, tests and documentation. (contribution from Dimitri Papadopoulos Orfanos)
- Update the
sh-to-mod
andsource-sh
mechanisms to support nested function definition on fish shell. - Fix the
sh-to-mod
andsource-sh
mechanisms to correctly detect functions with a_
character in their name on fish shell. - Update the module shell function definition for sh-kind shell to
enclose the output generated by
modulecmd.tcl
in quotes in order to pass it to the eval command. This change fixes definition of shell function, especially when coming from shell script evaluation over thesh-to-mod
andsource-sh
mechanisms. (fix issue #434) - Fix csh shell alias detection on
sh-to-mod
andsource-sh
mechanisms when enclosed in parenthesis. (fix issue #434) - Include for fish shell environment analysis on
sh-to-mod
andsource-sh
mechanisms the private functions defined by evaluated script, in order to catch all definitions that may be useful for shell completion. - Fix the
sh-to-mod
andsource-sh
mechanisms to correctly detect empty function on fish shell. - Script: add pre-commit git hook script to help verify if commits are free of misspellings (with codespell tool) and trailing spaces.
- Doc: fix typos found in documentation with Aspell utility.
- Doc: describe Dependencies between modulefiles in modulefile man page. (fix issues #431 and #433)
- Script: update pre-commit git hook script to spell check documentation files with Aspell tool.
- Script: add commit-msg git hook script to spell check commit message with Aspell tool.
- Doc: clarify that
#%Module
is a file signature also called Modules magic cookie. - Doc: update the ENVIRONMENT section in module man
page to provide for each Modules environment variable the name of the
configuration option that could be used to set the variable with the
config
sub-command. - Doc: clarify in module man page that
MODULES_SET_SHELL_STARTUP
,MODULES_SHELLS_WITH_KSH_FPATH
andMODULES_WA_277
should be set prior Modules initialization to get taken into account. - Doc: update Installing Modules on Unix document to provide the name of the configuration option linked the installation options.
- Doc: describe in module man page the default value of each configuration option and linked installation option and command-line switches.
- Doc: add Configuration options section in Installing Modules on Unix document with a table summarizing all configuration options and their relative installation options and environment variables.
- Add the
pushenv
modulefile command for compatibility with Lmod Tcl modulefiles. This command sets designated environment variable with specified value and save the previous value set to restore it when the modulefile is unloaded. Previous values are saved in a__MODULES_PUSHENV_<VAR>
environment variable. - Doc: add Compatibility with Lmod Tcl modulefile section in modulefile man page.
- Update definition of the
module()
python function and python initialization script to explicitly send output tosys.stderr
to get the ability to catch this content. - Lib: handle
sysconf
error in function implementing theinitStateUsergroups
procedure. (contribution from Lukáš Zaoral) - Introduce the
--tag
option for theload
,try-load
,load-any
,switch
sub-commands and associatedmodule
modulefile commands andprereq
,prereq-all
,depends-on
andalways-load
modulefile commands. This new option applies specified tags to the module to load. - Record tags set to loaded modules with the
--tag
option in the__MODULES_LMEXTRATAG
environment variable to make this information persists after module being loaded. - When saving a collection, record loaded module tags set with the
--tag
option and those resulting from module load states (likeauto-loaded
andkeep-loaded
). The--notuasked
string previously used to designate auto-loaded modules in collection is changed into the--tag=auto-loaded
option. - Introduce the
collection_pin_tag
configuration option, that records in collection all tags set on loaded modules when enabled. Option is disabled by default and when set it defines theMODULES_COLLECTION_PIN_TAG
environment variable. - When a collection is saved, its content starts with a
#%Module5.1
file signature if--tag
option is recorded in it. - Update the
restore
,savelist
,saveshow
andis-saved
sub-commands to exclude from result or return an error when checking a collection expressing a higher Modules version requirement in its header signature than the one currently in use. - Doc: describe differences between run-command file and modulefile interpretation in modulefile man page.
- Doc: describe
module
sub-commands available as modulefile Tcl command for each interpretation context in modulefile man page. - When loading a module with some extra tags defined through the
--tag
option, if this module is already loaded the new tags are added to those already set. - When reporting result of
avail
orlist
sub-commands, enclose module names in single quotes if they contain a space character. - When mentioning the loading, unloading or refreshing evaluation of a module,
report the tags associated to this module as done when printing results of
list
sub-command. - Fix Log module command cookbook recipe not to break Modules
initialization when using provided
siteconfig.tcl
file. (fix issue #453 with contribution from Eric Burgueño) - Mention tagging evaluation of a module, when tag list of an already loaded module is updated.
Modules 5.0.1 (2021-10-16)¶
- Doc: add How to preserve my loaded environment when running screen entry in Frequently Asked Questions.
- Fix the advanced version specifier resolution when the
extended_default
option is off andicase
option is on when resolving version list specification. (fix issue #411) - Doc: improve the Log module command cookbook to rely on the
trace
Tcl command to track every modulefile evaluation and module/ml procedure calls. (fix issue #412) - Doc: fix missing space between list entries in Variants design doc. (fix issue #413)
- Correctly detect tags set on loaded modules when refreshing them.
- Set the
__MODULES_AUTOINIT_INPROGRESS
environment variable when running theautoinit
sub-command and quit autoinit process if this variable is found defined and equal to 1 when starting it. Ensure this way that an autoinit process will not be triggered indefinitely by itself when theset_shell_startup
option is enabled and some module loaded at initialization time relies on the execution of a bash script. (fix issue #414) - Remove warning message when unloading a
prepend-path
orappend-path
modulefile command with--duplicates
option set. (fix issue #421) - Clarify the module sub-commands that are allowed to be used within a modulefile. (fix issue #423)
- Install: set in the module magic cookie of the
initrc
configuration file installed by default the version of Modules required to evaluate this file. - Doc: fix documentation of
getenv
modulefile command to describe that an empty string is now returned when designated environment variable is not defined and no default value to return is specified.
Modules 5.0.0 (2021-09-12)¶
- Remove deprecated createmodule.sh and createmodule.py
tools as shell script to modulefile conversion is now achieved with the
sh-to-mod
sub-command. - Remove mention of the
init*
sub-commands in module usage message to put focus on the collection handling sub-commands. - Do not declare anymore the
chdir
,module
,module-trace
,module-verbosity
,module-user
andmodule-log
commands under the modulerc Tcl interpreter as no-op commands. A clear error message is obtained if these commands are still used in modulerc files instead of silently ignoring them. - Return by default an empty string rather
_UNDEFINED_
ongetenv
modulefile command if passed environment variable is not defined. - Align empty directory name error message obtained on
use
sub-command with message obtained when module or collection name is empty. - Accept non-existent modulepath on
use
sub-command. - Install: installation option
--enable-auto-handling
is set on by default which enables the automated module handling mode (seeMODULES_AUTO_HANDLING
). - Install: installation option
--enable-extended-default
is set on by default which allows partial module version specification (seeMODULES_EXTENDED_DEFAULT
). - Install: installation option
--enable-advanced-version-spec
is set on by default which activates the Advanced module version specifiers - Install: installation option
--enable-color
is set on by default which enables theauto
output color mode (seeMODULES_COLOR
). - Install: installation option
--with-icase
is set tosearch
by default to activate case insensitive match on search contexts (seeMODULES_ICASE
). - Install: installation option
--enable-new-features
has been reset following major version change as all the options it implied are now enabled by default. - Install: installation option
--enable-set-shell-startup
is set off by default but could be enabled once installed through theinitrc
configuration file. - Install: installation option
--with-initconf-in
is set toetcdir
by default to locate configuration files in the directory designated by the--etcdir
option. Therefore the initialization configuration file is namedinitrc
in this directory, and the modulepath-specific configuration file is namedmodulespath
. - Only look at configuration files found in the location designated by the
--etcdir
or--initdir
option (depending on the value of--with-initconf-in
option). Configuration files were previously searched in both locations. - Install: remove installation option
--enable-compat-version
. Compatibility version co-installation is discontinued. switchml shell function andMODULES_USE_COMPAT_VERSION
are thus removed as well. - Testsuite: introduce the non-regression quick test mode. When the
QUICKTEST
environment variable is set to1
, only the main tests from the non-regression testsuite are run. When first argument of the mt script isquick
, tests are run in quick mode. - Install: run non-regression testsuite in quick mode in RPM spec file.
- Rename the environment variables that are used by Modules to track loaded
environment state (variables whose name starts with
MODULES_LM
). A__
prefix is added to the name of these variables to indicate that they are intended for internal use only. - Rename the environment variables used to indirectly pass to
modulecmd.tcl
the value of variables set in quarantine (variables whose name finishes with_modquar
). A__MODULES_QUAR_
prefix is applied to the name of these variables instead of the_modquar
suffix to indicate they are intended for Modules internal use of only. - Update Tcl requirement to version 8.5 as Tcl 8.4 is deprecated since a long
time and this version is not available anymore on recent OS distributions.
Update internal code of
modulecmd.tcl
to take benefit from the features brought by Tcl 8.5. - Split source code in several Tcl files hosted in
tcl
directory. When building Modules, the Tcl files are concatenated to make themodulecmd.tcl
script. - Record
auto-loaded
tag of loaded modules in__MODULES_LMTAG
environment variable rather set a specific entry for module in the__MODULES_LMNOTUASKED
environment variable. - Rename the environment variables used by the reference counting mechanism
of path-like environment variables. A
__MODULES_SHARE_
prefix is applied to the name of these variables instead of the_modshare
suffix to clearly indicate they are intended for Modules internal use of only. - Reference counting mechanism is not anymore applied to the Modules-specific
path variables (like
LOADEDMODULES
). As a result no__MODULES_SHARE_<VAR>
variable is set in user environment for these variables. Exception is made forMODULEPATH
environment variable where the mechanism still applies. - When an element is added to a path-like variable through the
append-path
orprepend-path
modulefile commands, add this element to the associated reference counter variable (named__MODULES_SHARE_<VAR>
) only when this element is added multiple times to the path-like variable. When an element is removed from a path-like variable, this element is removed from the reference counter variable when its counter is equal to 1. - When the
use
andunuse
module sub-commands are not called during a modulefile evaluation, the reference counter associated with each entry inMODULEPATH
environment variable is ignored. In such context, amodule use
will not increase the reference counter of a path entry already defined and amodule unuse
will remove specified path whatever its reference counter value. - When the
append-path
,prepend-path
andremove-path
module sub-commands are not called during a modulefile evaluation, the reference counter associated with each entry in targeted environment variable is ignored. In such context, amodule append-path/prepend-path
will not increase the reference counter of a path entry already defined and amodule remove-path
will remove specified path whatever its reference counter value. - Fix
unuse
sub-command when several modulepaths are specified as a single argument (i.e.,/path/to/dir1:/path/to/dir2
). Enabled modulepaths were not correctly detected when specified this way. - Doc: clarify that an already defined path is not added again or moved when
passed to the
use
sub-command or theappend-path/prepend-path
modulefile commands. (fix issue #60) - Change the
refresh
sub-command to evaluate all loaded modulefiles and re-apply the non-persistent environment changes they define (i.e., shell aliases and functions). With this change therefresh
sub-command is restored to the behavior it had on Modules version 3.2. - Evaluate the modulefile commands resulting from a
source-sh
command through the current modulefile Tcl interpreter in order to evaluate them according to the current modulefile evaluation mode. - When initializing Modules, refresh the loaded modules in case some user
environment is already configured. This is especially useful when starting a
sub-shell session as it ensures that the loaded environment in parent shell
is correctly inherited, as the
refresh
sub-command re-applies the non-persistent environment configuration (i.e., shell alias and function that are not exported to the sub-shell). (fix issue #86) - Init: add example code in default
initrc
, the initialization script of Modules, to either restore user's default collection if it exists or load a predefined module list at the end of the initialization process. - When initializing Modules, evaluate the
initrc
configuration file in addition to the themodulespath
configuration file and not instead of this file.initrc
is evaluated aftermodulespath
file. - When the installation option
--enable-modulespath
is set, the list of modulepath to enable by default is now only defined in themodulespath
configuration file and not anymore in theinitrc
configuration file. - No error is raised when evaluating in
display
mode a modulefile without a value specified for thevariant
it defines. This change helps to learn all the variant a modulefile defines. As a result, the unspecified variant is not instantiated in theModuleVariant
array variable. (fix issue #406) - When running the
unsetenv
modulefile command on an unload evaluation, do not unset designated environment variable if no value to restore is provided. - Fix
unsetenv
to distinguish between being called on a unload evaluation without a value to restore or with an empty string value to restore. - Make
system
modulefile command available from a modulerc evaluation context whatever the underlying module evaluation mode. - Make
is-used
modulefile command available from a modulerc evaluation context. - Remove internal state
tcl_version_lt85
as Tcl 8.5+ is now a requirement. - Forbid use of
module source
command in modulefile or in an initialization rc file, thesource
Tcl command should be used instead.source
sub-command should only be called from the command-line. - Report the modules loading and unloading during the module
command initialization (i.e., during the evaluation of the
initrc
configuration file). These report messages are disabled when theverbosity
configuration option is set toconcise
orsilent
. - During a module
restore
orsource
, only report the module load and unload directly triggered by these sub-commands. Load and unload triggered by other modules are reported through the automated module handling messages of the main modules. - Enforce use of the module magic cookie (i.e.,
#%Module
) at the start of global or user rc files,initrc
configuration file or any scriptfile passed for evaluation to thesource
sub-command. These files are not evaluated and an error is produced if the magic cookie is missing or if the optional version number placed after the cookie string is higher than the version of themodulecmd.tcl
script in use. - Doc: alphabetically sort installation option in Installing Modules on Unix document.
- Update the
--enable-quarantine-support
installation option to control aquarantine_support
configuration option. When this option is enabled, theautoinit
sub-command produces the shell code for the module shell function definition with quarantine mechanism support. When disabled, code is generated without quarantine support. - Install: installation option
--enable-quarantine-support
is set off by default. - Introduce the
MODULES_QUARANTINE_SUPPORT
environment variable to control thequarantine_support
configuration option once Modules is installed. To enable the quarantine mechanism,MODULES_QUARANTINE_SUPPORT
should be set to1
prior Modules initialization orquarantine_support
configuration option should be set to1
in theinitrc
configuration file. - Quarantine mechanism code in the Modules shell initialization scripts is now
always defined and mechanism always applies if some environment variables
are defined in
MODULES_RUN_QUARANTINE
. - Code in the
modulecmd.tcl
script to restore environment variables put in quarantine is now always generated and applies if the__MODULES_QUARANTINE_SET
environment variable is set to1
. This variable is set by the Modules initialization script prior calling theautoinit
sub-command or by the module shell function if it has been generated with quarantine support enabled. - Install: installation option
--enable-silent-shell-debug-support
is set off by default. - Code to silence shell debug properties in the Modules shell initialization
scripts is now always defined and mechanism applies if
MODULES_SILENT_SHELL_DEBUG
environment variable is set to1
. - Code to silence shell debug properties in the module shell
function could now be enabled if
MODULES_SILENT_SHELL_DEBUG
is set to1
prior Modules initialization or if thesilent_shell_debug
configuration option is set to1
in theinitrc
configuration file. - Doc: clarify TOC and title of MIGRATING document.
- Doc: extend description of Modules configuration steps of in Installing Modules on Unix document.
- Doc: document
initrc
andmodulespath
configuration files in module man page. - Install: replace
example.txt
byINSTALL.txt
guide in RPM. - Doc/Install: rename
diff_v3_v4
document into changes. - Doc: reorganize Changes between versions document to let room to describe Modules 5 changes.
Modules 4.8.0 (2021-07-14)¶
- Introduce the
edit
sub-command that opens modulefile passed as argument in a text editor. Modulefile can be specified like with any other sub-command, leveraging defined symbolic versions, aliases or using advanced version specifiers. - Add the
editor
configuration option to select the text editor to use withedit
sub-command. When this option is set through theconfig
sub-command, theMODULES_EDITOR
environment variable is set. The--with-editor
installation option controls the default value ofeditor
configuration option. If not set at installation time,vi
is set as default editor. - Default value of
editor
configuration option is overridden by theVISUAL
or theEDITOR
environment variables, which are both in turn overridden by theMODULES_EDITOR
environment variable. - Doc: fix
modulecmd.tcl
internal state check in recipes example codes. (fix issue #396) - The Advanced module version specifiers mechanism now allows the use
of version range in version list (for instance
mod@:1.2,1.4:1.6,1.8:
). Such specification helps to exclude specific versions. (fix issue #397) - Install: fix installation scripts to allow building Modules when its repository is set as a git submodule. (fix issue #398)
- Doc: demonstrate in the Source shell script in modulefile recipe how to use
the
source-sh
command when software provide a specific initialization script for each shell it supports. (fix issue #399) - When defining a shell function with the
set-function
modulefile command, only export this function when using the Bash shell (using theexport -f
shell command) to make it available in sub-shell contexts. Shell function export is not supported on other kind of sh shell (sh, ksh and zsh). (fix issue #401) - Doc: add Variants design notes.
- Add the
variant
modulefile command that enables to pass down arguments, specified when designating the module to evaluate, within modulefile evaluation context. This command defines a variant name and a list of allowed values. When evaluated,variant
instantiates an element in theModuleVariant
array whose name equals variant name and value is set with value specified for variant when module is designated. If specified value does not correspond to an allowed value or if no value is specified for variant an error is raised. - Enhance the Advanced module version specifiers to handle variant
specification following Spack's syntax (e.g., name=value). When the
advanced_version_spec
configuration is enabled, variant could be specified anywhere a module can be specified. - Add the
--default
option to thevariant
modulefile command to indicate the default value of the variant to apply when the designation of the evaluating module does not mention this variant. - Add the
--boolean
option to thevariant
modulefile command to indicate that the variant defined is of the Boolean type, thus no list of accepted value is expected. - Enhance the Advanced module version specifiers to handle Boolean variant specification following Spack's syntax (e.g., +name, ~name and -name). The -name syntax is not supported on ml command as the minus sign already means to unload designated module.
- Accept any minus argument (-word) set after the sub-command name when the
advanced_version_spec
configuration is enabled and if sub-command accepts Advanced module version specifiers (likeload
orunload
sub-commands). A false value may be set to Boolean variant this way. - Add the
variant_shortcut
configuration option to define shortcut characters that could be used to specify and report module variants. Default value for this option could be set at installation time with the--with-variant-shortcut
option. No variant shortcut is defined by default. This value could be superseded by setting up thevariant_shortcut
option withconfig
sub-command. Which sets theMODULES_VARIANT_SHORTCUT
environment variable. - Enhance the Advanced module version specifiers to handle variant shortcut specification (e.g., <shortcut>value).
- Record in user loaded environment, with
MODULES_LMVARIANT
environment variable, the value specified for the variants defined in the loaded modulefiles and their properties (if it is a Boolean variant and if the value set is the default one). - Add the
variant
element in the allowed value list of thelist_output
andlist_terse_output
configuration options. Set this new element in the default value list of thelist_output
option. When set, the variant defined for loaded modules are reported on modulelist
command output. - Add the
va
color key in default light and dark color palettes to graphically enhance the report of variant value. - Update the key section to explain on
list
sub-command output the reported variant elements (name=value, +name, -name or <shortcut>value) - Record variant specification of loaded modules when saving collections and reload specified variants when restoring these collections.
- When
collection_pin_version
configuration is disabled, only record in collections the variants whose value is not the default one. - Update module designation in error, warning or informational messages to report variant specification enclosed in curly braces ({}), enclose module name and version or variant specification in single quotes ('') if they contain a space character and highlight the module designation in report message if configured.
- Introduce the
getvariant
modulefile command to query for currently evaluating module the value of a given variant name. - When translating the
@loaded
version specifier also retrieve the variant specified for corresponding loaded module. - Update hide, forbid and tag mechanisms to apply them only if they match selected module variant.
- Any variant defined in module specification passed as argument to search
sub-commands (
avail
,whatis
,is-avail
,path
andpaths
) is ignored. - Raise an error if a variant named
version
is declared in a modulefile to let room for the future implementation of this specific variant. - Doc: describe in the Changes between versions document argument handling change on
setenv
since v3.2. (fix issue #402) - Introduce the
try-load
sub-command which likeload
sub-command tries to load the modulefile passed as argument, but does not complain if this modulefile cannot be found. (fix issue #392) - Init: fix stderr redirection in fish shell initialization script, now that
use of the
^
character to redirect stderr is disabled by default (fish >=3.3). - Protect quarantine mechanism code from
rcexpandparam
Zsh option when initializing the module command on this shell. (fix issue #403)
Modules 4.7.1 (2021-04-06)¶
- Doc: clarify the license terms used by the project. (fix issue #389)
- Align all files from the Modules project under the GPLv2+ license. Scripts and libraries that were previously licensed with GPLv3+ have been moved to GPLv2+ with the consent of their respective copyright holders. (fix issue #389)
- Revert "Install: have
configure
script assume the.
dot directory when invoked without the prepended./
" as consent was not obtained from author to re-license the contribution to GPLv2+. - Doc: fixes few typos in module and modulefile.
- Update the
sh-to-mod
mechanism to support version 3.2 of the fish shell. Fish 3.2 introduces the.
builtin command that should be regexp-escaped when determining the shell functions or aliases defined by the script analyzed bysh-to-mod
. - Vim: update addon files to highlight modulefile variables
ModuleTool
,ModuleToolVersion
andModulesCurrentModulefile
. - Doc: update the description and default value of the
--with-dark-background-colors
and--with-light-background-colors
installation options. - Doc: add description of changes that occurred on versions 4.6 and 4.7 for
the
--with-dark-background-colors
and--with-light-background-colors
installation options and for theMODULES_COLORS
environment variable. - Doc: correct the default value of the
--with-tag-abbrev
installation option. - Doc: add Sticky modules cookbook recipe.
Modules 4.7.0 (2021-02-19)¶
- Doc: simplify TOC of New features document
- Add the
ModuleTool
andModuleToolVersion
Modules variables to determine during modulefile or modulerc evaluation the name and version of the module implementation currently in use. - Introduce the
versioncmp
modulefile command to compare two version strings passed as argument. - Enable the use of wildcard character to designate multiple directories at
once in
modulespath
configuration file. (fix issue #125) - Distinguish aliases from symbolic versions in
MODULES_LMALTNAME
environment variable. Prefix these alias entries with theal|
string. - Fetch modulefile modification time only if required by
list
sub-command display format. - Use symbolic versions recorded in environment, with
MODULES_LMALTNAME
variable, to report the symbols applying to loaded modules onlist
sub-command. Modulerc files are not evaluated anymore when performing a module list. - Move the definition of the
FPATH
environment variable for Modules initialization on ksh shell from the initialization script of this shell to the resulting output of theautoinit
sub-command. - Introduce the
shells_with_ksh_fpath
configuration option to define a list of shell where to ensure that any ksh sub-shell will get the module function defined by use of theFPATH
environment variable. When theshells_with_ksh_fpath
option is set through theconfig
sub-command, theMODULES_SHELLS_WITH_KSH_FPATH
environment variable is set. Accepted values are a list of shell among sh, bash, csh, tcsh and fish separated by colon character (:
). - Add the
implicit_requirement
configuration option to control whether a prereq or a conflict requirement should be implicitly set onto modules respectively specified onmodule load
ormodule unload
commands in modulefile. Default value for this option could be set at configure time with the--enable-implicit-requirement
option (enabled by default). This value could be superseded by setting up theimplicit_requirement
option withconfig
sub-command. Which sets theMODULES_IMPLICIT_REQUIREMENT
environment variable. (fix issue #260) - Add the
--not-req
option to themodule
modulefile command to inhibit for itsload
andunload
sub-commands the definition of a prereq or conflict requirement onto specified modules. - Add the
lpopState
andcurrentState
procedures to respectively remove or return the last entry from the list of values of a given state. - Add the
topState
anddepthState
procedures to respectively return the first element from or the number of elements in the list of values of a given state. - Remove the pre-definition of runtime states with no specific property. These
basic states are defined on-the-fly which implied they are not reported on a
module config --dump-state
command unless if instantiated. - Introduce the
loaded
symbolic version among advanced version specifiers (e.g.foo@loaded
) to designate the currently loaded version of specified module. (fix issue #366) - Doc: add Module tags design notes.
- Report tags applying to the modules returned by the
avail
sub-command. Adapt the regular, terse and JSON output styles to report these tags along the module they are attached to (enclosed in<>
). Reported tags currently are states that apply to modules:auto-loaded
,forbidden
,hidden
,loaded
,nearly-forbidden
,sticky
andsuper-sticky
. - Record tags applying to each loaded module in the
MODULES_LMTAG
environment variable to make this information persist after module being loaded. - Report tags applying to the loaded modules returned by the
list
sub-command. Adapt the regular and JSON output styles to report these tags along the module they are attached to (enclosed in<>
). Reported tags currently are states applying to loaded modules:auto-loaded
,hidden-loaded
,nearly-forbidden
,sticky
andsuper-sticky
. - Introduce the
module-info tags
modulefile command to query the tags that apply to the currently evaluated modulefile. - Add the
module-tag
modulefile command to associate tag to designated modulefile. Those tags are reported onavail
andlist
sub-commands along the module they are attached to.module-tag
supports the advanced module version specifier syntax. - Add the
tag_abbrev
configuration option to define abbreviated strings for module tags and use these abbreviations instead of tag names when reporting tags onavail
andlist
command results. Default value for this option could be set at configure time with the--with-tag-abbrev
option. By default the following abbreviations are set:aL
for auto-loaded,F
for forbidden,H
for hidden,H
for hidden-loaded,L
for loaded,nF
for nearly-forbidden,S
for sticky,sS
for super-sticky. This value could be superseded by setting up thetag_abbrev
option withconfig
sub-command. Which sets theMODULES_TAG_ABBREV
environment variable. - A Select Graphic Rendition (SGR) code can be associated to module tag names or abbreviation strings in the color palette to graphically render these tags over the module name they are associated to. The default light and dark color palettes have been updated to set a color code for all basic module tags. When a color code is set for a tag, it is then graphically rendered over the module names and not reported along module name by its tag name or abbreviation. When multiple colored tags apply to a given module, each tag is graphically rendered over a sub-part of the module name.
- Add the
tag_color_name
configuration option to designate module tags whose graphical rendering should be applied to their own name or abbreviation rather than over the module name they are attached to. Default value for this option could be set at configure time with the--with-tag-color-name
option (empty by default). This value could be superseded by setting up thetag_color_name
option withconfig
sub-command. Which sets theMODULES_TAG_COLOR_NAME
environment variable. - Add the
--hidden-loaded
option to themodule-hide
modulefile command that indicates module should be hidden once loaded. When set, thehidden-loaded
module tag applies to module specification set onmodule-hide
command. - Do not report on
list
sub-command results the loaded modules associated with thehidden-loaded
tag, unless if the--all
option is set. - Doc: add an
hidden-loaded
example in the Hide and forbid modules cookbook recipe. - Introduce the
verbose2
verbosity level betweenverbose
andtrace
levels. Verbose2 mode can be enabled by setting theverbosity
config to theverbose2
value or by using the-v
command-line switch twice. - Do not report the load, unload or switch of modules set
hidden-loaded
if these modules have been loaded, unloaded or switched automatically. Unless the verbosity mode is set toverbose2
or any higher level or if any specific messages have to be reported for these module evaluations. - Report when trying to load a module which is already loaded or when trying
to unload a module which is not loaded in case the verbosity mode is set to
verbose2
or any higher level. (fix issue #187) - Doc: improve readability of version 4 improvements in Changes between versions document.
- Introduce stickiness: module tagged
sticky
withmodule-tag
command cannot be unloaded unless if the unload is forced or if the module is reloaded. (fix issue #269) - Introduce super-stickiness: module tagged
super-sticky
withmodule-tag
command cannot be unloaded even if the unload is forced unless if the module is reloaded. (fix issue #269) - Allow swap of sticky or super-sticky modules by another modulefile version if stickiness definition applies to module parent name. E.g., foo/1.0 can be swapped by foo/2.0 if sticky tag applies to foo.
- When forcing purge with a
purge --force
sub-command, also unload the modules that are depended by non-unloadable modules. - Doc: improve readability of Modules installation configuration in Installing Modules on Unix document and enable hypertext reference to these elements.
- Doc: improve readability of module command configuration option in module document and enable hypertext reference to these elements.
- Doc: describe in HTML documentation when installation options, module command configuration options and options of modulefile command or module sub-command were introduced.
- Doc: update HTML documentation Table Of Content.
- Doc: improve markup of module sub-commands, modulefile commands, installation option, module configuration option across documentation.
- Doc: colorize terminal output examples in New features document.
- Abort modulefile read if first file content chunk does not start with the
#%Module
magic cookie. (fix issue #375) - Install: add installation option
--enable-new-features
that enables all at once the installation options that are disabled by default due to the substantial behavior changes they imply. - Add a Key section at the end of
avail
andlist
sub-commands to explain the meaning of graphical renditions or of elements set in parentheses or chevrons along module name. - Fix output of
avail
andlist
sub-commands on very small terminal width. (fix issue #378) - Add
mcookie_version_check
configuration to define if version set in modulefile magic cookie should be checked against module current version to determine if modulefile can be evaluated. The new configuration, which is enabled by default, can be set at installation time with configure option--enable-mcookie-version-check
or can be superseded later on with theMODULES_MCOOKIE_VERSION_CHECK
environment variable. (fix issue #377) - Fix output of modulefile evaluation error stack trace on very small terminal width. (fix issues #379 and #381)
- Correct
config
sub-command to setnearly_forbidden_days
configuration. (fix issue #380) - Init: reduce usage of helper variables in
bash_completion
andtcsh_completion
that are showing up in the output of the shell'sset
command. (fix issue #382 with contribution from Colin Marquardt) - Consider modulepath starting with a reference to an environment variable as absolute. (fix issue #376)
- Consider the
module load
performed in the user or the global RC file like load commands issued from initialization RC file. (fix issue #372) - Install: have
configure
script assume the.
dot directory when invoked without the prepended./
. (contribution from R.K. Owen) - Install: disable the Makefile rules to build the HTML documentation in case if the documentation is found pre-built in the dist archive.
- Install: do not flag documentation as pre-built if
configure
script is ran another time after building docs. - Restrict the value accepted by
nearly_forbidden_days
configuration and--with-nearly-forbidden-days
installation option to integers comprised between 0 and 365. - Install: color ERROR and WARNING message headers produced by
configure
script if output is sent to a terminal. - Install: split error messages produced by
configure
script over an additional line when too long. - Doc: add Output configuration design notes.
- Introduce the
avail_output
andavail_terse_output
configuration options to define the content to report in addition to the available module names respectively foravail
sub-command regular and terse output modes. Excepted value for these configuration options is a colon separated list of elements to report. Default value ismodulepath:alias:dirwsym:sym:tag:key
foravail_output
andmodulepath:alias:dirwsym:sym:tag
foravail_terse_output
. These values can be changed at installation time respectively with the--with-avail-output
and--with-avail-terse-output
options. These values can then be superseded by using theconfig
sub-command which sets theMODULES_AVAIL_OUTPUT
andMODULES_AVAIL_TERSE_OUTPUT
environment variables. - Introduce the
list_output
andlist_terse_output
configuration options to define the content to report in addition to the available module names respectively forlist
sub-command regular and terse output modes. Excepted value for these configuration options is a colon separated list of elements to report. Default value isheader:idx:sym:tag:key
forlist_output
andheader
forlist_terse_output
. These values can be changed at installation time respectively with the--with-list-output
and--with-list-terse-output
options. These values can then be superseded by using theconfig
sub-command which sets theMODULES_LIST_OUTPUT
andMODULES_LIST_TERSE_OUTPUT
environment variables. - Add the
--output
/-o
command-line switches to supersede the output configuration ofavail
orlist
sub-commands on their regular or terse output modes. - Remove the
avail_report_dir_sym
andavail_report_mfile_sym
locked configuration options whose behaviors can now be obtained by respectively adding thedirwsym
andsym
elements to theavail_output
oravail_terse_output
configuration options. - When
modulepath
is omitted from the content to report onavail
sub-command, available modules collected from global/user rc and enabled modulepaths are aggregated and reported all together. - Install: print generated file names rather commands executed to generate
these files on Makefile build targets. Output obtained when building Modules
is this way simplified. When option
V=1
is passed tomake
, the verbose mode is enabled and run commands are shown. The simplifiedmake
output does not apply to the install, test and clean targets or any target similar to them. - Install: fix configure and build files of Modules Tcl extension library to make them compatible with autoconf >=2.69.
- Script: correctly detect previous Modules version number released from a side git branch on mpub command.
- Install: align RPM spec file syntax with spec file used on Fedora. Add
missing build dependency on
make
package. Also remove obsoleteGroup
RPM tag. - Add the
term_width
configuration option to set the width of the output. This configuration option is set to0
by default, which means that the output width is the full terminal width. The--width
/-w
command line switches are added to supersede the value of the configuration option. (fix issue #359 with contribution from Anaïs Gaertner) - Doc: add a Get Modules section in Installing Modules on Unix document to provide download links for Modules' sources. (fix issue #387)
Modules 4.6.1 (2020-11-14)¶
- Lib: implement
initStateClockSeconds
as a Tcl command in libtclenvmodules to provide an optimized way to retrieve current Epoch time. - Lib: implement
parseDateTimeArg
as a Tcl command in libtclenvmodules to provide an optimized way to convert a datetime string into an Epoch time. - When full module specification is equal to
@
, raise an error as no module name is provided. (fix issue #362) - Optimize internal recording of hidden module and tag specification when parsing modulerc files in order to reduce the time taken to test if a given module is hidden or if a given tag applies to it.
- Script: add the ability to select the benchmark test to perform on mb utility.
- Doc: add Use new features without breaking old module command cookbook recipe
- Doc: rework option description for
module-hide
andmodule-forbid
commands in modulefile document. - Doc: describe in Changes between versions document that shell special characters like backticks are escaped when used in values starting Modules 4.0. (fix issue #365)
- Doc: make the ENVIRONMENT section from modulefile man page point to the ENVIRONMENT section of module man page.
- Fix
clear
sub-command to unset theMODULES_LMSOURCESH
environment variable. (fix issue #367) - Correctly return on
avail
sub-command a symbolic version defined in a global RC file when specifically searched. (fix issue #368) - Fix module hiding resolution for symbolic versions defined in a global RC
file when
module-hide
statements are set in the modulepath where the modulefiles targeted by these symbols are located. (fix issue #369) - When a module fails to unload during a
purge
sub-command, preserve loaded the modules it requires to keep environment consistent. (fix issue #370) - Doc: add Hide and forbid modules cookbook recipe.
Modules 4.6.0 (2020-09-16)¶
- Rework internal state handling to gather all state definitions in a global
array and use the same initialization and retrieval procedure, named
getState
, for all these states. - Add the
setState
,unsetState
,lappendState
,isStateDefined
andisStateEqual
procedures to provide unified ways to set or check the value of state. - Introduce the
sh-to-mod
sub-command, to evaluate shell script and determine the environment changes it does. Corresponding modulefile content is outputted as a result. Changes on environment variables, shell aliases, shell functions and current working directory are tracked. The following shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish. - Doc: add Source shell script in modulefile design notes.
- Introduce the
source-sh
modulefile command, to evaluate shell script and apply resulting environment changes through modulefile commands. When a modulefile usingsource-sh
modulefile command is loaded, the modulefile commands resulting from shell script evaluation are recorded in theMODULES_LMSOURCESH
environment variable to be able to undo these environment changes when modulefile is unloaded and to report the modulefile commands used when modulefile is displayed. The same kind of environment changes than thesh-to-mod
sub-command are tracked. The same list of shells thansh-to-mod
sub-command are supported. (fix issue #346) - Doc: add Source shell script in modulefile cookbook recipe.
- Doc: embed new Modules logo on website, online README and documentation portal.
- Install: disable by default the build of Modules compatibility version. From
now on, option
--enable-compat-version
has to be set to trigger this build. - Introduce the
username
sub-command to themodule-info
modulefile command to get the username of the user currently runningmodulecmd.tcl
or to test a string passed as argument corresponds to this username. - Introduce the
usergroups
sub-command to themodule-info
modulefile command to get all the groups of the user currently runningmodulecmd.tcl
or to test a string passed as argument corresponds to one of these groups. - Doc: improve markup of Release notes and New features documents starting from this 4.6 version to enable references to module sub-commands, command line switches, environment variables and modulefile Tcl commands.
- Use inclusive terminology to eliminate master and slave terms as much as possible from code source and documentation.
- Doc: use a versioned magic cookie in examples that demonstrate new modulefile features. (fix issue #349)
- Introduce the
--enable-multilib-support
configure option to add mechanism inmodulecmd.tcl
to look at an alternative location to find the Modules Tcl extension library in case this library cannot be found at its main location. - Lib: remove fetch_hidden argument from
getFilesInDirectory
procedure of Modules Tcl extension library. - Doc: add Hide or forbid modulefile design notes.
- Add the
module-hide
modulefile command, to dynamically hide modulefile, module alias or symbolic version matching passed specification. When hidden, a modulefile, an alias or a symbolic version is not reported nor selected unless referred by its exact name, like for module whose name or version starts with a dot character.module-hide
supports the advanced module version specifiers. (fix issue #202) - Add option
--soft
to themodule-hide
modulefile command to introduce a soften level of camouflage: modules targeted by such hide directive are made visible as soon as their root name is part of search query. - Add option
--hard
to themodule-hide
modulefile command to introduce a hardened level of camouflage: modules targeted by such hide directive keep being hidden even if they are fully matched by search query. - Do not report among
whatis
search result the modulefiles with version name prefixed by a dot character and targeted by a symbolic version unless if they are precisely searched. - When a loading module has hidden alternative names (hidden due to their
name or version starting with a dot character or because they match a
module-hide
statement), these alternative names are not recorded in environment unless if they are not hard-hidden and if they have been used in query to select loading module. - On
avail
sub-command, remove hidden symbolic versions from the list to display along modulefile or directory they target, unless these symbols are not hard-hidden and are used in query to search modules. - When the
--default
filter ofavail
sub-command is set, unhide all the default symbolic versions or modules targeted by these symbols unless if they are hard-hidden. - Define the default and latest automatic symbolic versions only if relative module name matches search query to ensure all elements for this module have been processed prior assigning the symbols.
- In case a symbolic version is transitively applied toward a modulefile, like
for instance when this symbol is first set onto a directory, record the
resolution of each transitively applied symbol. By doing so, a module
load
tentative using the transitively applied symbolic version will now correctly resolve to the modulefile targeted by symbol. - Fix use of the advanced version specifiers in arguments to the
is-avail
modulefile command. - Introduce the
--all
/-a
option foravail
,aliases
,whatis
andsearch
sub-commands, to include in the search process all hidden modulefiles, module aliases or symbolic versions. Hard-hidden modules stay hidden even if--all
/-a
option is used. - Add the
module-forbid
modulefile command, to dynamically forbid evaluation of modulefile matching passed specification. When forbidden, a module cannot be loaded and an access error is obtained when trying to evaluate them.module-forbid
supports the advanced module version specifiers. - Add
--not-user
and--not-group
options tomodule-hide
andmodule-forbid
modulefile commands to ignore hiding or forbidding definition if current user is respectively part of specified username list or member of one of specified group list. - Add
--before
and--after
options tomodule-hide
andmodule-forbid
modulefile commands to ignore hiding or forbidding definition respectively after and before a specified date time. Accepted date time format isYYYY-MM-DD[THH:MM]
. - Add
--message
option tomodule-forbid
modulefile command to supplement the error message obtained when trying to evaluate a forbidden module. - When a module that will soon be forbidden (as the date limit specified on
the
--after
option of a matchingmodule-forbid
command is near) is evaluated, warn user this module access will soon be denied. - The range of time the above warning appears can be controlled with the
nearly_forbidden_days
configuration option, whose value equals to the number of days prior the module starts to be forbidden. This configuration is set to14
(days) by default and this value can be controlled atconfigure
time with--with-nearly-forbidden-days
option. When thenearly_forbidden_days
configuration is set through theconfig
sub-command, theMODULES_NEARLY_FORBIDDEN_DAYS
environment variable is set. - Add
--nearly-message
option tomodule-forbid
modulefile command to supplement the warning message obtained when evaluating a nearly forbidden module. - Add the
debug2
verbosity level, to report each call ofmodulecmd.tcl
internal procedures in addition to debug messages. Debug2 mode can be enabled by setting theverbosity
config to thedebug2
value or by using the-D
command-line switch twice. - Install: look for
make
rathergmake
on MinGW and build library with a.dll
extension on this platform. - Add the
trace
verbosity level, to report details on module searches, resolutions, selections and evaluations. Trace mode can be enabled by setting theverbosity
config to thetrace
value or by using the-T
/--trace
command-line switches. - Introduce the
tr
key in the color palette to specifically render trace messages. Default value fortr
key is2
(decreased intensity). - When trying to set an environment variable to an empty value on the Windows platform, unset this environment variable instead to cope with the underlying OS behavior.
Modules 4.5.3 (2020-08-31)¶
- Install: take into account the
--build
,--host
,--target
,--enable-dependency-tracking
and--disable-dependency-tracking
configure options to transmit them to theconfigure
scripts of Modules Tcl extension library and Modules compatibility version. (fix issue #354) - Install: ignore some regular options of an Autoconf
configure
script that are useless for this project but usually implied in build macros (like RPM%configure
macro). - Install: ignore unsupported
--enable-*
and--with-*
options onconfigure
script rather raise an error and add support to define environment variable and build system type asconfigure
script arguments to comply with GNU configuration recommendations. - Install: fix
modulecmd
pre-alternatives check in RPM spec file. - Install: use
%make_build
and%make_install
macros in RPM spec file. - When
module switch
command is used in modulefile, do not state when processing it a conflict over switched-off module if its specification on themodule switch
command also matches switched-on module's specification. Allow this way the replacement of any loaded version of a module for a specific one required by currently loading module. (fix issue #355) - Correctly report failed attempts to load module requirements expressed with advanced version specifiers. (fix issue #356)
Modules 4.5.2 (2020-07-30)¶
- Init:
list
andsource
sub-commands do not take available modules as argument in fish completion script. - Init: fix option list for
search
sub-command in bash completion script. - Fix double error counter increase when modulefile evaluation breaks.
- Install: adapt
configure
script to pass to theconfigure
script of Modules compatibility version only a subset of the options it supports (most commonly used options). - Install: raise an error when an unknown option is passed to
configure
script rather silently ignore it. (fix issue #348) - Install: enable the definition of installation directory options of
configure
script with the--option value
syntax in addition to the--option=value
syntax. (fix issue #348) - Doc: alphabetically sort sub-commands of
module-info
modulefile Tcl command in modulefile document. - Script: clean previously built environment-modules RPMs in mrel.
- Clearly separate quarantine variable definition from tclsh binary on
modulecmd.tcl
evaluated command call in_module_raw
function for sh, bash, ksh and zsh shells. (fix issue #350) - Doc: clarify in documentation index that Environment Modules should not be confused with language-specific modules. (contribution from Rob Hurt)
- Adapt conflict detection tests to ensure a module loaded by its full pathname will not detect itself as a conflict when declaring a reflexive conflict. (fix issue #352)
- Adapt the mrel and mpub commands to produce new Modules release from a vZ.Y.x git branch rather than from the repository main branch.
Modules 4.5.1 (2020-06-01)¶
- Install: consistently output Makefile warning messages on stderr.
- Script: add the
mrel
script, that automates build of the Modules release files and performs tests over these distribution files to guaranty their correctness. - Script: add the
mpub
script, that automates Modules new release publishing over git repositories and websites. - Install: remove project-specific tools from git repository export thus from release distribution files.
- Disable pager when
clear
sub-command is called fromml
shortcut command. (fix issue #338) - In case a modulefile evaluation fails, environment context prior this failed
evaluation is restored. Fix environment variable restoration mechanism to
keep the link that monitors and updates environment variable array
env
in every Tcl sub-interpreters. (fix issue #340) - Ensure environment variable change at the Tcl interpreter level is propagated to every sub-interpreters used to evaluate modulefiles or modulercs. (fix issue #342)
- Use absolute path to load Modules Tcl extension library. (fix issue #344 with contribution from Roy Storey)
- Fix formatting of error stack trace not to look for internal commands to withdraw if start-up stack pattern cannot be matched.
Modules 4.5.0 (2020-04-07)¶
- Doc: fix typos and grammar mistakes on module, modulefile and Changes between versions documents. (contribution from Colin Marquardt)
- Doc: update cookbook recipes to highlight code of the Tcl scripts included. (contribution from Colin Marquardt)
- Doc: improve markup of module, modulefile and Changes between versions documents to enable references to module sub-commands, command line switches, environment variables and modulefile Tcl commands. (contribution from Colin Marquardt)
- Doc: alphabetically sort module sub-commands, command-line switches, environment variables and modulefile Tcl commands in module and modulefile documents.
- Introduce the
ml
command, a handy frontend to themodule
command.ml
reduces the number of characters to type to triggermodule
. With no argumentml
is equivalent tomodule list
,ml mod
corresponds tomodule load mod
andml -mod
meansmodule unload mod
. Multiple modules to either load or unload can be combined on a single command.ml
accepts all command-line switches and sub-commands accepted bymodule
command.ml
command is defined by default. Its definition can be controlled at./configure
time with--enable-ml
option or later on withml
configuration option (which definesMODULES_ML
environment variable when set). - Fix module sub-command abbreviation match to ensure passed abbreviated
form fully match sub-command, not only its minimal abbreviated form. As an
example,
lod
orloda
do not match anymore theload
sub-command,lo
orloa
still do. - Add the
-j
/--json
command line switches to theavail
,list
,savelist
,whatis
andsearch
module sub-commands to render their output in JSON format. (fix issue #303) - Script: remove need to build project management-specific tools
(
mtreview
,mb
,mlprof
andplaydemo
) prior using them. - Script: gather all distributed and maintained scripts in a
script
directory at the root of the project repository tree. - Install: provide Windows-specific batch files when
./configure
option--enable-windows-support
is set. module command wrappermodule.cmd
is installed inbindir
and initialization scriptcmd.cmd
ininitdir
. Those batch files are relocatable and expectmodulecmd.tcl
in..\libexec
directory. (fix issue #272 with contribution from Jacques Raphanel) - Install: add ml command wrapper
ml.cmd
and install it inbindir
when./configure
option--enable-windows-support
is set. - Install: introduce envml command wrapper
envml.cmd
for Windowscmd
shell and install it inbindir
when./configure
option--enable-windows-support
is set. (contribution from Jacques Raphanel) - Doc: improve documentation portal index.
- Install: add
dist-win
target to Makefile in order to build a distribution zipball containing the required files to run Modules on a Windows platform.INSTALL.bat
andUNINSTALL.bat
Windows batch files are introduced and shipped in the zipball to automate installation and basic configuration of Modules on the Windows platform. - Doc: update Installing Modules on Windows document to describe how to install Modules with newly provided Windows-specific distribution zipball.
- Install: enable build of Modules from
git archive
tarball or zipball exports (like download source archives automatically provided on GitHub project) - Install: ship reStructuredText and MarkDown source documents at the root of Modules distribution tarball rather their built txt counterpart.
- Script: fix
createmodule.sh
script to correctly analyses environment when shell functions are found defined in it. - Script: inhibit output generated by scripts evaluated by
createmodule.sh
andcreatemodule.py
to ensure these outputs will not get in the way when analyzing the environment changes. (fix issue #309) - Correctly handle symbolic version target including a whitespace in their name.
- Testsuite: output test error details whatever the testsuite run verbose mode.
- Install: adapt configure script and Makefile to detect
python
command location and set it as shebang forcreatemodule.py
andgitlog2changelog.py
. Ifpython
command is not found,python3
thenpython2
are searched. - Install: enable to pass a specific Python interpreter command name or
location at configure step with
--with-python
option. Specified command name or location should be found on build system only if building from git repository. - Install: build
createmodule.py
script and install it inbindir
. - Install: update RPM spec file to explicitly define Python interpreter location.
- Script: fix
createmodule.py
script for Python3 (fix issue #315 with contribution from Armin Wehrfritz) - Lift Perl variable strictness when defining
_mlstatus
variable in casemodulecmd.tcl
output is directly evaluated without use of themodule
sub-routine in Perl script. (with contribution from Andrey Maslennikov) - Script: fix path de-duplication in
createmodule.sh
. (fix issue #316) - Doc: add Handling Compiler and other Package Dependencies cookbook recipe, which discusses various strategies for creating modulefiles for packages with multiple builds depending on previously loaded compiler, MPI libraries, etc. (contribution from Tom Payerle)
- Init: test availability of
compopt
Bash builtin prior using it in Bash completion script to avoid error with versions of this shell older than 4.0. (fix issue #318) - Install: adapt configure step to detect if
sed
option-E
is supported and fallback to-r
otherwise in shell completion scripts. (fix issue #317) - Add support for the
NO_COLOR
environment variable (https://no-color.org/) which when set (regardless of its value) prevents the addition of ANSI color. When set,NO_COLOR
prevails overCLICOLOR
andCLICOLOR_FORCE
environment variables.MODULES_COLOR
overrides these three variables. (fix issue #310) - Script: when analyzing environment variable changes in
createmodule.sh
applied by shell script passed as argument, produce asetenv
modulefile statement for any variable found set prior script evaluation and for which value is completely changed after script evaluation. (fix issue #320) - When an error message is composed of multiple lines, render it in the same way whether it is part of a block message or not: lines after the first one are prepended with a 2-space padding. As a result error messages appear clearly separated from each other.
- Append to the error message the error stack trace when a general unknown
error occurs in
modulecmd.tcl
and provide a link to encourage users to report such error to the GitHub project. - Add to the error message the error stack trace for errors occurring during
site-specific configuration evaluation. Error stack is expunged from the
modulecmd.tcl
internals to only report information relevant to site-specific configuration file. - When an error occurs during the evaluation of a modulefile or a modulerc,
report associated error stack trace expunged from
modulecmd.tcl
internal references to only output useful information for users. - GitHub: add issue templates to guide people submitting a bug report or a feature request.
- Doc: provide a link toward issues that have been fixed between versions 3.2 and 4.0 in Changes between versions document.
- Script: introduce
envml.cmd
script for Windows platform providing similar behavior thanenvml
Bash script. (contribution from Jacques Raphanel) - Init: add Bash shell completion for the
ml
command. (contribution from Adrien Cotte) - Fix Fish shell stderr redirection for newer Fish versions. (fix issue #325)
- Correctly handle modulefiles and modulepaths containing a space character in their name whether they are used from the command-line, in collections, within modulefiles or from loaded environment definitions.
- Doc: add Default and latest version specifiers design note.
- An
avail
search over a symbolic version targeting a directory now correctly returns the special modules (alias and virtual module) lying in this directory. (fix issue #327) whatis
andpaths
searches only return special modules (symbolic version, alias and virtual modules) that fully match search query, not those that partially match it. (fix issue #328)- alias and virtual module whose name mention a directory that does not exists are correctly handled. (fix issue #168)
- Hide special modules (aliases, symbolic versions and virtual modules)
whose version name starts with a dot character (
.
) fromavail
,whatis
andpaths
searches if their query does not fully match special module name. (fix issue #329) - Filter-out from the output of the
aliases
sub-command all hidden aliases, symbolic versions or hidden modules targeted by a non-hidden symbolic version. (fix issue #330) - Enable resolution of default module in module sub-directory when this default symbol targets a hidden directory (whose name starts with a dot character). (fix issue #331)
- Doc: clarify hidden module location in modulefile man page.
- Install: define
LD_PRELOAD
as quarantine var along withLD_LIBRARY_PATH
in RPM specfile. - When
implicit_default
andadvanced_version_spec
configuration are enabled, automatically define adefault
andlatest
symbolic version for each module name (at each module depth for deep modules) if those version names does not already exist. (fix issue #210) - Once a module is loaded, the automatically defined symbols associated to it
are recorded in loaded environment in the
MODULES_LMALTNAME
environment variable. They are distinguished from the other alternative names applying to the module by aas|
prefix, which qualifies their auto symbol type. - When an advanced version specifier list contains symbolic version references, fix resolving to honor default version if part of the specified list. (fix issue #334)
Modules 4.4.1 (2020-01-03)¶
- Fix error and warning messages relative to dependency management to enclose dependency specification in single quotes to clearly distinguish specification from each other.
- Skip output of module loading message if module is already loaded.
- Doc: add demonstration material played at SC19 to promote the new features of Modules.
- Contrib: add
playdemo
script to play recorded demonstration cast. - Doc: add a web anchor to each modulefile Tcl command, module sub-command and module environment variable documentation.
- Install: update RPM spec file to enable build on
el8
. - Doc: fix RST syntax for bullet lists in design docs. (fix issue #306)
- In case
module avail
query does not match a directory but only its contained elements (for instancemodule av mod/7
matchesmod/7.1
andmod/7.2
but notmod/
), fix query processing to correctly return latest or default element in case--latest
or--default
flags are set. - In case a
module avail
query performed in a no-indepth mode with--latest
or--default
flags either enabled or disabled, fix query processing to return directory elements if they are part of result. - When a
module avail
query performed in no-indepth mode targets a virtual module, fix result to filter-out the directory holding the virtual module from result. - Fix
module avail --default
queries when modulefile default version does not match query: select latest version from modulefiles matching query unlessimplicit_default
configuration is disabled in which case no default version is returned. - Improve highlighting of module
avail
andwhatis
search result by coloring module names matching search query expressed with the advanced version specifiers.name@1,3
orname@1:3
queries now highlightname/1
andname/3
strings found in search result. - Contrib: add the
mlprof
script which wrapsmodulecmd.tcl
to collect profiling information on its execution. - Contrib: adapt
mb
script to profilemodulecmd.tcl
run tests rather bench them whenprofile
argument is passed to the script. - Improve overall performances of module names and versions comparison by introducing optimized procedures and caching in memory module search results.
Modules 4.4.0 (2019-11-17)¶
- Doc: add Return file basename on module-info name for full path modulefile recipe to cookbook. (fix issue #297)
- Rework internal handling of configuration options to gather all option
definitions in a global array and use the same initialization and retrieval
procedure, named
getConf
, for all these options. - Add the
setConf
,unsetConf
andlappendConf
procedures to provide unified ways to set the value of configuration option. These procedures should be used in site configuration files to override configuration option value instead of directly setting corresponding option variable as it was done in previous Modules releases. - Add the ability to match module specification in a case insensitive manner.
Default case sensitiveness behavior is set at
./configure
time with the--with-icase
option. It could be superseded with theMODULES_ICASE
environment variable, that could be set withconfig
module sub-command through theicase
option. Command-line switch--icase
(-i
) enables to supersede defined case sensitiveness configuration. (fix issue #212 with contribution from Eric Deveaud) - Introduce the extended default mechanism, to help selecting a module when
only the first numbers in its version are specified. Starting portion of the
version, part separated from the rest of the version string by a
.
character, will get matched to the appropriate complete version name. In case multiple versions match partial version specified and only one module should be returned, default version (implicit or explicit) among matches is returned. In caseimplicit_default
option is disabled and no explicit default is found among matches, an error is returned. This mechanism is enabled through a new configuration option namedextended_default
(which definesMODULES_EXTENDED_DEFAULT
environment variable when set). It may be enabled by default inmodulecmd.tcl
script with option--enable-extended-default
passed to the./configure
script. - Introduce the advanced module version specifiers mechanism to specify finer
constraints on module version. This new feature enables to filter the module
selection to a given version list or range by specifying after the module
name a version constraint prefixed by the
@
character. It leverages the version specifier syntax of the Spack package manager. A single version can be specified with the@version
syntax, a list of versions with@version1,version2,...
, a greater than or equal to range with@version1:
syntax, a less than or equal to range with@:version2
and an in between or equal to range with@version1:version2
syntax. In caseimplicit_default
option is disabled and no explicit default is found among version specifier matches, an error is returned. This mechanism is enabled through a new configuration option namedadvanced_version_spec
(which definesMODULES_ADVANCED_VERSION_SPEC
environment variable when set). It may be enabled by default inmodulecmd.tcl
script with option--enable-advanced-version-spec
passed to the./configure
script. - Conflict defined with a generic module name or an advanced version specifier may match multiple loaded modules (generally in case multiple loaded modules share same root name). Loaded environment analysis has been fixed to bind conflict to all loaded modules matching it. As a result the Dependent Reload mechanism is not triggered when one loaded module matching conflict is removed if another loaded module still match the conflict.
- Doc: add Module selection contexts, Insensitive case, Extended default and Advanced module version specifiers design notes.
- Make
MODULESHOME
environment variable controllable through theconfig
sub-command withhome
configuration option. A--with-moduleshome
argument is also added to the ./configure script to set specific default value for this option at installation time. (fix issue #292)
Modules 4.3.1 (2019-09-21)¶
- Contrib: add
mb
script to bench Modules versions. - Correct
modulecmd.tcl
script startup to correctly report error in case Tcl extension library fails to load. (fix issue #284) - Install: fix typo on
CFLAGS
definition inlib/Makefile
. (fix issue #287 with contribution from Felix Neumärker) - Remove useless code in Modules Tcl extension library
- Make URLs in README correctly rendered in HTML. (contribution from Per Persson)
- Doc: clarify modulefile evaluation modes in modulefile.4 man page. (fix issue #289)
- When looking at the closest match among loaded modules when switching module with just a single module argument specified, load the information on the currently set environment to get the alternative names of loaded modules prior to look at closest module match. (fix issue #290)
- Doc: describe the way to determine the site-specific configuration script location in cookbook recipes implying the installation of such a file. (fix issue #266)
- Doc: add Log module command recipe to cookbook. (fix issue #283)
- Doc: add Expose procedures and variables to modulefiles recipe to cookbook.
- Doc: add Make defined modulepaths persist over sudo recipe to cookbook.
- Doc: add Ensure user fully qualify the modules they use recipe to cookbook.
- Introduce the
wa_277
configuration option to workaround an issue with Tcsh history mechanism. Defaultmodule
alias definition for Tcsh hits an issue with shell history mechanism: erroneous history entries are recorded each time themodule
command is called. Whenwa_277
option is enabled (which sets theMODULES_WA_277
environment variable to 1), an alternative module alias is defined which fixes the history mechanism issue. However the alternative definition of the module alias weakens shell evaluation of the code produced by modulefiles. Characters with special meaning for Tcsh shell (like { and }) may not be used anymore in shell alias definition elsewhere the evaluation of the code produced by modulefiles will return a syntax error. (fix issue #277) - Doc: add Tips for Code Reuse in Modulefiles recipe to cookbook. (contribution from Tom Payerle)
- Fix the
whatis
andpaths
sub-command results for module symbolic versions targeting a directory whenimplicit_default
configuration option is disabled. No error is returned and same result is now obtained whether the symbolic name or its target is used as argument for those two sub-commands. (fix issue #294) - Fix the
whatis
andpaths
sub-command results for module aliases targeting a directory whenimplicit_default
configuration option is disabled. No error is returned and same result is now obtained whether the alias name or its target is used as argument for those two sub-commands. (fix issue #295) - Rework all the ternary operator expressions in
modulecmd.tcl
that may result in a nan value (whatever the case used to write this string) as theexpr
Tcl command raises an error when it returns such a value, which breaks Modules as soon as a modulefile, an alias or a symbolic version is named nan. (fix issue #296)
Modules 4.3.0 (2019-07-26)¶
- Introduce Vim addon files to highlight the modulefile syntax. Installation
of these files, which is enabled by default, is controlled by the
--enable-vim-addons
and--vimdatadir
configure options. (contribution from Felix Neumärker) - If modulefile is fully read, cache the content read and the file header computed to avoid another file read if the same modulefile need to be read multiple times.
- Except for path, paths, list, avail and aliases module commands always fully read a modulefile whether its full content is needed or just its header to verify its validity. Proceed this way to only read file once on commands that first just check modulefile validity then read again valid files to get their full content.
- Introduce Modules Tcl extension library (written in C) to extend Tcl language in order to provide more optimized I/O commands to read a file or a directory content than native Tcl commands do.
- Install: add
--libdir
,--enable-libtclenvmodules
,--with-tcl
and--with-tclinclude
options to configure script to control libtclenvmodules build and installation. - When an error is caught during modulecmd.tcl first initialization steps, ensure the error report facility is initialized to render error message.
- When looking for modulefiles in enabled modulepaths, take
.modulerc
file found at the root of a modulepath directory into account. Which means these rc files are now evaluated like global rc files and can be used to define module aliases targeting modulefiles stored in the underlying file tree. - Correctly get available default (-d) and latest (-L) version whether search
pattern is passed with an ending forward slash character or not or if it
contains a
*
wildcard character. - Append a forward slash character to any directory result of an avail command to better distinguish these directories from regular files.
- Introduce the ability to control whether
avail
command search results should recursively include or not modulefiles from directories matching search query by use of the--indepth
and--no-indepth
command-line switches or the environment variableMODULES_AVAIL_INDEPTH
. Default behavior is set at the./configure
time with the--enable-avail-indepth
and--disable-avail-indepth
switches. (fix issue #150) - Update
bash
,fish
andzsh
completion scripts to propose available modulefiles in the no in depth mode. - Add the ability to graphically enhance some part of the produced output to
improve readability by the use of the
--color
command-line switch or theMODULES_COLOR
environment variable. Both accept the following values:never
,auto
andalways
. When color mode is set toauto
, output is colored if stderr is attached to a terminal. Default color mode could be controlled at configure time with the--enable-color
and the--disable-color
option, which respectively correspond to theauto
andnever
color mode. - Control the color to apply to each element with the
MODULES_COLORS
environment variable or the--with-dark-background-colors
and--with-light-background-colors
configure options. These variable and options take as value a colon-separated list in the same fashionLS_COLORS
does. In this list, each element that should be highlighted is associated to a Select Graphic Rendition (SGR) code. - Inform Modules of the terminal background color with the
MODULES_TERM_BACKGROUND
environment variable or the--with-terminal-background
configure option, which helps to determine if either the dark or light background colors should be used to color output in case no specific color set is defined with theMODULES_COLORS
. - Color prefix tag of debug, error, warning, module error and info messages.
- Highlight the modulefile or collection name when reporting messages for a an action made over this modulefile or collection.
- Color the modulepaths reported on a
use
command. - Highlight title of separator lines or column name of table header.
- Color modulepaths, directories, aliases and symbols reported by the
avail
,aliases
,list
,whatis
andsearch
commands. - When color mode is enabled and module aliases are colored, do not associate
them a
@
tag as the color already distinguish them from regular modulefile. - When color mode is enabled and a Select Graphic Rendition (SGR) code is set
for the
default
modulefile symbol, apply this SGR code to the modulefile name instead of associating it thedefault
symbol tag. - Highlight matched module search query string among
avail
,whatis
andsearch
command results. - Highlight the modulefile and collection full path name on
display
,help
,test
andsaveshow
command reports. - Color modulefile Tcl commands set in a modulefile on a
display
command report. - Color module commands set in a collection on a
saveshow
command report. - Re-introduce
clear
sub-command. (fix issue #203) - Leverage
--force
command-line switch onclear
sub-command to skip confirmation dialog. (fix issue #268) - Init: improve readability of variable definition operations by writing one
definition operation per line rather having multiple commands on a single
line like
VAR=val; export VAR
. (fix issue #225) - Add the ability to define a site-specific configuration file with an
environment variable:
MODULES_SITECONFIG
. When set, the script file pointed by the variable is sourced (if readable) after the site-specific configuration file initially defined inmodulecmd.tcl
. (contribution from Ben Bowers, fix issue #234) - Doc: add description in the module.1 man page of
MODULERCFILE
in the environment section andsiteconfig.tcl
in the files section. - Install: provide at installation time a bare site-specific configuration
script in designated
etcdir
if no pre-existingsiteconfig.tcl
file is found at designated location. - Introduce the
config
sub-command to get and setmodulecmd.tcl
options and to report its current state. - Contrib: update
createmodule.py
script to support execution from the cmd shell. (contribution from Jacques Raphanel, fix issue #270) - Add the ability to configure when unloading a module and multiple loaded
modules match request if firstly loaded module should be chosen or lastly
loaded module. Configure option
--with-unload-match-order
defines this setting which can be superseded with theMODULES_UNLOAD_MATCH_ORDER
environment variable. This variable can be set with the optionunload_match_order
on theconfig
sub-command. By default, lastly loaded module is selected. It is recommended to keep this behavior when the modulefiles used express dependencies between each other. - Add the ability to configure whether an implicit default version should be
defined for modules with no default version explicitly defined. When
enabled, which stays the default behavior, a module version is automatically
selected (latest one) when the generic name of the module is passed. When
implicit default selection is disabled, the name of modules to evaluate
should be fully qualified elsewhere an error is returned. This option is set
at
./configure
time with the--enable-implicit-default
and--disable-implicit-default
options. It could be superseded with theMODULES_IMPLICIT_DEFAULT
environment variable, that could be set withconfig
module sub-command through theimplicit_default
option. - Install: add to the configure script the
--with-locked-configs
option to ignore environment variable superseding of Modules configurations defined inmodulecmd.tcl
script. Lockable configuration option areextra_siteconfig
andimplicit_default
. Currently locked options are reported through thelocked_configs
option on theconfig
sub-command. - Introduce the ability to control the module search match. Search query
string should match module name start or any part of module fully qualified
name. Default search match behavior is set at
./configure
time with the--with-search-match
option. It could be superseded with theMODULES_SEARCH_MATCH
environment variable, that could be set withconfig
module sub-command through thesearch_match
option. Command-line switches--starts-with
(-S
) and--contains
(-C
) foravail
module sub-command enable to supersede defined search match configuration. - Introduce the ability not to set the shell startup file that ensure
module
command is defined once shell has been initialized. Setting shell startup file currently means definingENV
andBASH_ENV
environment variables to the Modules bourne shell initialization script../configure
options--enable-set-shell-startup
and--disable-set-shell-startup
define if shell startup should be set or not by default. It could be superseded with theMODULES_SET_SHELL_STARTUP
environment variable, that could be set withconfig
module sub-command through theset_shell_startup
option. - Cookbook: add the test-modulefiles recipe. (fix issue #182 with contribution from Colin Marquardt)
- Fix location of global RC file to
@etcdir@/rc
instead of@prefix@/etc/rc
to cope with@etcdir@
specific setup (@etcdir@
defaults to@prefix@/etc
). - Take into account Modules initialization configurations found in
etc
directory if they exist rather ininit
directory. Ifinitrc
configuration file is found inetcdir
then it is preferred overmodulerc
file ininitdir
. Following the same trend,modulespath
configuration file is found inetcdir
then it is preferred over.modulespath
file ininitdir
. - Introduce the ability to install the Modules initialization configuration
files in the
etcdir
rather than in theinitdir
. A new configure option is introduced for this task:--with-initconf-in
. Accepted values for this option are:etcdir
orinitdir
(default). - Add the
--enable-modulespath
configure option, which is an alias for the--enable-dotmodulespath
option as.modulespath
configuration file is namedmodulespath
when installed inetcdic
. - Install: update RPM spec file to disable
set_shell_startup
option by default, set/etc/environment-modules
as configuration directory and store Modules initialization configuration files in it. - Report an error when a module load or unload evaluation aborts due to the
use of the
break
orexit
modulefile commands. This error notification clarifies that module evaluation failed. (fix issue #267) - Remove the message block display output for the
reload
,purge
andrestore
sub-commands to preserve this output style for modulefile evaluation modes (load, unload and switch) and thus clarify understanding. - When unloading a module that contains a
module load
ormodule switch
modulefile command, inhibit the unload performed of the useless requirement when auto_handling mode is disabled if currently performing apurge
,reload
orrestore
sub-command. As the unload sequence is determined and managed from these top commands. - Add ability to control module command message verbosity with configuration
option. Introduced verbosity levels from the least to the most verbose are
silent
,concise
,normal
,verbose
anddebug
. This option could be set at./configure
time with--with-verbosity
option. It could be superseded with theMODULES_VERBOSITY
environment variable, that could be set withconfig
module sub-command through theverbosity
option. Silent, verbose and debug verbosity modes can be set at the command-line level respectively with--silent
/-s
,--verbose
/-v
and--debug
/-D
command-line switches. (fix issue #204) - When verbosity level is
normal
or higher, reports every module loads or unloads performed torestore
a collection orsource
a scriptfile, even if there is no specific message to output for these module evaluations. Clarifies what module evaluations have been triggered by these sub-commands. - Also honor the
CLICOLOR
andCLICOLOR_FORCE
environment variables to define color mode. (fix issue #279)
Modules 4.2.5 (2019-07-08)¶
- Correctly escape
?
character in shell alias. (fix issue #275) - When resolving the enabled list of modulepaths, ensure resolved path entries are unique. (fix issue #274)
- Right trim '#' characters from the fetched modulefile magic cookie string
to ensure a correct compatibility version comparison. Useful when modulefile
first line is equal to
#%Module4.2##############
. - Fix argument parsing for the
append-path
,prepend-path
andremove-path
modulefile commands to consider every arguments found after the variable name as variable values and not command option even if argument starts with-
character. (fix issue #278) - Fix automatic loading of modulefiles when multiple module names are set on a
single
module load
modulefile command. When auto_handling mode was disabled, the load of not loaded modules was not achieved as soon as some modules on this list were already loaded. (fix issue #281)
Modules 4.2.4 (2019-04-26)¶
- Better track each module evaluation and the context associated to it in order to report a more accurate information on the additional modules loaded or unloaded when proceeding the main evaluation request. (fix issue #244, #245, #246, #247 and #248)
- Doc: preserve quotes and dashes when making HTML docs. (fix issue #250 with contribution from Riccardo Coccioli)
- Fix hanging
list
sub-command when terminal width is equal to the single column text width to be printed. (contribution from Jesper Dahlberg) - During an additional evaluation triggered by an automated module handling mechanism, ensure warning and error messages are reported under the message block of the main evaluation. (fix issue #252)
- During the unload of a module when the automated module handling mode is disabled, report a warning message for each unload of a useless requirement that fails as done when the automated module handling mode is enabled. (fix issue #253)
- When multiple modules are listed on a
prereq
command, drop the output of those modules that fails to load (by the Requirement Load automated mechanism) to only keep the output of the module whose load succeed. (fix issue #254) - Fix
switch
sub-command when the switched-off module cannot be unloaded when other loaded modules depend on it. Whole switch process is failed and no load of the switched-on module is attempted. (fix issue #251) - When switching modules, report failure of switched-off module unload or switched-on module load under the message block of the switch action. A failed switched-off module unload is reported as an error, as it aborts the switch evaluation, whereas a failed switched-on module load is reported as a warning. (fix issue #255)
- When a module requirement is seen missing but the load of this module was attempted, report a more specific error or warning message to let user understand that the load of the requirement was attempted but failed. (fix issue #257)
- When loading a module, report any missing requirement on the message reporting block corresponding to this module load. This warning or error message comes in addition to the eventual Requirement Load message reported under the message block of the main evaluation. (fix issue #258)
- When unloading a module which has some dependent module still loaded, produce a more specific error or warning message if an evaluation of these dependent modules has been realized or if the unload of the required module is forced. (fix issue #259)
- When a conflicting module is seen loaded but the unload of this module was attempted, report a Conflict Unload error or warning message toward the main evaluation message block. (fix issue #261)
- When loading a module, report any loaded conflict on the message reporting block corresponding to this module load. This warning or error message comes in addition to the eventual Conflict Unload message reported under the message block of the main evaluation. (fix issue #261)
- Correctly report loading state of conflicting module. (fix issue #262)
- Adapt warning, error and info messages relative to the Dependent Reload mechanism to distinguish the unload phase from the load (reload) phase of this mechanism. In the automated module handling summary report, unloaded modules via this mechanism are reported in the Unloading dependent list and modules reloaded afterward are reported against the Reloading dependent list. (fix issue #263)
- When the automated module handling mode is disabled, do not attempt to load
a requirement expressed in a modulefile with a
module load
command, if this requirement is already loaded or loading. - Skip load or unload evaluation of a module whose respectively load or unload was already attempted but failed. If this second evaluation attempt occurs within the same main evaluation frame. (fix issue #264)
- When reloading modules through the Dependent Reload automated mechanism,
prevent modules to automatically load of other modules with the
module load
modulefile command, as it is done for theprereq
command. (fix issue #265) - Raise an error when an invalid option is set on
append-path
,prepend-path
orremove-path
modulefile command. (fix issue #249) - Zsh initializes by default the
MANPATH
environment variable to an empty value when it starts. To preservemanpath
system configuration even after addition to this variable by modulefiles, setMANPATH
variable to:
if found empty. (improve fix for issue #224) - Doc: provide a short installation guideline in README file. (fix issue #230)
Modules 4.2.3 (2019-03-23)¶
- Add all the module dependency-related internal information to those saved prior a modulefile evaluation in order to correctly restore internal state in case modulefile evaluation fails.
- Init: in shell initialization scripts, initialize
MANPATH
if not set with a value that preservesmanpath
system configuration even after addition of paths to this variable by modulefiles. (fix issue#224) - Enable to define an entire path entry to the
MODULEPATH
variable which corresponds to a variable reference only. (fix issue#223) - Cookbook: add the modulefiles-in-git recipe. (contribution from Scott Johnson)
- When
module switch
commands are found in modulefiles, track switched-off modulefile as a conflict and switched-to modulefile as a requirement to apply same behaviors than formodule load
andmodule unload
commands in modulefiles. Ifmodule switch
has only one argument, do not define a conflict toward switched-off modulefile. CAUTION: it is not recommended to use module switch command in modulefiles. (fix issue#229) - When unloading a module, revert
module switch
commands found in modulefile: switched-on module is converted to amodule unload
, like formodule load
command. Nothing is done for switched-off module, like formodule unload
command. (fix issue#226) - For default element in a modulefile directory which is a module alias that points to a modulefile, when this modulefile is loaded, it receives as alternative names the eventual module aliases set on the distant directory holding the alias pointing to it. (fix issue#231)
- When unloading a module that contains
module load
ormodule switch
commands in its modulefile, select for unload the automatically loaded requirement module which has been loaded prior its dependent. (fix issue#232) - Doc: describe Emacs settings useful for adhering to coding conventions in CONTRIBUTING guide. (fix issue #233 with contribution from Ben Bowers)
- When looking for a loaded or loading dependency requirement, select among the eventual multiple candidates the closest match to the dependent module.
- During the unload of a module, if the unload of one of its dependent (by the Dependent Unload mechanism) fails, abort the whole unload process. Exception made if the force mode is enabled. In this case failing module stays loaded and the Dependent Unload mechanism continues with next module to unload.
- During the unload of a module, if the unload of one of its useless requirements (by the Useless Requirement Unload mechanism) fails, keep the requirements of this failing module loaded. Such error is reported as a warning and it does not stop the whole unload process. (fix issue#240)
- During the load or the unload of a module, if the unload of one of its dependent (by the Dependent Reload mechanism) fails, abort the whole unload or load process. Exception made if the force mode is enabled. In this case failing module stays loaded and Dependent Reload mechanism continues with next module to unload. This failing module is removed from the Dependent Reload list, so it will not take part of the load phrase of the mechanism. (fix issue#239)
- During the load or the unload of a module, if the load of one of its
dependent (by the Dependent Reload mechanism) fails, abort the whole
unload or load process. Exception made if the force mode is enabled. In this
case failing module stays loaded and Dependent Reload mechanism continues
with next module to load. When the mechanism is applied during a
switch
command, force mode is enabled by default on the load phase. (fix issue#241) - When reloading all loaded modules with the
reload
sub-command, if one reloading module fails to unload or load, abort the whole reload process to preserve environment sanity. (fix issue#237) - During the unload of a module when the automated module handling mode is
disabled and this module declares its requirements with the
module load
modulefile command. If the unload of one of its useless requirements (by the Useless Requirement Unload mechanism) fails, whole unload process is not aborted and continue with next module to unload. (fix issue#238) - Contrib: add
mtreview
utility script that analyzes test suite log file to compare actual and expected output of failed test.mt
does not output the full test suite logs anymore but only the information produced bymtreview
on failed tests. - Install: exclude Continuous Integration configurations from dist tarballs.
Modules 4.2.2 (2019-02-17)¶
- Correct the Dependent Unload mechanism when it triggers the unload of 2 modules making together a requirement from another module. This module is now also added to the dependent modules to unload.
- Doc: add a cookbook section in the documentation and port there the 3 pre-existing recipes: inhibit-report-info, top-priority-values and unload-firstly-loaded.
- Doc: add a CONTRIBUTING guide.
- Doc: fix a typo on the Python initialization example in module man page.
- Doc: add a FAQ entry to describe the use of module from Makefile. (with contribution from Robert McLay)
- Trim any white-space, newline or
;
characters at the beginning or end of the function body passed to set-function modulefile command. - Init: add recognition of the
--auto
,--no-auto
and--force
command-line switches in fish shell completion script. - Init: add recognition of the
--auto
,--no-auto
,--force
,--paginate
and--no-pager
command-line switches in zsh shell completion script. - When the load of a modulefile is asked but a conflict is registered against this modulefile by an already loaded module, the load evaluation is now performed and the conflict is checked after this evaluation. If the conflict is still there, this evaluation (and the evaluation of its requirements) is rolled back. (fix issue#216)
- Init: fix
_module_not_yet_loaded
alias in tcsh completion script to handle situation whennoclobber
variable is set. Also ensure actualrm
command is called and not an alias. (fix issue#219) - Fix warning message when the load of a modulefile is forced over a reflexive conflict (message was reported twice).
- When looking at the dependency of a loaded module, only consider requirement loaded before dependent module (holding a prior position in the loaded module list) as valid. Those loaded after dependent module are considered as an unmet dependency thus they are not taking part in the Dependent Unload, the Useless Requirement Unload and the Dependent Reload mechanisms.
Modules 4.2.1 (2018-11-11)¶
- Cookbook: add the inhibit-report-info recipe.
- Cookbook: port unload-firstly-loaded and top-priority-values recipes to v4.2.
- Init: fix listing of loaded modules for fish and tcsh shell completions.
- Init: fix saved collection listing when no collection found for bash, zsh, tcsh and fish shell completions.
- Adapt
system
modulefile Tcl command to execute the command passed as argument through shell, like it is performed on compatibility version. (fix issue#205) - Correctly filter modulefile search memory cache entries when using a full search result to search later on a specific modulefile.
- Prefix debug messages by information on the current modulefile or modulerc interpreter if any.
- Init: fix listing of loaded modules on unload and switch sub-commands for bash shell completion.
- Refrain
module unload
modulefile command from unloading a module required by another loading module. - Enable
is-loaded
modulefile Tcl command in modulerc interpretation context, like done on compatibility version. (fix issue#207) - Check a required module is not already loading before attempting to load it. Helps to handle cyclic dependencies.
- Compute loaded modules requirement dependency relations without cycle and consider the module closing the cycle in a constraint violation state to avoid reloading loops on the Dependent Reload mechanism.
- Safely unset dependency reference when computing dependency relations as some dependencies expressed may target same module.
- Ensure a loaded module matching multiple entries of a same or
prereq
will just be considered as one module matching this requirement. - Init: quote prompt in csh and tcsh script with
:q
rather double quotes to accommodate prompts with embedded newlines. (fix issue#209 with contribution from Satya Mishra) - Init: skip shell environment alteration if
autoinit
command fails. (fix issue#208) - Reword path-like variable element counter reference handling to simply ignore the counter values not coherent with the content of related path-like variable. (fix issue#206)
Modules 4.2.0 (2018-10-18)¶
- Add
chdir
andputs
environment settings to the per-modulefile evaluation saved context. So previous values of these settings are restored in case of evaluation failure. - Fix save and restore of
x-resource
environment settings on the per-modulefile evaluation context. - Use the correct warning procedure to report the full reference counter
inconsistency message (so this message is fully inhibited during global
whatis
evaluations). - Make
append-path
,prepend-path
,remove-path
andunsetenv
commands alterenv
Tcl global array duringdisplay
,help
,test
orwhatis
evaluation modes. Thus an invalid argument passed to these commands will now raise error on these modes. (see Environment variable change through modulefile evaluation context section in MIGRATING document) - On
whatis
mode,append-path
,prepend-path
,remove-path
,setenv
andunsetenv
commands initialize variables if undefined but do not set them to their accurate value for performance concern. - Clear value instead of unsetting it during an unload mode evaluation of
setenv
or*-path
commands to avoid breaking later reference to the variable in modulefile. - Make
getenv
command returns value onhelp
,test
orwhatis
evaluation modes. (fix issue#188) - Add an argument to the
getenv
command to return the value of this argument if the queried variable is undefined. - Use a different modulefile interpreter for each evaluation mode.
- Adapt the procedure called for each modulefile command depending on the evaluation mode to adapt behavior of these commands to the module command currently running.
- Report calling name and arguments for modulefile commands on
display
mode. For the commands evaluated during this mode, trigger this report at the end of the evaluation. - Inhibit
chdir
,conflict
,module
,module-log
,module-trace
,module-user
,module-verbosity
,prereq
,set-alias
,system
,unset-alias
,x-resource
commands onhelp
,test
andwhatis
evaluation modes. - Ignore
chdir
,module
,module-trace
,module-verbosity
,module-user
andmodule-log
commands found during modulerc evaluation. - Correctly restore an empty string value on sub-interpreter global variables when sanitizing this interpreter between two modulefile/modulerc evaluations.
- Cache in memory results of a modulefile search to reuse it in case of rerun instead of re-walking the filesystem.
- Evaluate global rc files once module sub-command is known and registered, so it can be queried during their evaluation.
- Rename
_moduleraw
shell function in_module_raw
to use a common_module_
prefix for all module-related internal shell functions. - Install: add
--enable-append-binpath
and--enable-append-manpath
configure options to append rather prepend the bin or man directory when adding them to the relative environment variable. - Doc: clarify documentation for module usage on scripting language like Perl
or Python to mention that arguments to the
module
function should be passed as list and not as a single string. - When interpreting a
setenv
modulefile order during an unload evaluation, variable is still set to be unset in generated shell code but it is set to the value defined on thesetenv
order in the interpreter context instead of being cleared. - Register the conflicts defined by loaded modules in the environment
(variable
MODULES_LMCONFLICT
) and ensure they keep satisfied. (see Modulefile conflict constraints consistency section in MIGRATING document) - Register the prereqs defined by loaded modules in the environment (variable
MODULES_LMPREREQ
) and ensure they keep satisfied. (see Modulefile prereq constraints consistency section in MIGRATING document) - Introduce the automated module handling mode, which consists in additional actions triggered when loading or unloading a modulefile to satisfy the dependency constraints it declares. Those actions are when loading a modulefile: the Requirement Load and the Dependent Reload. When unloading a modulefile, Dependent Unload, Useless Requirement Unload and Dependent Reload actions are triggered. (see Automated module handling mode section in MIGRATING document)
- Track the loaded modules that have been automatically loaded (with
environment variable
MODULES_LMNOTUASKED
) to distinguish them from modules that have been explicitly asked by user. This information helps to determine what module becomes a useless requirement once all its dependent modules are unloaded. - Track in saved collections the loaded modules that have been automatically
loaded by add of a
--notuasked
argument tomodule load
collection lines. So this information is restored in loaded environment when collection is restored. This--notuasked
argument is ignored outside of a collection restore context. - Consider modules loaded from a
module source
file as explicitly asked by user. - Install: add
--enable-auto-handling
configure option to enable or disable the automatic modulefile handling mechanism. - Process list of loaded modules or modules to load one by one during the
restore
,purge
andreload
sub-commands whatever the auto handling mode is. - Add the ability to control whether the auto_handling mode should be enabled
or disabled with an environment variable called
MODULES_AUTO_HANDLING
or from the command-line with--auto
and--no-auto
switches. These command-line switches are ignored when called from modulefile. - Init: add pager-related command-line options in shell completion scripts.
- Doc: describe
MODULES_LMCONFLICT
,MODULES_LMPREREQ
andMODULES_LMNOTUASKED
in module.1 man page. - Add
-f
and--force
command-line switches to by-pass dependency consistency duringload
,unload
orswitch
sub-commands. (see By-passing module defined constraints section in MIGRATING document) - Disallow collection
save
or loaded modulesreload
if some loaded modules have some of their dependency constraints unsatisfied. - The Dependent Reload action of a
load
,unload
andswitch
sub-commands excludes modules that have unsatisfied constraints and includes modules whose constraints are satisfied again (when sub-command process solves a conflict for instance). - Doc: describe
--force
,--auto
and--no-auto
command-line switches andMODULES_AUTO_HANDLING
variable in module.1 man page. - Ignore directories
.SYNC
(DesignSync) and.sos
(SOS) when walking through modulepath directory content. (contribution from Colin Marquardt) - Install: look for
make
rathergmake
on MSYS2. - Fix
exec()
usage in Python module function definition to retrieve the correct return status on Python3. - Cookbook: add the top-priority-values and unload-firstly-loaded recipes.
- Install: add
gcc
to the build requirements in RPM specfile. - Silent any prereq violation warning message when processing Dependent
Reload mechanism or
purge
sub-command. - Doc: mention
createmodule.sh
andcreatemodule.py
scripts in FAQ. (fix issue#189) - Register all alternative names of loaded modules in environment with
MODULES_LMALTNAME
variable. These names correspond to the symbolic versions and aliases resolving to the loaded modules. Helps to consistently solveconflict
orprereq
constraints set over these alternative names. (fix issue#143 / see Consistency of module load/unload commands in modulefile section in MIGRATING document) - Doc: describe
MODULES_LMALTNAME
in module.1 man page. - Install: add
--with-bin-search-path
configure option to get in control of the path list used to search the tools required to build and configure Modules. (fix issue#164) - Install: add
--enable-silent-shell-debug-support
configure option to add the ability to control whether or not code to support silent shell debug should be added to the module function and sh-kind initialization scripts. (fix issue#166) - Install: add
--enable-quarantine-support
configure option to add the ability to control whether or not code to support quarantine mechanism should be added to the module function and initialization scripts. (fix issue#167) - Check version set in modulefile magic cookie. If modulefile sets a version
number greater than
modulecmd.tcl
script version, this modulefile is not evaluated like when no magic cookie is set at all. (fix issue#171 / see Express Modules compatibility of modulefile with versioned magic cookie section in MIGRATING document) - Fix uninitialized variable in procedure producing list of element output. (fix issue#195)
- Ensure the consistency of
module load
modulefile command once the modulefile defining it has been loaded by assimilating this command to aprereq
command. Thus the defined constraint is recorded in theMODULES_LMPREREQ
environment variable. Same approach is used formodule unload
modulefile command which is assimilated to aconflict
command. Thus the defined constraint is recorded in theMODULES_LMCONFLICT
environment variable. (see Modulefile alias and symbolic modulefile name consistency section in MIGRATING document) - Only look at loaded modules when unloading so unloading an nonexistent modulefile does not produce an error anymore. (fix issue#199)
- Report error raised from modulefile evaluation as
ERROR
ratherWARNING
, like when a conflict constraint is hit. Moreover this kind of evaluation error is now silenced on global evaluation like when processingavail
orsearch
sub-commands. - Record messages to report them by block on when processing a
load
or anunload
modulefile evaluation to improve readability on these evaluating modes that may cascade additional actions. (see Improved module message report section in MIGRATING document) - Foreground
load
,unload
,switch
andrestore
actions (i.e., asked on the command-line) now report a summary of the additional load and unload evaluations that were eventually triggered in the process. - Support
del
andremove
aliases forunload
sub-command like on compatibility version. (fix issue#200 with contribution from Wenzler) - Correctly transmit the arguments along with the command to execute on
system
modulefile command. (fix issue#201) - Contrib: add
mt
utility script which helps to run just specific part of the test suite. - Introduce
set-function
andunset-function
modulefile commands to define shell function on sh-kind and fish shells. (fix issue#193 with contribution from Ben Bowers)
Modules 4.1.4 (2018-08-20)¶
- Doc: fix typo on
getenv
command description in modulefile(4) man page and clarify this command should be preferred over::env
variable to query environment variable value in modulefile. - Init: fix
bash
andzsh
completion scripts to enable Extended Regular Expression (ERE) onsed
command with-E
argument (rather-r
) for compatibility with OS X's and BSDs' sed. (fix issue#178) - Handle default version sets on an hidden modulefile (were not found previously). (fix issue#177)
- Init: fix
ksh
initialization script for ksh88 compatibility. (fix issue#159) - Install: use
sed
command rathergrep
andcut
inconfigure
andMakefile
scripts. (fix issue#175 with contribution from Michael Sternberg) - Fix typo, tab indentation and pipe opening mode on
createmodule.py
utility script. (contribution from Jan Synacek) - Check
ModulesVersion
value set from.version
rc file to ensure this value refers to a version name in current directory. Report error if a nested value is detected and ignore this value. (fix issue#176)
Modules 4.1.3 (2018-06-18)¶
- Make
setenv
command alterenv
Tcl global array duringhelp
,test
orwhatis
evaluation modes. (fix issue#160) - Doc: describe MANPATH variable special treatment on compatibility version in diff_v3_v4 document.
- Initialize and export _moduleraw SH shell function if
stderr
is attached to a terminal. Was previously checkingstdout
. (fix issue#169) - For
csh
shells, quote code generated by modulecmd.tcl to pass it to theeval
shell command. - Escape special characters when producing code to define shell aliases (fix issue#165)
- Correct modulefile lookup when a modulefile directory is overwritten by a module alias definition but it contains an empty sub-directory. (fix issue#170)
- Doc: describe
getenv
command in modulefile(4) man page. - Improve SH shell detection in profile.sh initialization script to use shell
variable on
bash
orzsh
to determine current shell name. (fix issue#173)
Modules 4.1.2 (2018-03-31)¶
- Add an example global rc file in
contrib/etc
directory that ensuresMODULEPATH
is always defined. - Check
HOME
environment variable is defined onsavelist
andis-saved
commands or raise error if not. - Fix saving of deep module default version in collection when version pinning
is disabled: if
foo/bar/version
is default version forfoo
, collection will retain justfoo
(was retainingfoo/bar
). - Enable to save and restore collections containing full path modulefiles eventually with no modulepath defined.
- Run
puts
command not related tostderr
orstdout
channels in calling modulefile context to correctly get access to the targeted file channel. (fix issue#157) - Quote
autoinit
result for eval interpretation on SH-kind shells to avoid parameter expansion to randomly occur on generated code depending on file or directory names of current working directory. (fix RH bug#1549664) - Ignore empty elements found in
MODULEPATH
,LOADEDMODULES
or_LMFILES_
to ensure all elements in these variables are non-empty strings. - Raise error if loaded environment is in an inconsistent state when calling
commands requiring correlation of information from the
LOADEDMODULES
and the_LMFILES_
environment variables. Error raised onload
,unload
,switch
,reload
,purge
,list
,save
andrestore
commands. May affectinfo-loaded
oris-loaded
commands if module passed as argument to these command is specified as a full path modulefile. - Fix
list
command to process loaded modules information before performing any content output. - Install: adapt
configure
script and Makefiles to support installation on Cygwin system. - Detect terminal width on Windows
cmd
terminal withmode
command. - Improve Windows
cmd
shell support: error code returned, echoing text, shell alias creation and removal, working directory change. - Raise error when an empty module name is passed to module sub-commands like
load
,display
orunload
. - Raise error when an empty collection name is passed to module sub-commands
like
save
,saveshow
orrestore
. - Raise error when an empty path is passed to module
unuse
sub-command, like already done onuse
sub-command. - Clear argument list if an empty module command name is passed.
- Fix
module
function definition for all shells inautoinit
command to correctly handle empty-string parameters or parameters containing white-spaces, quotes, escape characters. - Fix
module
function definition for Python to accept being called with no argument. - Fix parameter expansion on
module
function for all SH-kind shells when quarantine mode is activated. - Escape
\
character when producing R shell code.
Modules 4.1.1 (2018-02-17)¶
- Make separator lines, used on
display
command result for instance, fit small screen width. - Install: give ability to build and install Modules from git repository
without documentation if
sphinx-build
cannot be found. - Install: adapt
configure
script and Makefiles to support installation on FreeBSD, Solaris and OS X systems. (fix issue#147) - Rework code generated by
autoinit
for sh-kind shells to avoid use of local variables as those are defined differently through the sh variants. (also fix issue#147) - Init: use a default value on undefined variables in sh-kind scripts to avoid
unbound variables in bash
-eu
mode. (fix issue#151) - Correctly detect terminal column number on Solaris.
- Init: fix csh init script to get compatibility with pure csh shell
- Sanitize content of
MODULEPATH
before using it at run-time, to make potential relative paths absolute, remove trailing slashes, etc. (fix issue#152) - Check loaded modulefiles still exists before displaying statistics on them
during a
list
action. - Use a specific reference counter variable name (
MODULES_MODSHARE_<VAR>
instead of<VAR>_modshare
) for DYLD-specific variables. (fix issue#153) - No error raise when updating a DYLD or LD path-like variable on OS X when System Integrity Protection (SIP) is enabled. In this situation, these variables are not exported in subshell context, so they appear undefined.
- Init: protect arguments passed to the
_moduleraw
sh function from interfering content of current working directory. (fix issue#154) - Install: move
hostname
RPM requirement to the compat sub-package. - Start pager process only if some text has to be printed. (partially fix issue#146)
- Ignore
PAGER
environment variable to configure Modules pager to avoid side effects coming from a general pager configuration not compatible with Modules pager handling. (fix issue#146) - Do not blank anymore default Modules pager options if default pager is
less
when theLESS
environment variable is defined. (fix issue#146)
Warning
With this bugfix release, changes have been made on the pager
setup to avoid side effects coming from the system general pager
configuration. As a result PAGER
environment variable is now ignored
and MODULES_PAGER
should be used instead to adapt Modules pager
configuration at run-time.
Modules 4.1.0 (2018-01-15)¶
- Extend stderr output redirection on sh-kind shells to all terminal-attached shell session, not only interactive shell session.
- Extend shell code produced by the
autoinit
command to perform the same environment initialization as done ininit
shell scripts (default value set for module-specific environment variables, parse or source of configuration files). - Make init shell scripts rely on
autoinit
command to define themodule
command and setup its default environment. - Fix error rendering code for Tcl shell by producing a call to the
error
procedure. - Introduce pager support to handle informational messages, using
less
command with-eFKRX
options by default. Environment variableMODULES_PAGER
orPAGER
may be used to supersede default pager command and options.--paginate
and--no-pager
switches enable or disable pager from the command line. - Install: add
--with-pager
and--with-pager-opts
configure options to define default pager command and its relative command-line options. - Introduce quarantine mechanism to protect module execution against side
effect coming from the current environment definition. Variables whose name
has been put in
MODULES_RUN_QUARANTINE
will be emptied or set to the value hold byMODULES_RUNENV_<VAR>
in the modulecmd.tcl run-time environment. Quarantine variable original value is then restored within modulecmd.tcl execution context once it has started. - Install: add
--with-quarantine-vars
configure option to define at build time theMODULES_RUN_QUARANTINE
andMODULES_RUNENV_<VAR>
environment variables set in initialization scripts. - Add
MODULES_SILENT_SHELL_DEBUG
environment variable to disable on sh shell and derivatives anyxtrace
orverbose
debugging property for the duration of either the module command or the module shell initialization script. (fix issue#121) - Change error code produced by modulecmd.tcl for the Tcl, Perl, Python, Ruby, CMake and R scripting languages to return a 'false' boolean value in case of error rather raising a fatal exception.
- Adapt module function definition for Tcl, Perl, Python, Ruby, CMake and R
scripting languages to always return a value, result of the modulecmd.tcl
run. When modulecmd.tcl run does not produce a specific status, a 'true'
boolean value is returned. On CMake, resulting value is returned though a
module_result
global variable. - Spool content sent to the stdout channel with
puts
command during a modulefile interpretation, to effectively transmit this content to stdout after rendering the environment changes made by this modulefile. (fix issue#113) - Introduce
append-path
,prepend-path
,remove-path
andis-loaded
module sub-commands, based on existing modulefile-specific Tcl commands. (fix issue#116) - Introduce
is-saved
,is-used
andis-avail
modulefile Tcl commands and module sub-commands to test availability of collection, modulepath or modulefile. - Raise error when a call to
path
orpaths
module sub-commands is attempted during a modulefile interpretation. Both commands now return text rather print text on scripting languages. An empty string is returned in no match case instead of a false boolean value. - Introduce
module-info loaded
modulefile command and its module sub-command counterpartinfo-loaded
. This new command returns name of the modules currently loaded corresponding to the name passed as argument. (fix issue#3) - Fix
is-loaded
command to correctly handle multiple module names passed as argument (fix issue#138) - Support no argument on
is-loaded
,is-saved
andis-used
commands to return if anything is respectively loaded, saved or used. - Interpret
module source
command set in modulefile inunload
mode when the modulefile itself is interpreted in this mode. - Consider a modulefile passed with name starting by
./
or../
a full path name modulefile, like those starting by/
. These kind of names are converted to absolute path names, for instance to register them in loaded modulefile list during aload
command. - Correlate modulefile passed as full path name (starting by either
./
,../
or/
) to already loaded modulefile registered with regular module name (file name without its modulepath prefix) to prevent for instance from loading twice same modulefile. Correlate in the same way regular module name to already loaded full path name modulefile. - Introduce
MODULES_COLLECTION_PIN_VERSION
environment variable to record modulefile version number when saving collections even if version corresponds to the default one. (fix issue#89) - Fix location of
etc/rc
global RC file to@prefix@/etc/rc
instead of$MODULESHOME/etc/rc
not to depend onMODULESHOME
environment variable value. - Strengthen argument check for
append-path
,prepend-path
andremove-path
modulefile Tcl commands and module sub-commands. Raise error if argument list is not correct. - Fix support for the
--delim=C
argument form onappend-path
,prepend-path
andremove-path
commands. - Fix path reference counter handling in case path element is an empty string. Distinguish an empty path element from a variable set empty to clear it.
- Pass multiple path elements separated by delimiter character as one string
on
append-path
,prepend-path
andremove-path
commands. - Accept multiple path element arguments on
append-path
,prepend-path
andremove-path
commands. - Introduce the
--duplicates
argument option toappend-path
andprepend-path
commands to add a path element already registered in variable. - Introduce the
--index
argument option toremove-path
command to delete a path entry by passing its position index in variable. - Provide the ability to setup a site-specific configuration sourced at the
start of
modulecmd.tcl
main procedure. This configuration is a Tcl script namedsiteconfig.tcl
which enables to supersede any Tcl definition made inmodulecmd.tcl
. Location of this file is controlled at configure time with the--etcdir
option. - Add the ability to handle paths containing reference to environment variable
in
MODULEPATH
. When these kind of paths are used bymodule
command, the variable references are converted to their corresponding value or to an empty string if they are not defined. - Enclose value set to environment variable on Tcl within curly braces rather double quotes to protect special characters in it from interpretation.
- Correctly parse
.modulespath
initialization file to handle lines without any#
character or to handle files with no content to extract. - Re-introduce the
--enable-versioning
configure option, which appends Modules version to installation prefix and deploy aversions
modulepath shared between all versioning enabled Modules installation. A modulefile corresponding to Modules version is added to the shared modulepath and enables to switch from one Modules version to another. - Fix removal of CMake generated temporary script file by stripping newline character from script file name.
- Add
MODULES_CMD
environment variable to expose path to the currently active module command script. This variable is set at initialization time. - Introduce
modulecmd
wrapper script, installed in binary directory, which executes the active module command. - Fix modulefile Tcl interpreter reset when handling list variables. (fix issue#145)
- Introduce 'module-virtual' modulefile Tcl command to associate a virtual module name to a modulefile. This module can be located with its virtual name and the associated modulefile is the script interpreted when loading, unloading, etc.
- Resolution of relative paths occurring during a modulefile interpretation to target a modulefile or a modulepath now takes the directory of the currently interpreted modulefile as the current working directory to solve the relative paths.
Modules 4.0.0 (2017-10-16)¶
Starting with this release, modules-tcl has become Modules. The following changes describe the differences with last modules-tcl release (1.923). To learn about the changes between this release and last Modules 3.2 release, please see the New features document.
- Relax constraint on command-line argument position so options and switches can be passed either before or after command name.
- Report
unsupported option
warning rather stop on error when compatibility-version specific command-line switches are passed (--force
,--human
,--verbose
,--silent
,--create
,--icase
,--userlvl
). - Keep empty
module load
line in shell configuration files after running theinitrm
orinitclear
commands. - Always return the value of
tcl_platform(osVersion)
foruname release
- Optimize code output, for Perl to only return
1;
once for a no-operation situation and for Python to notimport os
when there is only an error to render. - Use value of system command
uname -n
foruname nodename
. - Add support for CMake shell
- Ignore
/
character used as suffix in modulefile name passed on command line. - Rename Perl initialization script in
perl.pm
and Python inpython.py
. - Add support for Ruby shell (with contribution from Tammo Tjarks)
- Add support for R shell (with contribution from Roy Storey)
- When a default is set for a given module name, target modulefile can be referred on as modulename/default in addition to just modulename.
- Locate symbolic versions on
avail
command even these symbols are set over a module alias or another symbolic version. In this situation the symbol spread along the resolution path until reaching a modulefile. - Define a more standard shebang on modulecmd.tcl script.
- Determine modulefile corresponding to given module name using the loaded
context only on
unload
situation. - Enable to unload mod/dir/subdir/vers when unload of mod or mod/dir asked. Was previously working only if deep module to unload was also the default version for these root names.
- Make -l/-t switches mutually exclusive. Last switch mentioned on the command-line is honored.
- Output parsable modulepath header when -l/-t switches are enabled.
- When searching for a module in a given modulepath directory, if a module alias or a symbolic version matches searched module but the target of this alias or symbol is not found in current modulepath directory, search for this target restarting search from the first modulepath in list to ensure modulepath priority.
- Solve aliases or symbolic versions looking for all modulepaths on
search
andpaths
commands. Was previously solved if their target was found in same modulepath directory. - Add support for hidden dot modulefiles. A hidden modulefile does not appear in case of wild search, it is only returned when search is about its exact name.
- No table header print in --long mode on an
avail
command if no result are returned. - Add blank line between displayed list of elements, for instance between
modulepath content on
avail
command. - Improve readability of error messages encountered during modulefile
execution by putting Tcl error message first after the
Module ERROR
prefix. - Do not exit immediately when an internal error occurs in currently interpreted modulefile. Consider this interpretation as failed and continue to proceed the other modulefile arguments.
- When multiple modulefiles are passed on
display
,help
andtest
commands only output one separator line between 2 interpreted modulefiles. - Fix environment settings stack handling issue when restoring stack after a failed attempt to load a modulefile in a modulefile.
- Failed attempt to load or unload a modulefile within a modulefile now leads to this upper modulefile load or unload failure. Previously upper modulefile were loaded respectively unloaded even if its dependent sub-modulefile failed to load or unload.
- During a
switch
command, if the unloading part fails the loading part will not be tried. Unloading part fails if module to unload does not exist or its unload interpretation raise error. - Init: use
module source
rather shell commandsource
to load modulerc system configuration in sh-kind, csh-kind and fish shell init scripts. - Install: transform configuration options to bind to an existing compatibility Modules version into option (--enable-compat-version) to build and install this compatibility version along with main version.
- Init: adapt initialization scripts to handle both main and compatibility version. By default a shell script enables main version and if the environment variable MODULES_USE_COMPAT_VERSION is set to 1, the compatibility version is enabled instead of main version.
- Install: import from compatibility version and install
add.modules
andmkroot
utility scripts (scripts developed by R.K. Owen). - Install: update RPM spec file to handle compatibility version as a
compat
sub-package. - Add completion script for Fish shell (contribution from BEFH).
- Doc: extend content of diff_v3_v4 to details all noticeable changes between v3.2 and v4.0.
- Doc: introduce MIGRATING guide to learn the major changes when moving from v3.2 to v4.0.
- Fix
list
command when full pathname modulefile is loaded (fix bug#132) - Install: handle version number though git tags in scripts, documentation and RPM spec file.
- Doc: migrate documents from POD format to reStructuredText to benefit from Sphinx documentation framework and Read The Docs publishing capabilities.
Above changes describe the differences with modules-tcl release 1.923. To learn about the changes between Modules 4.0 and last Modules 3.2 release, please see the New features document.
modules-tcl-1.923 (2017-07-20)¶
- Fix
aliases
command when a global or user RC file is set. - Find and solve global or user RC aliases and symbolic versions on
search
,whatis
andpaths
commands. - Do not look at currently loaded modules to resolve the target of a module alias.
- Rework default and latest versions search on
avail
command. Correct display when at a given level a sub-directory element is last element in directory among modulefiles. Previously sub-directory was printed but last file among modulefiles was also printed (2 latest versions at the same level). A directory tagged "default" does not appear anymore in default listing result as its content (the default version found in that directory) will be displayed. - When an alias is set and overrides name of an existing directory, take this alias into account for default and latest choice and ignore directory content.
- Bad default set will lead to no result displayed for the corresponding
module in case of default
avail
display. - Correct inclusion of aliases in output result when these aliases are not part of the exact same module path than module path of the search.
- Rewrite existing shell initialization file with initadd, initprepend, initswitch, initrm and initclear commands rather than writing a new file then copying this new file to replace the existing initialization file. In addition only re-writes shell initialization file if its content need to be altered.
- Raise an error on initadd, initprepend, initswitch, initrm and initclear
commands when no
module load
line are found in shell initialization file. - Normalize error messages for the various collection-related commands when collection cannot be accessed.
- Cleanup existing reference counters of a path list variable when this
variable is altered by a
setenv
or anunsetenv
command. - Init: do not pollute tab-completion with moduleraw command. (Bert Wesarg)
- Make use of the same Tcl interp for each modulefile interpretation and
use another one for each modulerc (but the same for each modulerc). By
doing so we proceed like on C-version where same interpreter is used
across modulefile or modulerc interpretation. Huge performance
improvement is achieved with this change on commands making intensive
use of interp like
avail
. Interpreter state is reset from one interpretation to another: the initial variable and procedure state is restored before each new interpretation to avoid spread of definitions from one interpretation to another. Also in case of nested interpretation each interpretation level has its own interpreter so a module loaded by another does not influence the interpretation of the module loading it. - Improve performance of aliases and symbolic versions resolution by computing these resolution at definition time. As a consequence resolution loop are not registered anymore and produce an error message when spotted not at display time.
- Reduce number of
access
system call by trying access to modulefile when reading the content of a modulefile directory rather testing access before trying it. - No error raise on empty argument list for load. To cope with initadd
behavior that requires at least an empty
module load
line in startup files. (fix SF bug#88) - Fix initadd to handle load line without trailing space. Was previously
expecting load directive to be written "module load " to get a match.
With fix,
module load
line will also be matched. - Like C-version catch raised error when break or continue are called from outside of a loop to handle them as when they are called from modulefile main body. (fix SF bug#87)
- Return error on
module use
command when an empty path string is provided rather ignoring it. - Workaround
min
andmax
functions andlreverse
procedure for correct operations under Tcl version 8.4. - Install: add --with-tclsh configure option to give the ability to choose the Tcl interpreter shell to setup in initialization scripts.
- Handle error raised from the ModulesDisplay, ModulesHelp and ModulesTest
procedures in the same way than for the evaluation of the modulefile
content. An error occurring during the evaluation of the modulefile
content will lead to no evaluation of the
display
,help
andtest
command specific functions. - Remove
debug
module command - Doc: describe
path
,paths
andautoinit
module command. - Correct use of xrdb tool when not installed in default path.
- Fix
init*
module commands to behave more like C-version and document remaining differences in diff_with_c-version. - Init: make
sh
init script closer to POSIX specification to support sh flavors different than Bash or Zsh like Dash. - Fix column-mode display for very short width terminal.
- Install: introduce an
install
non-regression testsuite which is triggered by themake testinstall
command and checks modules-tcl installation is operational. - Init: fix modulerc load test on
fish
init script. - Init: fix interactive shell test on
sh
init script. - Install: add --enable-example-modulefiles configure option that install by default some modulefiles provided as example in the system modulefiles directory.
- Install: when uninstalling, do not remove modulefiles directory if it is not empty.
- Add completion script for Zsh shell.
- Add
module test
command to trigger when called execution of a ModulesTest procedure in target modulefile following same kind of mechanism thanmodule help
.
modules-tcl-1.832 (2017-04-29)¶
- Fix
getenv
sub-command to correctly return environment variable value. - Clarify in man-pages display of module alias and symbolic version-name on
avail
command and management of file access issue when locating modulefiles. - Distinguish access issue (permission denied) from find issue (cannot
locate) when trying to access directly a directory or a modulefile as
done on
load
,display
orwhatis
commands. In addition on this kind of access, not readable .modulerc files are ignored rather producing a missing magic cookie error. - When mode is set to unload,
module load
commands in modulefile are interpreted asmodule unload
commands. To guaranty correct behavior regarding requirements, the module list passed to the load command is reversed to unload the modulefiles in the reverse order than they have been loaded. - Correct
display
command to only report module commands set in modulefile and not those set in the various .modulerc on the path toward this modulefile. - Fix bash and tcsh completion scripts to eliminate symbolic version names
from
avail
command result. - Improve
avail
command when a symbolic version-name is passed as argument to return the modulefile target of this symbolic version-name. - When looking for an implicit default in a directory, now a module alias is taken into account so it can be returned as the last element in it (highest numerically sorted version).
- Fix
list
command to correctly display thedefault
tag along loaded modules when set via a .version file. - Fix long output of
list
command to display the symbolic version-names associated to each loaded module if any. - Improve
avail
command to return alias module when an alias name is passed as argument. - On a
--default
listing, a modulefile does not appear anymore if a directory is set default at the same level. On a--latest
listing, a directory does not appear anymore if set default but not the latest. - Read modulerc and validate its header in a single open/read/close sequence
instead of two in order to reduce to number of IO operations during an
avail
command. - Drastically reduce grid size computation time which removes overhead when displaying module avail results in column-mode.
- Translate module name to currently interpreted module name when name correspond to the last part this interpreted module only in case of symbolic version-name or alias resolution.
- Avoid resetting regular path (/usr/bin) or manpath (/usr/share/man) when switching from Tcl to C version in switchml utility.
- Raise error on x-resource if DISPLAY environment variable is not set.
- Fix lisp init script which was broken for environment change actions.
modules-tcl-1.775 (2017-03-07)¶
- Improve README with examples, requirements, links, etc. Also update INSTALL documentation with details on the new configure/make/make install process.
- Add display of a release date next to the version number when calling for
--help
or--version
. - Update diff_with_c-version document to describe the features of the Tcl-version that are not supported on the C-version. Also state that the diff takes C version 3.2.10 against Tcl version 1.729 as a basis.
- Introduce
switchml
tool, a shell function (or alias for csh or tcsh shells) that swap currently enabled Modules version (C or Tcl) by the other version (C or Tcl). Configure option--with-cver-initdir
must be defined to enableswitchml
in initialization script. - Define a PATH and MANPATH in shell initialization scripts that point to the defined modules-tcl installation directories.
- Give ability to generate distribution tarball from the git repository with
Makefile
dist
target. - Introduce an installation process for this software following the configure/make/make install fashion. Configure step enables to choose installation paths and init scripts features to activate. Make step mainly translates init scripts with the configuration set. Make install creates target directories and copy files into them.
- Fix MODULESHOME setup in autoinit command to define it as an absolute path
and set it to the upper directory when modulecmd.tcl is located in a
bin
or alibexec
directory. - Correct alias and version resolution on avail command which was erroneous
in case of a modulefile holding symbols (like
default
) and targeted by aliases. Avail output was showing the aliases holding the symbols instead of the modulefile.
modules-tcl-1.729 (2017-02-01)¶
- Add documentation in module(1) man page on the modulefile collection
concept and the relative
save
,restore
,saverm
,saveshow
andsavelist
commands. - Add document to list the differences of the functionalities that can be found on the C-version of the Modules package compared to the Tcl-version.
- Improve modulecmd.tcl shebang to only search
tclsh
once if found in PATH. - Add
module-info mode
check againstremove
andswitch
values. - Introduce
module-info command
Modules-specific Tcl command to distinguish complexload
orunload
commands that cannot be determined withmodule-info mode
alone. For instance a modulefile can now be aware that aswitch
, arestore
or apurge
command is currently being run. - Enable usage of
module-info
Modules-specific Tcl command from a modulerc file. - Fix
module-info specified
Modules-specific Tcl command. - No exit raise on modulefile or modulerc error during
avail
,aliases
,whatis
andsearch
commands to avoid harming results from these global commands if error exists in a few modulefiles. - Exit with error code when a critical error is encountered when interpreting a modulefile or a modulerc.
- Inhibit non-critical error report raised from modulefiles during
avail
,aliases
,whatis
andsearch
commands to avoid error flood when parsing all modulefiles or modulercs. - Handle multiple lines of
module-whatis
Modules-specific Tcl commands defined for the same modulefile. - Handle multiple arguments passed to the
module-whatis
Modules-specific Tcl commands. They are joined to get a single line of text. - Return error on
whatis
command if searched modulefile is not found.
modules-tcl-1.704 (2017-01-20)¶
- Set path variable counter to 1 for paths without a known reference count (was previously set to 999999999).
- Introduce
envml
utility which acts as an application launcher where module commands are instantiated to setup environment before launching the given application. - Always register paths provided to be part of MODULEPATH environment variable as absolute paths to get independent from the current working directory.
- Inhibit next modulefiles interpretation with
exit
Modules-specific Tcl command only if current mode isload
. - Add argument to
module-info shell
andmodule-info shelltype
to test current shell or shelltype value. - Fix use of
default
version-name to not consider it as a module symbol if a modulefile is nameddefault
. - Fix path variable counters when
:
character is used in elements of a path-like variable. - Update module(1) and modulefile(4) man pages to clear content specific to the C version of Modules and add content specific to or adapt content that behave differently on this Tcl version.
- Fix TCLSH variable issue in Python init script.
modules-tcl-1.677 (2017-01-04)¶
- Make
switch
command handle a single argument. The modulefile to switch to is the one passed on the command-line and the modulefile to unload is assumed to be the currently loaded module with the same root name as this modulefile specified on the command-line. - Make
switch
command idempotent by always ending up withold
unloaded andnew
loaded, whatever the starting situation is. - Fix
exit
Modules-specific Tcl command. - Add
refresh
command as alias onreload
command. - Add dummy
module-log
,module-trace
,module-user
andmodule-verbosity
Modules-specific Tcl commands to enable support for modulefiles using them. - Fix
system
Modules-specific Tcl command to behave like described on the man page. - Fix
module list
when module loaded with full path - Disable
g_force
property by default to avoid loading a modulefile already loaded. It also avoids path element reference counting to get increased when the same module is asked twice for load. - Clarify module-info
mode
option and sethelp
mode onmodule help
command. - Clarify module-info
flags
anduser
options. - Handle empty or separator path on
add-path
adunload-path
commands. - Delete environment variable targeted by an
unsetenv
command onunload
mode if no value has been provided along. On display mode, print environment variable value if any has been passed tounsetenv
command. - When setting Tcl variable, enclose value within double quotes.
- Fix perl quoting style for variable set, escape single quotes rather double quotes.
- Call
unuse
command instead ofuse
command on amodule unload
. - Fix
continue
Modules-specific Tcl command. - Add
chdir
Modules-specific Tcl command. - Fix
break
Modules-specific Tcl command.
modules-tcl-1.655 (2016-11-23)¶
- No display of modulepath header if no module found in it.
- Remove call to
module aliases
onmodule avail
command, as aliases are now directly included in theavail
results. - Include module aliases in the displayed result of an
avail
command. Also display aliases defined in a global or user modulerc file. - Exit with error code if error occurred on display or help commands.
- Fix module-info symbols resolution.
- Better handling of .modulerc and .version files when searching for a modulefile.
- Fix module-info version resolution.
- Fix module-info alias resolution.
- Register alias and version by the short module name and improve their resolution to avoid loop.
- Source $MODULERCFILE/modulerc when $MODULERCFILE is dir.
- Make it so you can do
module avail un
, wildcard*
character implied.
modules-tcl-1.632 (2016-09-06)¶
- Raise error if command does not receive the excepted number of arguments.
- Improve column-mode display to get a denser output on
avail
command. - Standardize the output of Warning, Error, InternalBug and ErrorAndExit messages.
- Add short option -d for --delim on prepend-path.
- Introduce collection target concept to distinguish between machines, environments or domains that are incompatible with each other.
- Introduce
saveshow
command, to display content of saved collections. - Improve
save
andrestore
commands to handle collection specified as absolute or relative file path. - Introduce
saverm
command, to delete saved collections. - Enable to
restore
collection with multiple modulefiles specified on the same line. - Fix
restore
command when there is no module to load in collection. - Fix
restore
command when collection fully rewind module paths. - Fix
restore
command to preserve module path order set in collection. - Raise error if try to save an empty environment in a collection.
modules-tcl-1.602 (2016-08-13)¶
- Add support for Fish shell.
- Import recent tests added to C-version on 10-use and 50-cmds testsuites.
- Add short option -d for --delim on append-path and remove-path.
- Fix load and implement unload x-resource.
- Fix Python code that was broken or not Python3-compliant. Fixed code is used to define the module command, to render error and to process x-resource.
- Always dictionary-sort (also called numerical-sort) list of modulefiles or list of collections.
- Fix bash completion script to be compliant with bash posix mode.
modules-tcl-1.578 (2014-12-24)¶
- First release to be described in this NEWS file but it does not mean this is the first version of modules-tcl as this Modules flavor is born in 2002.
- At this stage, modules-tcl handles a majority of the module commands and modulefile Tcl commands available on C version.
Frequently Asked Questions¶
Module command¶
How does the module
command work?¶
The command module
is an alias for something like:
sh:
module ()
{
eval "$(/some/path/modulecmd sh "$@")"
}
csh:
eval "`/some/path/modulecmd csh !*:q`"
Where the modulecmd
outputs valid shell commands to stdout which manipulates the shell's environment. Any text that is meant to be seen by the user must be sent to stderr. For example:
puts stderr "\n\tSome Text to Show\n"
I put the module
command in a script and I run the script... it doesn't change my environment?¶
A child process (script) can not change the parent process environment. A module load
in a script only affects the environment for the script itself. The only way you can have a script change the current environment is to source the script which reads it into the current process.
sh:
. somescript
csh:
source somescript
How do I capture the module command output?¶
This ties in with the very first question. Since the module command is essentially an eval, the visible output to the screen must necessarily be sent to stderr. It becomes a matter on how to capture output from stderr for the various shells. The following examples just show how to spool the output from the avail command to a file. This also works for the various other module commands like list, display, etc. There are also various tricks for piping stderr to another program.
sh:
module avail 2> spoolfile
csh: (overwrite existing file)
module avail >&! spoolfile
How to use the module command from Makefile?¶
To make use of the module
command from a Makefile, the shell initialization script should first be sourced within Makefile rule to define the module
function in that context. Environment variable MODULESHOME
may help to locate the shell initialization script in a generic way, like done in the following example:
module_list:
source $$MODULESHOME/init/bash; module list
How to preserve my loaded environment when running screen
?¶
Usually the Screen terminal utility is installed with the setgid bit
set. Depending on the operating system, when a setgid program is ran, it may
not inherit several environment variables from its parent context like
LD_LIBRARY_PATH
. This is a safeguard mechanism to protect the
privileged process from being fooled by malicious dynamic libraries.
As a result, if your currently loaded environment has defined
LD_LIBRARY_PATH
, you will find it cleared in the screen
session.
One way to get your environment correctly initialized within screen
session
is to reload it once started with module reload
command:
$ module load foo/1.0 $ echo $LD_LIBRARY_PATH /path/to/lib $ screen $ module list Currently Loaded Modulefiles: 1) foo/1.0 $ echo $LD_LIBRARY_PATH $ module reload $ echo $LD_LIBRARY_PATH /path/to/lib
Other way around is to reconfigure screen
not to rely on the setgid bit
for its operations. You may also look at the tmux utility, which is an
alternative to screen
that do not use the setgid mechanism.
Modulefiles¶
I want the modulefile to source some rc script that came with some application¶
See the module sh-to-mod sub-command sub-command to translate the environment changes done by a shell script into a modulefile.
You could also check the source-sh modulefile command to directly import the environment changes performed by a shell script within a modulefile.
How do I specify the default modulefile for some modulefile directory?¶
Modules usually uses the the highest lexicographically sorted modulefile under the directory, unless there is a .version
file in that directory which has a format like the following where "native" is a modulefile (or a sub-directory) in that directory. It's also possible to set the default with a .modulerc
file with a module-version command.
#%Module1.0#####################################################################
##
## version file for Perl
##
set ModulesVersion "native"
Build Issues¶
The configure script complains about TclX¶
...
checking for TclX configuration (tclxConfig.sh)... not found
checking for TclX version... using 8.4
checking TCLX_VERSION... 8.4
checking TCLX_LIB_SPEC... TCLX_LIB_SPEC not found, need to use --with-tclx-lib
checking TCLX_INCLUDE_SPEC... TCLX_INCLUDE_SPEC not found, need to use --with-tclx-inc
...
TclX is an optional library that can speed up some operations. You don't need TclX for modules to compile and work, so you can add the --without-tclx option when configuring and it should proceed to completion. In fact, it should have succeeded anyways and just not attempt to use TclX.
Otherwise, you can load the TclX library package for your OS and the configure
script should find it. If not then if you know where the tclxConfig.sh
file or the library and include files are placed then use the following options:
--with-tclx=<dir> directory containing TclX configuration
(tclxConfig.sh) [[searches]]
--with-tclx-ver=X.Y TclX version to use [[search]]
--with-tclx-lib=<dir> directory containing tclx libraries (libtclxX.Y)
[[none]]
--with-tclx-inc=<dir> directory containing tclx include files
(tclExtend.h,...) [[none]]
Meta Information¶
Why does modules use Tcl?¶
The first versions of the Modules package used shell scripts to do its magic. The original authors then chose to implement the same in C to speed things up and to add features. At the time the only easily embeddable interpreter was Tcl which provided a standard language and the glue. Now that other interpreters are available they could be embedded, but haven't so far. There is also a pure Tcl version available.
How can I help?¶
We can use help at various levels. The best way to contribute is to send in a patch file (see the FAQ on how to generate a patch file) with whatever fixes. The patch will be reviewed and tested. If you are a regular contributor then you'll likely be invited to become a developer and to have direct source access, and the fame, power, and prestige that all entails.
How do I download the source repository?¶
Anonymously clone the git repository, view the list of branches, and set to a specific branch:
git clone git://git.code.sf.net/p/modules/git modules-myversion
cd modules-myversion
git branch -a
git checkout modules-3-X-Y
git status
How do I generate a patch file?¶
If you're starting from a tarball¶
Unpack the tarball and it should place the sources into a directory named modules-3.X.Y , then rename the directory to modules-3.X.Y-myversion or something like that. Make whatever changes you want, and be sure to test the changes and if you can add tests to identify the bug and the fix... that will endear yourself to the developers.
Once you have the changes in your version, then unpack the original sources from the tarball in a directory side-by-side to the directory with your version, and at that parent level run the following diff
command:
diff -u -r -P -N modules-3.X.Y modules-3.X.Y-myversion > my.patch
If you're starting from the git cloned repository:¶
From within the git repositories.
git diff > my.patch
Changes between versions¶
This document lists functionality differences between each major version of Modules. The goal of each following section is to reference the features of previous major version that are missing or behave differently on the next major version and the features that can only be found on this newer version. For instance the Modules 4 section lists the changes compared to Modules 3.2.
Regarding deprecated or newly introduced features, this document only lists their name or the command line argument related to them. Please refer to the module and the modulefile man pages of the previous or newer Modules version to learn the details about these removed or added features.
Modules 4¶
This section provides the list of differences with Modules version 3.2. This version of Modules is also referred in this document as compatibility version. Modules 4 is based on what was previously called Modules-Tcl. Comparison takes as a basis version 3.2.10
of compatibility version against Modules version 4.0
. Any change made past these versions will explicitly mention the release number starting from the difference appears or disappears.
Note
The numerous bugs or limitations spotted on Modules 3.2
across the years have been fixed in Modules 4.0
. The list of reported issues that have been solved are available on the project code forge.
Removed or changed features¶
This section describes the features of the compatibility version that are not supported or that behave differently on Modules 4.
Package Initialization¶
MODULESBEGINENV
environment snapshot functionality is not supported on version 4. Modules collection mechanism should be preferred to save and restore sets of enabled modulepaths and loaded modulefiles. Modules 4 also introduces a system configuration file init/modulerc, located in Modules installation directory. Starting version 4.3
, this file could also be etc/initrc. This modulerc/initrc file is sourced by Modules shell initialization scripts and helps to setup the initial environment right after initializing the module command.
Command line switches¶
--human
--create, -c
--userlvl lvl, -u lvl
These command line switches are not supported on Modules 4. When these options are passed on the command-line, it produces an Unsupported option warning and command is ran with the unsupported switches ignored.
--ter
--lon
--sil
--verb
These intermediate-form command line switches are not supported on Modules 4. Short or long switch name should be used instead.
This command line switch is short version of--help
switch on Modules 4 whereas it is short version of --human switch on compatibility version.
This command line switch was not supported starting Modules version4.0
but reintroduced starting version4.2
with a different meaning: instead of enabling an active dependency resolution mechanism--force
command line switch now enables to by-pass dependency consistency when loading or unloading a modulefile.
These command line switches were not supported starting Modules version4.0
but reintroduced starting version4.3
. However, reintroduced--silent
switch does not redirect stderr channel to/dev/null
if stderr is found not to be a tty.
This command line switch was not supported starting Modules version4.0
but reintroduced starting version4.4
. When--icase
switch is now set it applies to search query string and module specification on all sub-commands and modulefile Tcl commands.
Module Sub-Commands¶
On compatibility version, paths composing the MODULEPATH
environment variable may contain reference to environment variable. These variable references are resolved dynamically when MODULEPATH
is looked at during module sub-command action like avail
. This feature was missing on Modules 4.0
but it has been re-introduced on Modules 4.1
.
update
This module sub-commands is not supported on Modules 4.
This command line switch was not supported starting Modules version4.0
but reintroduced starting version4.3
. It now takes into account the--force
command-line switch to skip confirmation dialog.
Compatibility version redirects output made on stdout in
ModulesHelp
Tcl procedure to stderr.During an
help
sub-command, only theModulesHelp
Tcl procedure of a modulefile is interpreted on compatibility version. Version 4 interprets all the content of the modulefile, then call theModulesHelp
procedure if it exists.On version 4,
ModulesHelp
subroutine is not ran if an error occurred during the interpretation of the modulefile main body.
On version 4,ModulesDisplay
subroutine is not ran if an error occurred during the interpretation of the modulefile main body.
On compatibility version, the same Tcl interpreter is used for the interpretation of all .modulerc or .version files during an
avail
command but the state of this interpreter is not reset between each interpretation. So some variable and procedure definitions may spread from one interpretation to another on this compatibility version. Modules 4 reuses the same interpreter for all .modulerc or .version interpretation but it is cleaned between each interpretation to protect from definition spread.In case of
--terse
or--long
mode, all enabled modulepaths will be displayed whether they hold result to display or not. Modules 4 outputs only the modulepaths where matching results are found. Modulepaths with no result to report are discarded from output.
On Modules 4, string passed as argument is always searched in a case insensitive manner.
On Modules 4, the value of an environment variable is set even if the new value is the same as the current value of this variable in environment.
When an already loaded modulefiles is asked for load again, compatibility version will refresh the shell alias definition this modulefile hold if any, whereas Modules 4 will ignore the new load order.
In case of modulefile loading another modulefile, if sub-modulefile load fails calling modulefile will still be loaded on compatibility version whereas Modules 4 will also abort calling modulefile load. Compatibility version behavior could be restored by enclosing
module load
command and arguments withincatch
Tcl command.Starting with version
4.1
, content sent to thestdout
channel during a modulefile interpretation is spooled to effectively transmit this content to stdout after rendering the environment changes made by this modulefile.
On Modules 4, the value of an environment variable is set even if the new value is the same as the current value of this variable in environment.
Compatibility version enables to load a modulefile by passing on the command-line the name of a module alias or symbolic version pointing to this modulefile. However this module alias or symbolic version name cannot be used to unload the modulefile once loaded. Modules 4 enables to pass a module alias or symbolic version name to unload a loaded modulefile referred by this name.
On versions
4.0
and4.1
, unloading an nonexistent modulefile generates an Unable to locate modulefile error. Starting with version4.2
, unloading a module only looks at loaded module list and does not trigger a modulefile search. So starting version4.2
the same behavior than Modules compatibility version is obtained.Starting with version
4.1
, content sent to thestdout
channel during a modulefile interpretation is spooled to effectively transmit this content to stdout after rendering the environment changes made by this modulefile.When the specified module to unload matches multiple loaded modules, Modules 4 unloads lastly loaded module whereas compatibility version unloads firstly loaded module. A configuration option
unload_match_order
has been introduced in version4.3
and it enables to restore the behavior of compatibility version when it is set toreturnfirst
.
When switching on version 4 an old modulefile by a new one, no error is raised if old modulefile is not currently loaded. In this situation compatibility version throws an error and abort switch action.
When switching on Modules 4 an old modulefile by a new one, this new modulefile does not keep the position that the old modulefile had in the
LOADEDMODULES
list as done on compatibility version but it is appended to the end of the list. Same goes for PATH-like environment variables: replaced PATH component is appended to the end or prepended to the beginning of the relative PATH-like variable, not appended or prepended relatively to the position hold by the swapped PATH component.When a modulefile loads another modulefile with a module load order, this sub-module is not unloaded when the top modulefile is swapped-out during a
switch
command on compatibility version. Version 4 interprets the swapped-out modulefile in unload mode, so the module load order is interpreted as module unload order and sub-module is unloaded.
When the modulepath to enable is passed as a relative path, compatibility version will set it using passed relative name whereas Modules 4 will determine the corresponding absolute path and will register it rather passed relative name.
Modules 4 provides path element counting feature which increases a reference counter each time a given path entry is added to a given environment variable. This feature also applies to theMODULEPATH
environment variable. As consequence a modulepath entry element is removed from the modulepath enabled list only if the related element counter is equal to 1. When unusing a modulepath if its reference counter is greater than 1, modulepath is kept enabled and reference counter is decreased by 1.
On Modules 4, environment variable edition commands (setenv, unsetenv, append-path, prepend-path and remove-path) do no set variable to the defined value on the modulefile evaluation context during awhatis
evaluation. Instead environment variables are initialized with an empty value if undefined, to avoid raising error when attempting access to an undefined element during the modulefile evaluation.
On version 4 no message is displayed to give details on how list of modulefiles to load has been altered in initialization file.
No message is displayed on Modules 4 to inform of the modulefiles that have been removed from the loading list in initialization file.
Empty
module load
line is left on version 4 when last modulefile from a line is asked to be removed. On compatibility versionmodule load null
line is set in this case.
Emptymodule load
lines are left on version 4 whereasmodule load null
lines are set on compatibility version.
Modules Specific Tcl Commands¶
On version 4 the characters that have a special meaning when rendered in shells are escaped when used in value to set environment variables, shell alias or shell functions. Thus it is possible to set environment elements with value containing these special characters (like backticks). On version 3 these special characters were evaluated by shell when recording the environment changes implied by modulefile evaluation.
Modules 4 produces an error when adding a bare colon character : as a path element to a path-like variable, as this colon cannot be distinguished from the colon used for path separator.
Modules 4 supports adding or removing empty path element to a path-like variable, whereas compatibility version looses track of this path element when the path-like variable is modified afterward. Empty path element enables to set a leading colon character :, which has a specific meaning on some regular environment variable like
MANPATH
orLD_LIBRARY_PATH
.When adding a path element to the
MANPATH
environment variable, Modules 4 is treating this variable like any other whereas a special treatment was applied on compatibility version: a default MANPATH value, set at configure time, was appended in caseMANPATH
variable was unset.
Modules 4 provides path element counting feature which increases a reference counter each time a given path entry is added to a given environment variable. As consequence a path entry element is removed from a path-like variable only if the related element counter is equal to 1. If this counter is greater than 1, path element is kept in variable and reference counter is decreased by 1.
When unloading a modulefile,
remove-path
command is not applied to environment variable on Modules 4, whereas on compatibility version it is processed the exact same way than when loading modulefile.
On Modules 4 code passed to theexit
Modules specific Tcl command will not be thrown to be the module return value.
In case the specified aliased module or the symbolic version introduces a resolution loop with already defined aliases or symbolic versions, this new alias or symbolic version is not registered and an error message is raised. On compatibility version, alias or symbolic version introducing loop are registered as the modulefile resolution is not computed at registration time.
module-info flags
module-info trace
module-info tracepat
module-info user
Thesemodule-info
options are related to compatibility version-specific features so they are available on Modules 4 but with a dummy implementation that always returns false or an empty value.module-info mode
During an
unload
sub-command,unload
is returned instead ofremove
. However if mode is tested againstremove
value, true will be returned.During a
switch
sub-command,unload
thenload
is returned instead ofswitch1
thenswitch2
thenswitch3
. However if mode is tested againstswitch
value, true will be returned.module-info name
If the module name passed to the command-line has been specified as a full path name, the module-info name used in modulefile returns this file base name on compatibility version whereas it returns on Modules 4+ the full path name as it is identified by this name once loaded.module-info version
Declared aliases or symbolic versions are not registered anymore if they introduce a resolution loop. As a result module-info version does not return an*undef*
string value as it does not face resolution loop situation anymore.module-info symbols
Declared aliases or symbolic versions are not registered anymore if they introduce a resolution loop. As a consequence symbolic versions introducing loop situation are not part anymore of the module-info symbols returned result as they are not registered.
A symbolic version sets on a module alias will be propagated toward the resolution path to also apply to the relative modulefile if it still correspond to the same module name.
module-log
module-trace
module-user
module-verbosity
These Modules specific Tcl commands are related to compatibility version-specific features so they are available on Modules 4 but with a dummy implementation that always displays a warning message saying the command is not implemented.
When multiple words are passed as argument tomodule-whatis
but they are not enclosed in double-quotes or curly braces they will be displayed as a single line on Modules 4 whereas compatibility version displays them as one line per word.
Whereas compatibility version sets a shell function when variables are in use in alias value on Bourne shell derivatives, Modules 4 always defines a shell alias never a shell function.
Locating Modulefiles¶
On version 4, when a module alias is set and overrides name of an existing directory, this alias is taken into account to locate the default version of this module name and the modulefiles locating in the directory are ignored.
When looking for an implicit default in a modulefile directory, aliases are taken into account in addition to modulefiles and directories to determine the highest numerically sorted element.
Modules 4 will resolve module alias or symbolic version passed to unload
command to then remove the loaded modulefile pointed by the mentioned alias or symbolic version.
Modules 4 resolves module alias or symbolic version pointing to a modulefile located in another modulepath.
When locating modulefiles on Modules 4, if a .modulerc, a .version, a directory or a modulefile cannot be read during the search it is simply ignored with no error message produced. Visibility of modulefiles can thus be adapted to the rights the user has been granted. Exception is made when trying to directly access a directory or a modulefile. In this case, the access issue is returned as an error message. Access issue is also returned when a direct access is made to a module alias or a symbolic version targeting an unreadable modulefile.
New features¶
This section describes the features of Modules version 4 that are not supported on the compatibility version. Please refer to the above section for features supported by both versions but behaving differently.
Package Initialization¶
Support for fish, lisp, tcl and R code output has been introduced on Modules 4.0
.
On version 4 and for sh, bash, ksh, zsh and fish shells, text output, like listing from the avail
command, is redirected from stderr to stdout after shell command evaluation if shell is in interactive mode. Starting version 4.1
, this content redirection occurs if shell session is attached to a terminal.
Starting version 4.5
, a new alias or function called ml may be defined at initialization time, to provide a handy frontend to the module command.
Starting version 4.5
, support for Windows cmd shell is introduced.
Modulecmd startup¶
Starting with version 4.1
, modulecmd.tcl
sources upon invocation a site-specific configuration script named siteconfig.tcl
. This Tcl script enables to supersede any global variable or procedure definition of modulecmd.tcl.
Command line switches¶
The following command line switches appeared on Modules 4.
Introduced in version | New command line switches |
---|---|
4.0 | --debug , -D , --default ,
-d , --latest , -L |
4.1 | --paginate , --no-pager |
4.2 | --auto , --no-auto |
4.3 | --indepth , --no-indepth , --color ,
--starts-with , -S , --contains ,
-C |
4.5 | --json , -j |
4.6 | --trace , -T , --all , -a ,
-DD |
4.7 | -vv , --output , -o ,
--width , -w |
Module Sub-Commands¶
The following module sub-commands appeared on Modules 4.
Introduced in version | New module sub-commands |
---|---|
4.0 | reload , source , search ,
save , restore , saverm ,
saveshow , savelist , path ,
paths , autoinit , aliases ,
test |
4.1 | append-path , prepend-path ,
remove-path , is-loaded , is-saved
is-used , is-avail , info-loaded |
4.3 | config |
4.6 | sh-to-mod |
4.8 | edit , try-load |
All module sub-commands will return a non-zero exit code in case of error whereas on compatibility version issues that occurred do not lead to an exit of the module command with a non-zero code.
Starting with version 4.1
, module function for all scripting languages, like Perl or Python, always returns a value. In case of error, a false boolean value is returned instead of raising a fatal exception. For module sub-commands returning a text value, the module function will actually return this value. In all other cases a true boolean value is returned.
Non-critical errors are not displayed on
avail
,whatis
andapropos
sub-commands. Only valid results are returned.Module aliases are included in the result of these sub-commands. They are displayed in the module path section where they are defined or in a global/user modulerc section for aliases set in user's or global modulerc file. A
@
symbol is added in parenthesis next to their name to distinguish them from modulefiles.Search may be performed with an alias or a symbolic version-name passed as argument.
Arguments to these
avail
,whatis
andapropos
commands may use wildcard characters to express glob patterns.
Collections¶
Modules Collections have been introduced on Modules 4.0
.
Environment¶
The following environment variables appeared on Modules 4.
Modules Specific Tcl Commands¶
The following modulefile Tcl commands appeared on Modules 4.
Introduced in version | New modulefile Tcl commands |
---|---|
4.0 | module-info command , getenv ,
reportError , reportWarning |
4.1 | module-info loaded , is-saved ,
is-used , is-avail , module-virtual |
4.2 | set-function , unset-function |
4.6 | source-sh , module-hide ,
module-forbid ,
module-info usergroups ,
module-info username |
4.7 | versioncmp , module-tag ,
module-info tags |
4.8 | variant , getvariant |
Starting with version4.2
, these Modules-specific Tcl commands support being called with a symbolic modulefile or a modulefile alias passed as argument.
In case of
module load
command specifying multiple modulefiles, when mode is set tounload
these modulefiles will be unloaded in the reverse order to ensure correct handling of prerequisites.Starting with version
4.7
, theload
,unload
andswitch
sub-commands support the--not-req
option to avoid recording a prereq or a conflict requirement toward specified modules.
Starting with version4.1
, both commands handle being called with multiple value arguments and option--duplicates
is added.
Starting with version4.1
,remove-path
handles being called with multiple value arguments and option--index
is added.
Starting with version
4.1
,is-loaded
supports being called with no argument passed. In this case, it returns true if any modulefile is currently loaded, false otherwise.Starting with version
4.2
,is-loaded
supports being called with a symbolic modulefile or a modulefile alias passed as argument.This Modules-specific Tcl command was not enabled for modulerc evaluation starting Modules version
4.0
but it has been reintroduced starting version4.2.1
.
Modules Variables¶
The following Modules-specific Tcl variables appeared on Modules 4.
Introduced in version | New Modules-specific Tcl variables |
---|---|
4.7 | ModuleTool , ModuleToolVersion |
4.8 | ModuleVariant |
Modules configuration options¶
The concept of configuration option has been introduced on Modules 4.3
. The
following Modules configuration option has been introduced on Modules 4.
Introduced in version | New Modules configuration options |
---|---|
4.3 | auto_handling , avail_indepth ,
collection_pin_version , collection_target ,
color , colors , contact ,
extra_siteconfig , implicit_default ,
locked_configs , pager , rcfile ,
run_quarantine , silent_shell_debug ,
search_match , set_shell_startup ,
term_background , unload_match_order ,
verbosity , wa_277 |
4.4 | advanced_version_spec , extended_default ,
home , icase |
4.5 | ml |
4.6 | nearly_forbidden_days |
4.7 | avail_output , avail_terse_output ,
implicit_requirement , list_output ,
list_terse_output , mcookie_version_check ,
shells_with_ksh_fpath , tag_abbrev ,
tag_color_name , term_width |
4.8 | editor , variant_shortcut |
list_output
, list_terse_output
Starting version 4.8, elementvariant
is added to the list of accepted values. It is added to the default value list oflist_output
.
Modules 5¶
This section provides the list of differences with Modules version 4.
Comparison takes as a basis version 4.8
against Modules version 5.0
.
Any change made past these versions will explicitly mention the release number
starting from the difference appears or disappears.
Removed or changed features¶
This section describes the features of Modules 4 that are not supported or that behave differently on Modules 5.
Package Initialization¶
The initialization configuration file initrc
and the
modulepath-specific configuration file modulespath
are now searched by
default in the etcdir
instead of in the initdir
. Moreover these
configuration files are only searched in one location. Previously they were
searched in both etcdir
and initdir
locations by Modules
initialization process.
When initializing Modules, the initrc
configuration file is evaluated
in addition to the the modulespath
configuration file and not instead
of this file. initrc
is evaluated after modulespath
file.
Report the modules loading and unloading during the evaluation of the
initrc
configuration file. These report messages are disabled when the
verbosity
configuration option is set to concise
or silent
.
Enforce use of the Modules magic cookie (i.e., #%Module
file signature) at
the start of initrc
configuration file. No evaluation occurs and an
error is produced if the magic cookie is missing or if the optional version
number placed after the cookie string is higher than the version of the
modulecmd.tcl
script in use.
Quarantine mechanism code in the Modules shell initialization scripts is now
always defined and mechanism always applies if some environment variables are
defined in MODULES_RUN_QUARANTINE
. Code in the modulecmd.tcl
script to restore environment variables put in quarantine is now always
generated and applies if the __MODULES_QUARANTINE_SET
environment
variable is set to 1
. By default on Modules 5 the module shell
function definition is generated without quarantine support but it could be
enabled by setting quarantine_support
to 1
in initrc
.
Code to silence shell debug properties in the Modules shell initialization
scripts is now always defined and mechanism applies if
MODULES_SILENT_SHELL_DEBUG
is set to 1
. Code to silence shell
debug properties in the module shell function could now be enabled
if MODULES_SILENT_SHELL_DEBUG
is set to 1
prior Modules
initialization or if the silent_shell_debug
configuration option is
set to 1
in the initrc
configuration file. Option is set off by
default on Modules 5.
During the autoinit
process, the environment variable
__MODULES_AUTOINIT_INPROGRESS
is checked and if it is found set to
1
, the initialization process immediately ends. If not, this environment
variable is set to 1
which ensures no initialization loop could occur,
especially when the set_shell_startup
configuration option is set.
Modulecmd startup¶
Enforce use of the Modules magic cookie (i.e., #%Module
file signature) at
the start of global or user rc files. These files are not evaluated and an
error is produced if the magic cookie is missing or if the optional version
number placed after the cookie string is higher than the version of the
modulecmd.tcl
script in use.
Module Sub-Commands¶
append-path
, prepend-path
, remove-path
When sub-command is not called during a modulefile evaluation, the reference counter associated with each entry in targeted environment variable is ignored. In such context, amodule append-path/prepend-path
will not increase the reference counter of a path entry already defined and amodule remove-path
will remove specified path whatever its reference counter value.
No error is raised when evaluating a modulefile without a value specified for thevariant
it defines. As a result, the unspecified variant is not instantiated in theModuleVariant
array variable.
Reference counting mechanism is not anymore applied to the Modules-specific path variables (likeLOADEDMODULES
). As a result no__MODULES_SHARE_<VAR>
variable is set in user environment for these variables. Exception is made forMODULEPATH
environment variable where the mechanism still applies.
Sub-command evaluates all loaded modulefiles and re-apply the non-persistent environment changes they define (i.e., shell aliases, shell functions and command put on stdout channel). With this change therefresh
sub-command is restored to the behavior it had on Modules version 3.2.
Only report the module load and unload directly triggered by these sub-commands. Load and unload triggered by other modules are reported through the automated module handling messages of the main modules.
Starting Modules 5.2:
- if no argument is provided and if default collection does not exist, initial environment is restored.
- sticky modules are unloaded when restoring a collection.
Enforce use of the Modules magic cookie (i.e.,#%Module
file signature) at the start of any scriptfile passed for evaluation to thesource
sub-command. These files are not evaluated and an error is produced if the magic cookie is missing or if the optional version number placed after the cookie string is higher than the version of themodulecmd.tcl
script in use.
Starting Modules 5.2, if no argument is provided and if default collection does not exist, initial environment is displayed.
Non-existent modulepath is now accepted as argument.
Reference counting mechanism is ignored when sub-command is not called during a modulefile evaluation. In such context, a
module use
will not increase the reference counter of a path entry already defined.
Reference counting mechanism is ignored when sub-command is not called during a modulefile evaluation. In such context, a
module unuse
will remove specified path whatever its reference counter value.Correctly handle several modulepaths specified as a single argument (i.e.,
/path/to/dir1:/path/to/dir2
).
Modules Specific Tcl Commands¶
When an element is added to a path-like variable, add this element to the associated reference counter variable (named__MODULES_SHARE_<VAR>
) only when this element is added multiple times to the path-like variable. When an element is removed from a path-like variable, this element is removed from the reference counter variable when its counter is equal to 1.
chdir
, module
, module-trace
, module-verbosity
,
module-user
, module-log
These modulefile commands have been undeclared from the modulerc Tcl interpreter on Modules 5. An error message is obtained if still used instead of silently ignoring it.
When passed environment variable is not defined, an empty string is returned by default rather_UNDEFINED_
.
Forbid use of
module source
command in modulefile or in an initialization rc file, thesource
Tcl command should be used instead.Starting version
5.1
an error is raised when an unused option is set onmodule use
ormodule unuse
commands.
When running on an unload evaluation, do not unset designated environment variable if no value to restore is provided.
Distinguish between being called on a unload evaluation without a value to restore or with an empty string value to restore.
Starting version 5.1,variant
command accepts being called without a list of accepted value defined. In this case, any value specified is accepted.
Locating Modulefiles¶
As the Advanced module version specifiers mechanism is enabled by
default on Modules 5, several characters are made special and cannot be used
anymore in module name or version. These characters are @
, =
, ~
,
+
and ,
. Also a module name cannot start with -
character. Module
name is allowed to finish by one or more +
character but +
cannot be
used at the start or inside a module name.
Environment¶
The following Modules environment variables have been changed on Modules 5.
Environment variable | Change |
---|---|
MODULES_LMALTNAME |
Renamed to __MODULES_LMALTNAME |
MODULES_LMCONFLICT |
Renamed to __MODULES_LMCONFLICT |
MODULES_LMNOTUASKED |
Removed |
MODULES_LMPREREQ |
Renamed to __MODULES_LMPREREQ |
MODULES_LMSOURCESH |
Renamed to __MODULES_LMSOURCESH |
MODULES_LMTAG |
Renamed to __MODULES_LMTAG |
MODULES_LMVARIANT |
Renamed to __MODULES_LMVARIANT |
MODULES_USE_COMPAT_VERSION |
Removed |
<VAR>_modquar |
Renamed to __MODULES_QUAR_<VAR> |
<VAR>_modshare |
Renamed to __MODULES_SHARE_<VAR> |
Modules configuration options¶
The default value of the following Modules configuration option has been changed on Modules 5.
Configuration option | Previous default value | New default value |
---|---|---|
auto_handling |
0 |
1 |
extended_default |
0 |
1 |
advanced_version_spec |
0 |
1 |
color |
never |
auto |
icase |
never |
search |
set_shell_startup |
1 |
0 |
silent_shell_debug |
undefined | 0 |
New features¶
Package Initialization¶
When initializing Modules, refresh
the loaded modules in case some
user environment is already configured.
Command line switches¶
The following command line switches appeared on Modules 5.
Introduced in version | New command line switches |
---|---|
5.1 | --redirect , --no-redirect , --tag |
5.2 | --timer |
5.3 | --ignore-cache , --ignore-user-rc |
Starting Modules 5.3, this command line switch accepts value prefixed by+
or-
which means value should respectively be appended to or subtracted from current configuration option value.
Module Sub-Commands¶
The following module sub-commands appeared on Modules 5.
Introduced in version | New module sub-commands |
---|---|
5.1 | state , load-any |
5.2 | lint , mod-to-sh , reset ,
stash , stashpop , stashrm ,
stashshow , stashclear , stashlist |
5.3 | cachebuild , cacheclear |
Starting Modules 5.1:
- this sub-command accepts patterns to filter the loaded modules to list.
- the
--starts-with
and--contains
options are supported on this sub-command to provide the regular search match capabilities.Starting Modules 5.3:
- Search query with just a variant set (no module name and version) is accepted.
Starting Modules 5.2, only the loaded modules listed in the__MODULES_LMREFRESH
environment variables are refreshed.
Starting Modules 5.2, initial environment is restored when specified collection name is__init__
.
Starting Modules 5.2:
- this sub-command accepts patterns to filter the named collections to list.
- the
--starts-with
and--contains
options are supported on this sub-command to provide the regular search match capabilities.- the
--all
option is supported on this sub-command not to limit to the collection matching currently set collection target.
Starting Modules 5.2, initial environment is displayed when specified collection name is__init__
.
Starting Modules 5.1, this sub-command also tracks shell completion changes for bash, tcsh and fish shells.
Starting Modules 5.2, this sub-command accepts modulefile specification as argument in addition to file path.
Starting Modules 5.3:
- variant specified in search query is taken into account to return available modules matching the variant specification.
- Search query with just a variant set (no module name and version) is accepted.
- Extra specifier is accepted in search query to query content of modulefiles.
Environment¶
The following environment variables appeared on Modules 5.
Modules Specific Tcl Commands¶
The following modulefile Tcl commands appeared on Modules 5.
Introduced in version | New modulefile Tcl commands |
---|---|
5.1 | add-property , remove-property ,
extensions , prereq-any ,
require-fullname , depends-on ,
prereq-all , always-load ,
module load-any , family ,
complete , uncomplete , pushenv |
Starting Modules 5.0, these modulefile commands are available from a modulerc evaluation context.
Starting version 5.1, the--return-value
option is added to return environment variable value or its fallback when modulefile is evaluated in display mode.
prereq
, module load/try-load/load-any/switch
Starting Modules 5.1, these modulefile commands accept the--tag
option.
prereq
, prereq-all
, always-load
,
depends-on
Starting Modules 5.2, these modulefile commands accept the--optional
option.
Starting Modules 5.1, these modulefile commands accept the--not-req
option.
Starting version5.1
options--*-on-unload
added to theremove-path
command are also added to themodule unuse
command.
Starting Modules 5.1, if content is sent to theprestdout
channel, it is rendered as command to evaluate in current shell session and prior any other environment changes.
Starting with version
5.1
:
- the
--remove-on-unload
option is added to also remove value when modulefile is unloaded.- the
--append-on-unload
and--prepend-on-unload
options are added to restore when modulefile is unloaded the value list unset at load time.- the
--noop-on-unload
option is added to perform no operation when modulefile is unloaded.
Starting with version5.1
, the--set-if-undef
option is added to set environment variable when modulefile is loaded only if not yet defined.
Starting Modules 5.1, this modulefile command also tracks shell completion changes for bash, tcsh and fish shells.
Starting with version
5.1
:
- the
--noop-on-unload
option is added to perform no operation when modulefile is unloaded.- the
--unset-on-unload
option is added to also unset variable when modulefile is unloaded.
Starting version 5.1, the--return-value
option is added to return variant value or its fallback when modulefile is evaluated in display mode.
Modules Variables¶
The following Modules-specific Tcl variables appeared on Modules 5.
Introduced in version | New Modules-specific Tcl variables |
---|---|
5.1 | ModuleVersion |
Modules configuration options¶
The following Modules configuration option has been introduced on Modules 5.
Introduced in version | New Modules configuration options |
---|---|
5.0 | quarantine_support |
5.1 | redirect_output , mcookie_check ,
collection_pin_tag |
5.2 | tcl_linter , protected_envvars ,
reset_target_state |
5.3 | ignore_cache , cache_buffer_bytes ,
cache_expiry_secs , ignore_user_rc |
avail_output
, avail_terse_output
Starting version 5.3, element
variant
is added to the list of accepted values.Starting version 5.3, element
variantifspec
is added to the list of accepted values. It is added to the default value list of both configuration options.Starting Modules 5.3, these configuration options accept value prefixed by
+
or-
which means value should respectively be appended to or subtracted from current configuration option value.
list_output
, list_terse_output
, colors
,
protected_envvars
, shells_with_ksh_fpath
,
tag_abbrev
, tag_color_name
, variant_shortcut
Starting Modules 5.3, these configuration options accept value prefixed by+
or-
which means value should respectively be appended to or subtracted from current configuration option value.
Cookbook¶
Modules can be used in many ways. The following collection of recipes provides
various installation examples that shed lights on how to take advantage of
existing Modules features and how to extend the module
command to achieve
specific needs.
Handling Compiler and other Package Dependencies¶
When creating a collection of software (applications and libraries) for users to use, there is the problem of ensuring that the user is using the correct builds of everything. Generally, if an user is attempting to compile code making use of the system software collection, you want to ensure that the user is compiling his code with the same compiler that was used to compile the library. This tends to be particularly true of C++ and Fortran code using modules, and parallel codes using MPI libraries.
As a result, in environments supporting multiple compilers, software libraries often end up with multiple installs of libraries and applications of the same version, depending on the compiler and other libraries used to build them. Sometimes there are even additional installs for variants with different threading models, number formats, level of vectorization support, etc. This cookbook describes various strategies for handling the modulefiles to support all these different builds for each package.
For each strategy, we will provide an overview of how it works, and then show how an user might interact with it, usually a similar sequence for each case. We wish to explore how, and how well, each strategy succeeds in handling the multiple builds of the same version of a package, including
- Basic dependency handling: seeing how well the strategy supports the loading of the correct build of a package depending on the previously loaded dependencies. And if no appropriate build is available, they should error accordingly.
- The
module switch
command and more advanced dependency handling: how well the strategy supports more advanced cases. E.g. a case wherein several modules are loaded and the user replaces a module upon which other modules currently loaded depend. In general, how well the strategy prevents the user's set of loaded modules from being incompatible. - Visibility into what packages are available. This includes being able to readily see all of the packages installed, seeing what versions of packages are available for a given compiler/MPI/etc combination, and seeing for which compiler/MPI/etc combinations a specific version of a package is available.
- How easily the user can navigate the modules for the builds. This includes how well partial modulenames (e.g. omitting version, etc) are handled by the different strategies.
We then try to summarize the strengths, weaknesses, and other attributes of each strategy. We also try to discuss differences in using on older (3.x) and newer (4.x) Environment Modules versions.
In addition to displaying examples for each strategy in this document, we have set up a the test environment as a playground in which you can explore.
Contents¶
Overview of Examples¶
The examples are a bit more elaborate than in some other cookbooks, so
the directory structure under doc/example/compiler-etc-dependencies
is similarly more complicated.
Example Software Library¶
For the purpose of the examples and the playground, we have created
a fake example software library, rooted at the subdirectory
doc/example/compiler-etc-dependencies/dummy-sw-root
beneath where
you placed the modules source files. This software tree is intended
to represent some of the features you might see in a real software
tree, which supports various compiler and MPI libraries, and that has
been added to over time, and not always in the most systematic way.
The example software library does not contain any real code; there are
dummy scripts for e.g. gcc
, mpirun
, etc. which just echo then
name of the code and what version, compiler, etc. it was supposed to be
built for, which is handy to show in the examples that the modulefiles
are working as expected. It also shows how such a directory tree might
be laid out --- the details of the layout will affect some of the code
in the modulefiles, etc. The directory structure can be altered to
fit your standards, but would require some minor modification to the
modulefiles, etc.
Note that there are also a bunch of subdirectories named 1
containing symlinks, these are for the strategy using the Flavours add-on and are
discussed in that section.
The software in the example software library consists of:
- GNU compiler versions
8.2.0
and9.1.0
- Intel Parallel Studio suite versions
2018
and2019
(includes compilers, MPI and MKL) - PGI compiler suite versions
18.4
and19.4
- OpenMPI version
4.0
, built for:gcc/9.1.0
intel/2019
pgi/19.4
- OpenMPI version
3.1
, built for:gcc
versions8.2.0
and9.1.0
intel
versions2018
and2019
pgi
versions18.4
and19.4
- mvapich version 2.3.1, built for:
gcc/9.1.0
intel/2019
pgi/19.4
- mvapich version
2.1
, built for:gcc
versions8.2.0
and9.1.0
intel
versions2018
and2019
pgi
versions18.4
and19.4
- foo version
2.4
, built for:gcc/9.1.0
andopenmpi/4.0
gcc/9.1.0
andmvapich/2.3.1
gcc/9.1.0
and no MPIintel/2019
andopenmpi/4.0
intel/2019
andmvapich/2.3.1
intel/2019
andintelmpi
intel/2019
and no MPIpgi/19.4
andopenmpi/3.1
pgi/19.4
and no MPI
- foo version
1.1
, built for:gcc/8.2.0
andopenmpi/3.1
gcc/8.2.0
andmvapich/2.1
gcc/8.2.0
and no MPIintel/2018
andopenmpi/3.1
intel/2018
andmvapich/2.1
intel/2018
andintelmpi
intel/2018
and no MPIpgi/18.4
andopenmpi/3.1
pgi/18.4
andmvapich/2.1
pgi/18.4
and no MPI
- bar version
5.4
, built with:gcc/9.1.0
and supportingavx2
gcc/9.1.0
and supportingavx
- bar version
4.7
, built for:gcc/8.2.0
and supportingavx
gcc/8.2.0
and supportingsse4.1
I.e., we have 3 families of compiler suites with 2 different versions each. And two MPI families (openmpi and mvapich) with two versions each, with the most recent version only built with the latest compiler version of each family, and the older version built with both versions of each compiler family. In addition, it is assumed that the intel compiler suites include Intel's MPI library built for that compiler. The application foo depends on the compiler and optionally on MPI libraries and has two versions; the newer version mostly has builds for the latest compiler and MPI (for pgi it only supports the latest compiler and older openmpi), and the older version mostly has builds for the older compiler and MPI. The bar application depends on compiler and has variants depending on size of integers used in the API.
We also assume that the gcc/8.2.0
compiler is the system default; i.e. it is
the compiler provided by default by the Linux distro used by the system, and
therefore might potentially be available to users without loading any modules.
More directories under doc/example/compiler-etc-dependencies¶
The modulefiles for the different strategies do not play well with each
other, in part because we use the same names for many of the modules
between strategies. So in addition to the dummy-sw-root
subdirectory,
each strategy has its own modulepath tree subdirectory
underneath doc/example/compiler-etc-dependencies
. There are some minor
differences between the modulefiles for the Modulerc-based Strategy
depending on whether Environment Modules 3.x or 4.x is being used,
so we actually have two trees for that case (modulerc3
and modulerc4
).
As there are a fair number of modulefiles, we make use of various tricks
in the cookbook Tips for Code Reuse in Modulefiles to minimize the amount of repeated
code. In general, the actual modulefiles are small "stubfiles", setting one or a few
Tcl variables, and then sourcing a common
tcl file which does all the
real work. Symlinks are used where possible to avoid duplicating files.
The Modulerc-based Strategy also uses some complicated .modulerc
files; these
are fairly generic and to avoid redundancy are symlinked into the appropriate
places in modulepath tree from the modrc_common
directory.
We also in some cases use Tcl procedures; for the sake of the
examples these our sourced in the files as needed, but if one were to
use the strategies needing such in production it would be better to follow
the suggestions in Expose procedures and variables to modulefiles and
place the required procedures in site config script.
The various tcl procedures are placed in the tcllib
sub-directory, outside
of the modulepaths. These are actually broken up into multiple files
for the purpose of this cookbook (so that smaller chunks of code can be
looked at in this document).
The example-sessions
subdirectory contains various shell scripts
used for the usage examples for each strategy (shell scripts are used
because there are some slight variations required between the strategies),
as well as the outputs of running such scripts. Subdirectories exist
for each strategy, and beneath them for each of the two Environment
Modules versions (3.2.10
and 4.3.1
) used; for brevity not all of them
are shown in this document, especially as the 3.x and 4.x differences
are often small. In the example outputs, the Environment Modules
version and the strategy being employed is indicated in the shell prompt
(e.g. mod3-flavours
or mod4 (modulerc)
).
Using the playground environments¶
Although we strive to provide a decent discussion in this cookbook, you are encouraged to try things out in the playground in order to get a better feel for things.
Because we use some modulefile names (e.g. gcc, intel, pgi, openmpi, etc)
that likely are present on your system as well, it is recommended
that if you wish to explore the playground environment that you
spawn a new shell, do a "module purge", and then set your MODULEPATH
environment variable appropriately for the specific strategy.
The Flavours_strategy, as will be discussed, requires some modifications to your Environment Modules installation. It is recommended that you you make a copy or new installation (for Flavours, a 3.x install works best), and then spawn a new shell and initialize the new Flavours install in that first. Flavours code is not provided with this cookbook.
Some of the modulefiles, etc. require knowledge of where they were
installed. To avoid requiring you to update lines in numerous
files, we require you to set the environment variable
MOD_GIT_ROOTDIR
to location where the modules git working directory
was cloned. E.g., if you issued the command
git clone https://github.com/cea-hpc/modules.git ~/modules.test
you should set MOD_GIT_ROOTDIR
to ~/modules.test
. Please
ensure it is exported (use setenv
in csh and related shells,
or export
in Bourne derived shells like bash). This is just
a hack to make the examples work better; if you opt to use one of
these strategies in production, you will want to hard code some
relevant paths; the comments in the modulefiles will describe
what needs to be done.
Some more detail on setting up the playground is given at the start of the Examples section for each strategy.
Flavours Strategy¶
The Flavours strategy uses the Flavours extension to Environment Modules. Unlike the other strategies discussed, this requires the separate download and installation of an extension to Environment Modules.
Installation and Implementation¶
More details can be found at the website for this extension, but to install this you basically just need to:
- Clone the git repo somewhere (
git clone https://git.code.sf.net/p/flavours/code flavours-code
) - Rename the standard Environment Modules
modulecmd
file (in thebin
subdirectory under the installation root) tomodulecmd.wrapped
. (It is recommended that you do this in a copy of your production installation, or better yet, in a new install of the 3.x Environment Modules (as Flavours has been developed for Modules 3.x)) - Copy the
modulecmd.wrapper
file from Flavours to thebin
subdirectory above. Make sure themodulecmd.wrapper
file is executable. - Symlink
modulecmd.wrapper
tomodulecmd
- Edit
modulecmd.wrapper
where indicated to give fully qualified path tomodulecmd.wrapped
- Copy the
flavours.tcl
andpkgIndex.tcl
files to some (possibly new) directory under the modules installation root, and setTCLLIBPATH
to that directory (you probably will want to add that to the various modules init scripts)
The module
command invokes modulecmd
, which in this case is results
in the Flavours wrapper bash script modulecmd.wrapper
being invoked. This
calls the renamed standard modulecmd.wrapped
command. This wrapper
command catches and processes certain output from the modulefile evaluation
intended for its consumption.
The modulefiles themselves make use of various commands in the Tcl module flavours
.
Many of these are just flavours variants of standard modulefile commands, e.g.
flavours prepend-path
versus prepend-path
. Some important flavours
commands:
package require flavours
: This loads the Tcl package flavours, and should occur near the top of your modulefileflavours init
: This initializes the flavours package, and should be the first of the flavours commands issued. Typically call right after the package load.flavours prereq
: Like the standardprereq
command, this declares a prerequisite. But it also does quite a bit more, as is discussed further below.flavours root
: This is used to set the root for where the package is actually installed. This is used when generating theflavours path
flavours revision
: seem intended to allow for changes in the path format in future versions offlavours
. It is used in constructing the final path to the package.flavours conflict
: This is similar to the standard conflict command, but enhanced to recognize the flavours prereqs above.flavours commit
: This should be called after theroot
,revision
, andprereq
sub-commands offlavours
are called, and before any of thepath
sub-commands. It seems to be responsible for taking all those values to above and constructing the path to the package.flavours path
: This returns a string with the path to the specific build of the package.flavours prepend-path
,flavour append-path
: These work much like the standardprepend-path
andappend-path
, except that the value being prepended/appended to the environment variable has the path (as returned byflavours path
) prepended to it with the appropriate directory separator. E.g., to add to thePATH
variable the bin subdirectory of the root directory where the specific build was installed, useflavours prepend-path PATH bin
flavours cleanup
: This should be called after allflavours
sub-commands are finished and before exiting the script to ensure proper cleanup. Among other things, it ensures that any packages that depend on this package will get reloaded if this package is switched out.
The flavours prereq
command accepts the new -class
parameter, allowing
it to require a class of packages; e.g. one could use -class compiler
to indicate
that it has a prereq on a compiler (any of the modules gnu
, intel
, or pgi
).
The allowable classes, and the package basenames that are in each class, is defined in
flavours.tcl
in the Tcl associative array _class
. The ones shipped by default are
- compiler: consisting of gnu, intel, and pgi
- mpi: consisting of openmpi, mvapich2, mvapich, intelmpi
- linalg: consisting of mkl, atlas, acml, netlib
You will likely want to adjust these if you go with flavours in production.
The flavours prereq
command also accepts the parameter -optional
, which declares
optional prerequisites. Although it sounds a little oxymoronic, this comes into play
with the secondary purpose of the command in declaring the components of the path, as
discussed below. If a prereq is not optional, the modulefile will complain if nothing
satisfying the prereq has been module loaded previously. If the prereq is optional,
the modulefile will not complain if it was not loaded, but will use the prereq in
constructing the path to the build of the package if it was loaded.
The flavours prereq
command also defines the components which will comprise the final
path to the directory containing the specific build of the package. The order of the
prereq commands controls the order of the components in the path.
The modulefile will check that all non-optional flavours prereq
commands are satisfied,
and then construct a path to the installation root for this build of the package using
the packages satisfying the prereqs. The resultant path is composed of:
- the value from
flavours root
- directory separator (
/
) - the value from
flavours revision
- directory separator (
/
) - a
prefix
created by concatenating the package names satisfying the prereqs, in order. The package name and version will be separated by a hyphen (-), as will the different components.
So if flavours root
was set to /local/software/foo/1.7
, revision
to 1, and the
package had prereqs compiler and mpi, and gnu/9.1.0
and openmpi/4.0
were loaded, the
resulting path would be /local/software/foo/1.7/1/gnu-9.1.0-openmpi-4.0
.
The modulefile actually will test for the existence of that directory, and if not found will return an error to the that the package was not built for that combination of prereqs. You either need to install your packages using the above directory schema, or create symlinks linking that scheme to where you actually install the packages.
Examples¶
We now look at the example modulefiles for flavours. To use the examples, you must
- Have Flavours extension installed. NOTE these examples will NOT work without the Flavours installed.
- Set (and export)
MOD_GIT_ROOTDIR
to where you git-cloned the modules source - Do a
module purge
, and then set yourMODULEPATH
to$MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/flavours
We start with the module avail
command:
[mod4-flavours]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/flavours -
bar/4.7 foo/2.4 intel/2018 mvapich/2.1 openmpi/4.0 simd/avx
bar/5.4 gnu/8.2.0 intel/2019 mvapich/2.3.1 pgi/18.4 simd/avx2
foo/1.1 gnu/9.1.0 intelmpi/default openmpi/3.1 pgi/19.4 simd/sse4.1
We note that we only see the package names and versions; e.g. foo/2.4
, without any mention
of the compilers and MPI libraries for which it is built. This terser type was an intentional
design goal of the authors. Also of note are the intelmpi and simd packages. The Flavours
approach relies on seeing what modules have been loaded previously in order to determine what
'flavor' of the requested package should be loaded. To support the different builds of bar
which depend on the CPU vectorization commands supported, we need to add a "dummy" package simd
.
The module definition is quite trivial; a simple stub file like
#%Module
# Modulefile for CPU vectorization support
set simd avx
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/common
and the main content in the common
file:
# Common stuff for "simd" modulefiles
# Using "flavours" strategy
#
# This file expects the following Tcl variable to have been previously defined:
# simd: The level of simd support, eg. avx, avx2, sse4.1
# Initialise "flavours"
package require flavours
flavours init
proc ModulesHelp { } {
global simd
puts stderr "
This is a dummy modulefile to indicate that the CPU vectorization
should be set to '$simd' where possible.
"
}
module-whatis "CPU Vectorization support level: $simd"
# Even in production, this modulefile would not do anything
conflict simd
# Reload any modules with this as a prerequisite
flavours cleanup
Basically it just declares a help procedure and whatis text. This way, an user can
load the appropriate simd module to control which variant of bar they will get. The
only interesting aspect is that near the beginning of the file we do a
package require flavours
and flavours init
, and add a flavours cleanup
near the bottom. The lines at the beginning instruct Tcl command to load the Flavours
package, and then initialize the package.
The flavours cleanup
is required so that if the simd module is switched out,
any modulefiles that depend on it get reloaded.
In our example, we assumed that the Intel MPI libraries are automatically set up properly if one
were to load the intel
module, and we assumed the Intel MPI libraries were not supported
for either the GNU or PGI compilers. However, we also wished to allow for foo
to
be used without any MPI support. So we need a way to distinguish if someone wants to
use an Intel compiler build of foo
without MPI or with the Intel MPI libraries. Our
choice for this example was to require one to explicitly module load intelmpi
if one
wished to use the Intel MPI variant --- we do not bother with a real version number because
assuming the version is determined by the version of intel
(the Intel Parallel Studio version).
So the intelmpi modulefile is similar to the simd modulefiles, a dummy modulefile. Again,
it includes the flavours init
and flavours cleanup
wrapping to ensure proper reloading
of dependent modules should it be switched out.
If you were to support Intel MPI for non-intel compilers, you could create your intelmpi
modulefiles as usual, and then add a default
or intel
"dummy" version to use the
version that is part of the intel
Parallel Studio. Or you could separate the intelmpi
bits from the intel
modulefile so both non-intel and intel compilers need to explicitly
module load intelmpi.
The modulefiles for the various compilers are all pretty much standard, except for the
same three flavours
lines as the simd modulefile: package require flavours
,
flavours init
, and flavours cleanup
. These are required to
ensure dependent modulefiles get reloaded if the compiler is switched out.
We also note that the modulefile for the GNU Compiler Collection is referred to as gnu
, not gcc
(this is due to how the compiler
class is defined in flavours.tcl
, and we did not bother
to change that for the purposes of this cookbook).
With the openmpi and mvapich MPI libraries, things start to get interesting. These all
should setup the environment for a different build depending on the compiler loaded. The
real work is done in the common
tcl file, as shown below:
# Common stuff for "openmpi" modulefiles
# Using "flavours" strategy
#
# Expects the following Tcl variables to have been previously set:
# version: version of openmpi
# Common parts of modulefile for openmpi
# Initialise "flavours"
package require flavours
flavours init
proc ModulesHelp { } {
global version
puts stderr "
openmpi: Test dummy version of OpenMPI $version
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy openmpi $version"
# Construct flavour name
flavours prereq -class compiler
flavours conflict openmpi
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
flavours root $swroot/openmpi/$version
flavours revision 1
flavours commit
# Set environment variables
setenv MPI_DIR [flavours path]
# Prepend to environment variables (paths relative to
# the directory containing the flavour)
flavours prepend-path PATH bin
flavours prepend-path LIBRARY_PATH lib
flavours prepend-path LD_LIBRARY_PATH lib
flavours prepend-path CPATH include
# Reload any modules with this as a prerequisite
flavours cleanup
Like the previous cases, the file starts with the Tcl command to load the
package, followed by the flavours init
command.
The flavours prereq
command states that this package requires a compiler to have been previously
loaded, and that the path to the specific build to use will depend on that. We note the use
of the -class
parameter; the exact definition of the compiler class is in the compiler
field of the Tcl associative hash _class
defined in flavours.tcl
.
The flavours root
sets the root directory of where the builds for this package is installed.
We use the MOD_GIT_ROOTDIR
environment variable for convenience in this example, but in production
you would generally hardcode a path. The result of all the directives is that the build will be
found in a path named after the compiler (since in this case there is only one flavour prereq
);
e.g. for gcc version 9.1.0
, we expect to find the build in $swroot/openmpi/4.0/1/gnu-9.1.0
.
If you do not use that naming convention for your installation directories, you can use symlinks
to fake it.
The flavours path
command in the setenv MPI_DIR
statement sets MPI_DIR to the aforementioned
build path. The flavours prepend-path
commands prepend to the environment variable specified
by the first argument the result of prepending the flavours path
to their second argument. E.g.,
the first such, assuming openmpi version 4.0
was requested and gnu/9.1.0
loaded, would be basically
the same as a standard Modules command:
prepend-path PATH $swroot/openmpi/4.0/1/gnu-9.1.0/bin
The following shows how this would appear to the user:
[mod4-flavours]$ module purge
[mod4-flavours]$ module load pgi/19.4
[mod4-flavours]$ module load openmpi/4.0
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod4-flavours]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4-flavours]$ module unload openmpi
[mod4-flavours]$ module switch pgi intel/2019
[mod4-flavours]$ module load openmpi/4.0
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod4-flavours]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4-flavours]$ module unload openmpi
[mod4-flavours]$ module switch intel gnu/9.1.0
[mod4-flavours]$ module load openmpi/4.0
[mod4-flavours]$ mpirun
mpirun (openmpi/4.0, gcc/9.1.0)
[mod4-flavours]$ module unload openmpi
[mod4-flavours]$ module switch gnu gnu/8.2.0
[mod4-flavours]$ module load openmpi/4.0
openmpi/4.0 - no flavour compatible with modules 'gnu/8.2.0'
Loading openmpi/4.0
ERROR: Module evaluation aborted
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/8.2.0
Here we note that once a compiler is loaded, the PATH
and the other environment
variables are set appropriately to point to the bin dir for the particular build of
openmpi/4.0
, as evidenced by the output of our dummy mpirun command. At the end, we attempt
to load openmpi/4.0
for gnu/8.2.0
, and receive an error because our dummy SW library does not contain
a matching build. This is determined from the flavours path
; if the
path does not exist (in this example $swroot/openmpi/4.0/1/gnu-8.2.0
) it will
abort in this fashion.
In the above, we have explicitly unloaded openmpi, switched the compilers, and then reloaded openmpi. A nice feature of Flavours is that it can handle the switching out of compilers or other modulefiles which other modulefiles depend on, as:
[mod3-flavours]$ module purge
[mod3-flavours]$ module load pgi/19.4
[mod3-flavours]$ module load openmpi
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod3-flavours]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod3-flavours]$ module switch pgi intel/2019
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod3-flavours]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod3-flavours]$ module switch intel intel/2018
openmpi/4.0 - no flavour compatible with modules 'intel/2018'
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod3-flavours]$ mpirun
mpirun (openmpi/4.0, intel/2019)
Note that when we switched between the pgi and intel compilers above, Flavours
automatically "unloaded" and "reloaded" the openmpi module. This happens in
the flavours cleanup
portion of the compiler modulefiles, and is due to
openmpi
declaring a flavours prereq
on the compiler class.
Note
The above behavior with switch
was done with version 3.2.10
of Environment Modules; it does not appear to work with 4.3.1
.
Note that when we further tried to replace version 2019
of the intel compiler with the 2018
version,
the module switch of the compilers failed because openmpi/4.0
was not built with
intel/2018
. Since the user never explicitly requested version 4.0
of openmpi (it was
defaulted in the initial load as the latest version of openmpi available for pgi/19.4
),
it would have been nicer had the attempted reload of openmpi allowed it t:o default to the 3.1
version (as the latest version available for intel/2018
). Nevertheless, it behaved well
in this situation; the module switch failed with a reasonable error message and the resulting
set of modules was still consistent.
We also note that if we attempt to load openmpi without having previously loading a compiler, we will get an error:
[mod4-flavours]$ module purge
[mod4-flavours]$ module load openmpi/3.1
openmpi/3.1 depends on one of the module(s) 'gnu intel pgi'
Loading openmpi/3.1
ERROR: Module evaluation aborted
[mod4-flavours]$ module list
No Modulefiles Currently Loaded.
[mod4-flavours]$ module purge
[mod4-flavours]$ module load gnu/8.2.0
[mod4-flavours]$ module load openmpi
openmpi/4.0 - no flavour compatible with modules 'gnu/8.2.0'
Loading openmpi/4.0
ERROR: Module evaluation aborted
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/8.2.0
In particular, there is no support for a "default" compiler; if e.g. you wished to make the
distribution supplied gcc the default compiler, you will need to have the initializations
scripts automatically do a module load of that compiler (possibly
a dummy modulefile like simd/intelmpi if the compiler is already in the user's path)
in your user's start up dot files or similar. We also note that there is no additional
intelligence in the version defaulting --- in the last example, we have gnu/8.2.0
loaded and if
we try to load openmpi without specifying a version, it defaults to version 4.0
as that is the latest version of openmpi without regard for the fact that there
is no build of openmpi version 4.0
for gnu/8.2.0
(but there is such for openmpi/3.1
).
The situation for foo
is more complicated, as it depends both on the compiler and
optionally on the MPI library. But with Flavours, the modulefile is only slightly more
complicated, e.g. for the common file is:
# Common stuff for "foo" modulefiles
# Using "flavours" strategy
#
# Expects the following Tcl variables to have been previously set:
# version: version of foo
# Initialise "flavours"
package require flavours
flavours init
proc ModulesHelp { } {
global version
puts stderr "
foo: Test dummy version of foo $version
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy foo $version"
# Construct flavour name
flavours prereq -class compiler
flavours prereq -optional -class mpi
flavours conflict foo
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
flavours root $swroot/foo/$version
flavours revision 1
flavours commit
# Set environment variables
setenv FOO_DIR [flavours path]
# Prepend to environment variables (paths relative to
# the directory containing the flavour)
flavours prepend-path PATH bin
flavours prepend-path LIBRARY_PATH lib
flavours prepend-path LD_LIBRARY_PATH lib
flavours prepend-path CPATH include
# Reload any modules with this as a prerequisite
flavours cleanup
Basically, the main difference is the addition of the
line flavours prereq -optional -class mpi
.
This instructs Flavours that there is an additional, optional prereq. The
order of the prereq lines matter, as that controls the resultant flavors path
.
With the current configuration, assuming gnu/9.1.0
and openmpi/4.0
were loaded,
the path would become $swroot/foo/2.4/1/gnu-9.1.0-openmpi-4.0
. If the order were
reversed, the openmpi-4.0
would precede the gnu-9.1.0
. Because the MPI requirement
is optional, if gnu/9.1.0
was loaded and no MPI library loaded, the path would
evaluate to $swroot/foo/2.4/1/gnu-9.1.0
.
We show how it works below:
[mod4-flavours]$ module purge
[mod4-flavours]$ module load pgi/19.4
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (pgi/19.4, nompi)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module load openmpi/3.1
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/3.1 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (pgi/19.4, openmpi/3.1)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module unload openmpi
[mod4-flavours]$ module switch pgi intel/2019
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (intel/2019, nompi)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module load intelmpi
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) intelmpi/default 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (intel/2019, intelmpi)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module switch intelmpi mvapich/2.3.1
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) mvapich/2.3.1 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (intel/2019, mvapich/2.3.1)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module switch mvapich openmpi/4.0
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (intel/2019, openmpi/4.0)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module unload openmpi
[mod4-flavours]$ module switch intel/2019 gnu/9.1.0
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module load mvapich/2.3.1
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) mvapich/2.3.1 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (gcc/9.1.0, mvapich/2.3.1)
[mod4-flavours]$ module unload foo
[mod4-flavours]$ module switch mvapich openmpi/4.0
[mod4-flavours]$ module load foo/2.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) openmpi/4.0 3) foo/2.4
[mod4-flavours]$ foo
foo 2.4 (gcc/9.1.0, openmpi/4.0)
So basically, if the user loads a compiler, the
the environment variables (PATH
, etc) are set up for the correct build of foo.
If no MPI library was loaded, a version of foo built without MPI will be loaded,
otherwise, a version of foo built with the loaded MPI library will be loaded.
This is shown by the output of the foo
command. Note
also how we use the dummy intelmpi
package to indicate a desire for the
intelmpi enabled version.
The 3.x version of Environment Modules supports using the switch command on either the compiler or MPI library, and will result in reloading of foo and the MPI library.
[mod3-flavours]$ module purge
[mod3-flavours]$ module load pgi/18.4
[mod3-flavours]$ module load openmpi/3.1
[mod3-flavours]$ module load foo/1.1
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 2) openmpi/3.1 3) foo/1.1
[mod3-flavours]$ foo
foo 1.1 (pgi/18.4, openmpi/3.1)
[mod3-flavours]$ module switch pgi intel/2018
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2018 2) openmpi/3.1 3) foo/1.1
[mod3-flavours]$ foo
foo 1.1 (intel/2018, openmpi/3.1)
[mod3-flavours]$ mpirun
mpirun (openmpi/3.1, intel/2018)
[mod3-flavours]$ module purge
[mod3-flavours]$ module load intel/2019
[mod3-flavours]$ module load foo
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod3-flavours]$ foo
foo 2.4 (intel/2019, nompi)
[mod3-flavours]$ module load openmpi
[mod3-flavours]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4 3) openmpi/4.0
[mod3-flavours]$ foo
foo 2.4 (intel/2019, openmpi/4.0)
In particular note the final case, wherein we load intel/2019
then foo, and get the
version of foo built without MPI. When we subsequently load openmpi, foo is reloaded
to be the openmpi version (this is because the hooks to reload foo are in the flavours cleanup
part of the openmpi modulefile, and foo declared its optional dependency on MPI).
Also, we don't bother showing it, but if you were to attempt to load foo without
at least a compiler loaded, it would display an error.
Our final example for flavours is the bar
command. Here in addition to the
compiler dependency, we have versions for different SIMD vectorization supported.
Again, the difference in the modulefile is small, e.g.
# Common stuff for "bar" modulefiles
# Using "flavours" strategy
#
# Expects the following Tcl variables to have been previously set:
# version: version of bar
# Initialise "flavours"
package require flavours
flavours init
proc ModulesHelp { } {
global version
puts stderr "
bar: Test dummy version of bar $version
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy bar $version"
# Construct flavour name
flavours prereq -class compiler
flavours prereq simd
flavours conflict bar
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
flavours root $swroot/bar/$version
flavours revision 1
flavours commit
# Set environment variables
setenv BAR_DIR [flavours path]
# Prepend to environment variables (paths relative to
# the directory containing the flavour)
flavours prepend-path PATH bin
flavours prepend-path LIBRARY_PATH lib
flavours prepend-path LD_LIBRARY_PATH lib
flavours prepend-path CPATH include
# Reload any modules with this as a prerequisite
flavours cleanup
Basically, the optional flavours prereq
on the mpi class from the foo
package
is replaced by a (mandatory) flavours prereq
on the simd
dummy package.
We note that Flavours package knows nothing about our simd
dummy package until
we add it as a prereq for bar. (This is in contrast to the compiler and mpi classes).
Usage would be like:
[mod4-flavours]$ module purge
[mod4-flavours]$ module load gnu/9.1.0
[mod4-flavours]$ module load simd/avx2
[mod4-flavours]$ module load bar/5.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) simd/avx2 3) bar/5.4
[mod4-flavours]$ bar
bar 5.4 (gcc/9.1.0, avx2)
[mod4-flavours]$ module unload bar
[mod4-flavours]$ module switch simd simd/avx
[mod4-flavours]$ module load bar/5.4
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) simd/avx 3) bar/5.4
[mod4-flavours]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4-flavours]$ module unload bar
[mod4-flavours]$ module switch simd simd/sse4.1
[mod4-flavours]$ module load bar/5.4
bar/5.4 - no flavour compatible with modules 'gnu/9.1.0 simd/sse4.1'
Loading bar/5.4
ERROR: Module evaluation aborted
[mod4-flavours]$ module list
Currently Loaded Modulefiles:
1) gnu/9.1.0 2) simd/sse4.1
Here we note that as both the compiler and simd prereqs are non-optional, it complains
unless both have been previously loaded. When both have been loaded, the PATH
and
other environment variables are set appropriately for the requested build; and if
it does not exist and error is produced.
Summary of Flavours¶
- It is an external extension to Environment Modules, requiring additional installation steps.
- The git repository appears to have been last updated in 2013; although which means that it has not been updated for Environment Modules 4.x, a simple experimentation indicates that it still works, with the exception of automatic reloading of a module if any of the modules it depends on are switched. However, the Flavours extension does not appear to be actively supported.
- The Flavours package (using Environment Modules 3.x) fully supports the
module switch
syntax, with the switching out of a dependency (e.g. a compiler) causing the reload of all modulefiles depending on it. (however the test of this feature failed when using Environment Modules 4.x.) - The syntax for modulefiles is elegant, and one can easily extend the basic compiler dependency modulefile to add additional dependencies. Even for packages/dummy packages that the Flavours extension knows nothing about (e.g. simd in the above example).
- The Flavours package will provide a shorter module avail output, only e.g. giving package name and version and not listing a separate modulefile for each combination of package, version, compiler+version, MPI library+version, etc.
- The Flavours package will fail with an error message if user tries to load a package which was not built for the values of the dependency packages loaded.
- The Flavours package will fail to load with an error message if any dependent package is not already loaded. In particular, it will not attempt to default these. So if such defaults are desired, you will need to have initialization scripts automatically load the appropriate modules.
- The Flavours package does not include any mechanism for more intelligent defaulting. I.e., if an
user requests to load a package without specifying the version desired, the version will be defaulted
to the latest version (or whatever the
.modulerc
file specifies) without regard for which versions support the versions of the compiler and other prereq-ed packages the user has loaded. While one could write custom.modulerc
files for such, Flavours does not provide any tools for simplifying such.
Homebrewed Flavors Strategy¶
Although the Flavours extension described above has an elegance about it, one can achieve much of the same functionality in modulefiles using standard Environment Modules and Tcl commands. This can be facilitated by the definition of some useful Tcl procedures. For lack of a better name, we will refer to this strategy as Homebrewed flavors.
Implementation¶
This strategy just makes use of standard Environment Modules and Tcl procedures
to query what modules of a given type are loaded and to construct the path to the
software package accordingly. To avoid needless (and error prone) repetition of
code, we collect these into several Tcl procedures of our own. Ideally, these
should be placed in a site configuration Tcl file and exposed to modulefiles
as explained in the cookbook Expose procedures and variables to modulefiles.
However, to avoid the need for that in these examples, we instead have placed them
into a file and use the MOD_GIT_ROOTDIR
to locate and source that file in the
relevant modulefiles. (Actually, we have a single tcl file that is sourced both
for this and some other strategies, and it sources several files so that we can
break up the discussion of the the Tcl procedures. All of that is just for the
purposes of this cookbook; normally you just put the procedures you need in the
one site config file).
We discuss the various Tcl procedures here, as they are what provide most of the functionality. We start with the routines for generic loaded modules:
#--------------------------------------------------------------------
# GetLoadedModules
#
# Returns a tcl list of all modules loaded. From $ENV{LOADEDMODULES}
proc GetLoadedModules { } {
global env
#Handle case if no modules loaded
if { [info exists env(LOADEDMODULES)] == 0 } {
#No modules loaded, return empty list
return [ list ]
}
set loadedenv $env(LOADEDMODULES)
set loaded [ split $loadedenv : ]
return $loaded
}
#--------------------------------------------------------------------
# GetTagOfModuleLoaded(pkg)
#
# Looks for a loaded module matching ^$pkg/, and returns the tag matched.
# Returns {} if no tags matched (i.e. module pkg not loaded)
proc GetTagOfModuleLoaded { mymodule } {
set loadedlist [ GetLoadedModules ]
set regex "^$mymodule/"
set fndidx [ lsearch -regex $loadedlist $regex ]
if { $fndidx == -1 } { return {} }
set found [ lindex $loadedlist $fndidx ]
return $found
}
This defines the two Tcl procedures:
- GetLoadedModules : this returns the list of loaded modules, from the
LOADEDMODULES
- GetTagOfModuleLoaded : this takes as argument the base name of a package, and returns the first full spec for the matching package, or an empty string if no matching package found.
The Tcl procedure GetTagOfModuleLoaded can be used to find out what version of a given package is loaded, and is enough for many packages. However, for compilers, and similar, a bit more is needed. For compilers:
#--------------------------------------------------------------------
# GetDefaultCompiler:
#
# Returns the default compiler, gcc/8.2.0
proc GetDefaultCompiler { } {
return "gcc/8.2.0"
}
#--------------------------------------------------------------------
# RequireCompiler:
#
# Does a module load of specified compiler $mycomp.
# Includes special handling if $mycomp is the default compiler
proc RequireCompiler { mycomp } {
# If your module tree is set up so that there is no module for the
# default compiler (because e.g. it is available w/out loading a module
# anyway), you can uncomment the following block which will cause
# RequireCompiler to do nothing if mycomp is the default compiler
#set defComp [GetDefaultCompiler]
#if { $mycomp eq $defComp } {
#return
#}
module load $mycomp
}
#--------------------------------------------------------------------
# GetKnownCompilerFamilies:
#
# Returns a list of recognized compiler family names
#E.g. gcc, intel, pgi
proc GetKnownCompilerFamilies { } {
set cfamilies {gcc intel pgi}
return $cfamilies
}
#--------------------------------------------------------------------
# GetLoadedCompiler:
#
# Returns the string for the compiler we are using (i.e. was previously
# module loaded). E.g., gcc/8.2.0
# If no compiler was previously loaded, then if the optional parameter
# $pathDefault is set, it will look for a compiler family and
# version in the last components to the path to the current modulefile or
# .modulerc, and if found, uses that.
# If still no path found, it will return the value of [GetDefaultCompiler]
# if $useDefault is set.
# Otherwise, returns empty string.
#
# Takes the following arguments:
# pathDefault: boolean, default false. If set, attempt to determine
# the compiler from the full path to the modulefile if
# no compiler was loaded.
# useDefault: boolean, default false. If set, return the value of
# GetDefaultCompiler if no compiler is loaded or found from
# path (if $pathDefault).
# loadIt: boolean, default false. If set and a compiler
# was defaulted from path of GetDefaultCompiler, we will
# module load that compiler.
# Ignored unless either pathDefault or useDefault is set
# requireIt: boolean, default false. If set, we will prereq the
# compiler before returning.
proc GetLoadedCompiler {{pathDefault 0} { useDefault 0}
{loadIt 0 } { requireIt 0 } } {
global ModulesCurrentModulefile
set ctag {}
set cfams [ GetKnownCompilerFamilies ]
foreach cfam $cfams {
if { [ is-loaded $cfam ] } {
set ctag [ GetTagOfModuleLoaded $cfam ]
if { $requireIt } { prereq $ctag }
return $ctag
}
}
# No loaded compiler found, try to default from path to modulefile?
if { $pathDefault} {
set moduledir [file dirname $ModulesCurrentModulefile ]
set cversion [file tail $moduledir]
set tmppath [file dirname $moduledir]
set cfamily [file tail $tmppath]
if { [lsearch $cfams $cfamily] > -1 } {
# We matched a known compiler family in our path
set ctag "$cfamily/$cversion"
if { $loadIt } { RequireCompiler $ctag }
if { $requireIt } { prereq $ctag }
return $ctag
}
}
# Still no compiler, default to GetDefaultCompiler>
if { $useDefault } {
set ctag [ GetDefaultCompiler ]
if { $loadIt } { RequireCompiler $ctag }
if { $requireIt } { prereq $ctag }
return $ctag
}
#Nothing found, and not defaulting
return $ctag
}
We defined four procedures above:
- GetDefaultCompiler : this simply returns the name of our default compiler, which for
this example is
gcc/8.2.0
- RequireCompiler : this simply does a module load on the specified compiler.
It is kept as a separate procedure just in case you wish to intercept and prevent
the loading of the default compiler (e.g. because no modulefile exists for it).
In our example, there is a modulefile for it and so it is just a wrapper for
module load
. - GetKnownCompilerFamilies : this simply returns a Tcl list of known compiler families.
- GetLoadedCompiler: this is the procedure that does the main work, and is described in detail below.
The GetLoadedCompiler procedure basically checks if any packages matching
the names in GetKnownCompilerFamilies have been previously loaded. If so,
it returns the modulefile specification for the first one found, and returns.
If not, if pathDefault
is set and there is a recognized compiler name and version
in the last two components of the module specification, it will return
that compiler. Otherwise, if the optional flag useDefault
is set, it will return the
value from GetDefaultCompiler. If all else fails, returns the empty string.
If the optional parameter loadIt
is set, if a compiler was defaulted (i.e.
not returned because it was already loaded), the procedure will call RequireCompiler
to module load it.
If the optional parameter requireIt
is set, we invoke prereq
on the compiler
found before returning.
A similar set of procedures exist for the MPI libraries, namely:
#--------------------------------------------------------------------
# RequireMPI:
#
# Does a module load of specified MPI library $mympi
# Includes special handling if $mympi is nompi or intelmpi (or one of its aliases)
# If $mympi is nompi, nothing is loaded.
# If the optional parameter noLoadIntel is set (default false), and if
# $mympi is intelmpi (or intel or impi), then we do not load module if
# the loaded compiler is intel (as we assume that provides intel MPI as well)
proc RequireMPI { mympi {noLoadIntel 0} } {
# We do not do anything if mympi is nompi
if { $mympi eq {nompi} } { return }
if { $noLoadIntel } {
# Get the basename of requested MPI library
set mympiSplit [ split $mympi / ]
set mympiBase [ lindex $mympiSplit 0 ]
# Check if we requested an intel MPI
set intelList "intelmpi impi intel intelmpi-mt impi-mt intel-mt"
if { [lsearch $intelList $mympiBase ] > -1 } {
# We requested intelmpi in some form
# Check if an intel compiler was loaded
set curComp [ GetLoadedCompiler 1]
if { $curComp ne {} } {
set curCompSplit [ split $curComp / ]
set curCompBase [ lindex $curCompSplit 0 ]
if { $curCompBase eq {intel} } {
# $noLoadIntel is set, requested MPI is intel MPI, and intel compiler loaded
return
}
}
}
}
module load $mympi
}
#--------------------------------------------------------------------
# GetKnownMpiFamilies:
#
# Returns a list of recognized MPI library family names
#E.g. gcc, intel, pgi
proc GetKnownMpiFamilies { } {
set mfamilies {openmpi mpavich intelmpi}
return $mfamilies
}
#--------------------------------------------------------------------
# GetLoadedMPI:
#
# Returns the string for the MPI library we are using (i.e. was previously
# module loaded), or empty string if nothing loaded (from is-loaded command)
# E.g., intel/2013.1.117
# Takes an optional argument,
# useIntel: boolean, default false. If set, returns 'intelmpi' if
# no MPI library is loaded but intel compiler is loaded
# forceIt: boolean, default false. If set, prereq MPI lib before returning.
# requireIt: boolean, default false. If set, prereq the MPI library
proc GetLoadedMPI { { useIntel 0} {forceIt 0} {requireIt 0} } {
set mtag {}
foreach mfam [ GetKnownMpiFamilies ] {
if { [ is-loaded $mfam ] } {
set mtag [ GetTagOfModuleLoaded $mfam ]
if { $requireIt } { prereq $ctag }
return $mtag
}
}
# No loaded compiler found, should we check for Intel compiler and return intelmpi?
if { $useIntel } {
#Yes
set ctag [ GetCompilerLoaded ]
set cSplit [ split $ctag / ]
set cBase [ lindex $cSplit 0 ]
if { $cBase eq intel } { return intelmpi }
}
return $mtag
}
The three procedures here are analogues of the compiler versions:
- RequireMPI : this basically does a module load of the specified MPI library. It
has some added logic so that it will not do a module load if the MPI library is
nompi
. Also, if the optional parameternoLoadIntel
is set, if the MPI library isintelmpi
(or a variant of that name) and the loaded compiler inintel
, we assume that no additional module needs to be loaded. For this strategy, we want to loadintelmpi
modules, because, just like in the Flavours Strategy, we need to provide dummyintelmpi
modules to allow one to request the use of the Intel MPI library. - GetKnownMpiFamilies : this returns a list of known MPI library family names. Used in GetLoadedMPI
- GetLoadedMPI : This is the analogue of GetLoadedCompiler. If an MPI library is
loaded, it will return the name of that module. If the optional
requireIt
flag is set, it will do aprereq
on the MPI library before returning. The first optional argument,useIntel
, indicates whether this module should returnintelmpi
if no MPI library is loaded but an Intel compiler is loaded.
The modulefiles for the compilers are basically standard; unlike the
Flavours Strategy there is nothing special needed in these. Likewise
for the dummy simd
and intelmpi
modules (the latter is only this
basic because we assume intelmpi is only available if an Intel compiler
is loaded. If one allowed for intelmpi with other compilers, it would
more closely resemble the other MPI libraries).
We also define some Tcl procedures for generating warning and error messages, namely
#--------------------------------------------------------------------
# PrintIfLoading:
#
# Prints supplied text to stderr but only if in "load" mode
proc PrintIfLoading { args } {
if [ module-info mode load ] {
set tmp [ join $args ]
puts stderr "$tmp"
}
}
#--------------------------------------------------------------------
# PrintLoadInfo:
#
# Prints supplied text to stderr as informational message, but only
# if actually trying to load the module.
proc PrintLoadInfo { args } {
set tmp [ join $args ]
PrintIfLoading "
\[INFO\] $tmp
"
}
#--------------------------------------------------------------------
# PrintLoadWarning:
#
# Prints supplied text to stderr as warning message, but only
# if actually trying to load the module.
proc PrintLoadWarning { args } {
set tmp [ join $args ]
PrintIfLoading "
WARNING:
$tmp
"
}
#--------------------------------------------------------------------
# PrintLoadError:
#
# Like PrintLoadWarning, but as error message and does a "break"
proc PrintLoadError { args } {
set tmp [ join $args ]
PrintIfLoading "
**** ERROR *****:
$tmp
"
if [ module-info mode load ] {
break
}
}
These procedures:
- PrintIfLoading: will print supplied text to stderr only when in
load
mode - PrintLoadInfo: will print supplied text as informational text, but only when trying to load a module
- PrintLoadWarning: will print supplied text as warning text, but only when trying to load a module
- PrintLoadError: will print supplied text as error text and abort, but only when trying to load a module
The gist of this is that we might wish to print errors if an user tries to load an incompatible modulefile, but do not wish to print errors if they are merely doing a help, display, or whatis command.
The interesting bit begins with the openmpi and mvapich modulefiles. These both depend on the compiler, we show the main part of the openmpi modulefile below:
# Common modulefile for openmpi
# Using "homebrewed flavors" strategy
# Expects the following variables to have been
# previously defined:
# version: version of openmpi
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
# Also get location of and load common procedures
# This is a hack for the cookbook examples, in production
# one should either
# 1) declare the procedures in a site config file (preferred)
# 2) hardcode the path to $tcllibdir and common_utilities.tcl
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
proc ModulesHelp { } {
global version
puts stderr "
openmpi: Test dummy version of OpenMPI $version
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy openmpi $version"
# Figure out what compiler we have loaded
# Optional args ensure will default to and load/prereq default compiler
# if no compiler currently loaded
set ctag [ GetLoadedCompiler 1 1 1 ]
# Compute the installation prefix
set pkgroot $swroot/openmpi
set vroot $pkgroot/$version
set prefix $vroot/$ctag
# Make sure there is a build for this openmpi version/compiler
# I.e. that the prefix exists
if ![ file exists $prefix ] {
# Not built for this compiler, alert user and abort
PrintLoadError "
openmpi/$version does not appear to be built for compiler $ctag
Please select a different openmpi version or different compiler.
"
}
# We need to prereq the compiler to allow autohandling to work
prereq $ctag
# Set environment variables
setenv MPI_DIR $prefix
set bindir $prefix/bin
set libdir $prefix/lib
set incdir $prefix/include
prepend-path PATH $bindir
prepend-path LIBRARY_PATH $libdir
prepend-path LD_LIBRARY_PATH $libdir
prepend-path CPATH $incdir
We begin by sourcing the common_utilities
file which defined the previously
described Tcl procedures. Normally it is recommended that you put those
procedures in a site config Tcl script and expose them to the modulefiles
using the techniques described in the cookbook Expose procedures and variables to modulefiles.
Even if you opt against that and decide to source a Tcl file, it is recommended
to hard code the path.
The next interesting bit comes when we set the local Tcl variable ctag
by calling the GetLoadedCompiler
procedure. We allow the procedure to
default the compiler, and because we have a default compiler defined we
should always get a value. (If no default compiler was defined, one would
have to handle the error if no compiler was loaded/defaulted.) We then use
the value of ctag
to set the path to the build of the package. To ensure
that the package is built for this compiler, we do a quick check that the
package installation path exists.
The modulefile for foo
is a bit more complex:
# Common stuff for "foo" modulefiles
# Using "homebrewed flavors" strategy
#
# This file expects the following Tcl variables to have been
# previously set:
# version: version of foo
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
# Also get location of and load common procedures
# This is a hack for the cookbook examples, in production
# one should either
# 1) declare the procedures in a site config file (preferred)
# 2) hardcode the path to $tcllibdir and common_utilities.tcl
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
proc ModulesHelp { } {
global version
puts stderr "
foo: Test dummy version of foo $version
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy foo $version"
# Figure out what compiler we have loaded
# Will default to and load default compiler if none loaded
set ctag [ GetLoadedCompiler 1 1 1 ]
# Figure out what MPI we have loaded
# We do NOT want to default to intelmpi if intel compiler loaded
set mtag [ GetLoadedMPI ]
# Set mtag it nompi if no MPI library found loaded
if { $mtag eq {} } { set mtag nompi }
# Set mtag to intelmpi if intelmpi/default found loaded
if { $mtag eq {intelmpi/default} } { set mtag intelmpi }
# Compute the installation prefix
set pkgroot $swroot/foo
set vroot $pkgroot/$version
set prefix $vroot/$ctag/$mtag
# Make sure there is a build for this foo version/compiler/MPI library
# I.e. that the prefix exists
if ![ file exists $prefix ] {
# Not built for this compiler/MPI, alert user and abort
PrintLoadError "
foo/$version does not appear to be built for compiler $ctag and MPI $mtag
Please select a different openmpi version or different compiler/MPI library combination.
"
}
# We need to prereq the compiler to allow autohandling to work
prereq $ctag
# and the MPI library if used
if { $mtag ne {nompi} } {
# We currently require one to load intelmpi to use Intel MPI with
# intel compilers. So we prereq on intelmpi as well
# But if not, we could place the prereq below in an if-then block
# so is only executed if mtag != intelmpi
prereq $mtag
}
# Set environment variables
setenv FOO_DIR $prefix
set bindir $prefix/bin
set libdir $prefix/lib
set incdir $prefix/include
prepend-path PATH $bindir
prepend-path LIBRARY_PATH $libdir
prepend-path LD_LIBRARY_PATH $libdir
prepend-path CPATH $incdir
conflict foo
The main difference between this modulefile, depending on both compiler and
optionally MPI, and the openmpi modulefile above, is that in addition to
detecting which compiler is loaded, we call GetLoadedMPI
to determine
the MPI library which was loaded, and use both of them in constructing the
prefix to the installed foo.
Examples¶
We now look at the example modulefiles for the Homebrewed flavors strategy.
To use the examples, you must
#. Set (and export) MOD_GIT_ROOTDIR
to where you git-cloned the modules source
#. Do a module purge
, and then set your MODULEPATH
to:
$MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/homebrewed
The Homebrewed flavors strategy behaves much like the Flavours Strategy in practice. The module avail command,
[mod4 (homebrewed)]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/homebrewed -
bar/4.7 foo/2.4 intel/2018 mvapich/2.1 openmpi/4.0 simd/avx
bar/5.4 gcc/8.2.0 intel/2019 mvapich/2.3.1 pgi/18.4 simd/avx2
foo/1.1 gcc/9.1.0 intelmpi/default openmpi/3.1 pgi/19.4 simd/sse4.1
looks basically the same, showing the a concise listing of packages and versions without information on the compilers and MPI libraries they were built with.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load pgi/19.4
[mod4 (homebrewed)]$ module load openmpi/4.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (homebrewed)]$ module unload openmpi
[mod4 (homebrewed)]$ module switch --auto pgi intel/2019
[mod4 (homebrewed)]$ module load openmpi/4.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4 (homebrewed)]$ module unload openmpi
[mod4 (homebrewed)]$ module switch --auto intel gcc/9.1.0
[mod4 (homebrewed)]$ module load openmpi/4.0
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, gcc/9.1.0)
[mod4 (homebrewed)]$ module unload openmpi
[mod4 (homebrewed)]$ module switch --auto gcc gcc/8.2.0
[mod4 (homebrewed)]$ module load openmpi/4.0
**** ERROR *****:
openmpi/4.0 does not appear to be built for compiler gcc/8.2.0
Please select a different openmpi version or different compiler.
Loading openmpi/4.0
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0
Again, once a compiler is loaded, loading openmpi will set the PATH
, etc. for
the correct build of openmpi, as evidenced by the output of the dummy
mpirun command. Notice that the module list
command only shows
the version of openmpi loaded, and contains no information about what
compiler it was built with (you just have to assume it matches the loaded
compiler). And again we note that if one attempts to load a version
of openmpi (e.g. 4.0
) that was not built for the specified compiler (e.g.
gcc/8.2.0
), an error is generated.
Unlike in Flavours Strategy, we did not put any code in the modulefiles to cause
dependent modulefiles to be reloaded if a module they depend on gets switched
out. However, starting with Environment Modules 4.2
, a feature called
Automated module handling was added. Without this feature, attempting to
switch out a module upon which other modules depended could be problematic,
as evidenced in this sequence below (using Environment Modules 3.2.10
and
so without automated module handling mode):
[mod3 (homebrewed)]$ module purge
[mod3 (homebrewed)]$ module load pgi/19.4
[mod3 (homebrewed)]$ module load openmpi
[mod3 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod3 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod3 (homebrewed)]$ module switch pgi intel/2019
[mod3 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod3 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
Here we note that we were able to switch out the pgi compiler for the intel compiler, but the openmpi module was not reloaded and the environment is still set for openmpi compiled with the pgi compiler, and that this inconsistency is not readily determined from the module list command.
Environment Modules 4.x, even with automated module handling disabled, is better ---
in a command sequence as above the module switch from pgi to intel would fail due to the
prereq module. However, with the Automated module handling
enabled (this feature is disabled by default but could be enabled on a per-command basis with the --auto
flag), things work much better, as evidenced below:
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load pgi/19.4
[mod4 (homebrewed)]$ module load openmpi
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (homebrewed)]$ module switch --auto pgi intel/2019
Switching from pgi/19.4 to intel/2019
Unloading dependent: openmpi/4.0
Reloading dependent: openmpi/4.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4 (homebrewed)]$ module switch --auto intel intel/2018
**** ERROR *****:
openmpi/4.0 does not appear to be built for compiler intel/2018
Please select a different openmpi version or different compiler.
Loading openmpi/4.0
ERROR: Module evaluation aborted
Switching from intel/2019 to intel/2018
WARNING: Reload of dependent openmpi/4.0 failed
Unloading dependent: openmpi/4.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2018
[mod4 (homebrewed)]$ mpirun
mpirun: command not found
When we switch out the pgi compiler for the intel/2019
compiler, the openmpi
module is automatically unloaded before the compiler switch and reload afterwards,
so we end up with the correct build of openmpi for the newly loaded intel/2019
compiler. If one then switches out intel/2019
replacing it with intel/2018
,
the openmpi module is first unloaded, the compilers are switched, and as there
is no openmpi/4.0
build for intel/2018
, a warning is given and the openmpi module
is left unloaded. Since the user never specifically requested version 4.0
of openmpi
(it was defaulted in the original module load of openmpi as that was the latest version
available for pgi/19.4
), it would have been nicer if on the switch of intel compiler
versions the reload only attempted a module load openmpi
instead of module load openmpi/4.0
,
but nevertheless this well behaved. The openmpi module is dropped with a warning and the
user has a consistent set of modules loaded.
We note that the modulefile is able to default the compiler, so when we attempt to load openmpi without having previously loaded a compiler, as in
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load openmpi/3.1
Loading openmpi/3.1
Loading requirement: gcc/8.2.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) openmpi/3.1
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/3.1, gcc/8.2.0)
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load gcc/8.2.0
[mod4 (homebrewed)]$ module load openmpi
**** ERROR *****:
openmpi/4.0 does not appear to be built for compiler gcc/8.2.0
Please select a different openmpi version or different compiler.
Loading openmpi/4.0
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0
it will default to the default compiler, gcc/8.2.0
. Note however, that if
one does not specify version 3.1
of openmpi, it will still default to 4.0
and fail to load as there is no build of openmpi/4.0
for gcc/8.2.0
.
The situation is similar for foo:
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load pgi/19.4
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (pgi/19.4, nompi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module load openmpi/3.1
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/3.1 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (pgi/19.4, openmpi/3.1)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module unload openmpi
[mod4 (homebrewed)]$ module switch --auto pgi intel/2019
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module load intelmpi
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) intelmpi/default 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, intelmpi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module switch --auto intelmpi mvapich/2.3.1
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) mvapich/2.3.1 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module switch --auto mvapich openmpi/4.0
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, openmpi/4.0)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module unload openmpi
[mod4 (homebrewed)]$ module switch --auto intel/2019 gcc/9.1.0
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module load mvapich/2.3.1
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) mvapich/2.3.1 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4 (homebrewed)]$ module unload foo
[mod4 (homebrewed)]$ module switch --auto mvapich openmpi/4.0
[mod4 (homebrewed)]$ module load foo/2.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) openmpi/4.0 3) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (gcc/9.1.0, openmpi/4.0)
Again, one can load a compiler without an MPI library to get the non-MPI version of foo, or a compiler and MPI library to get the MPI version. The dummy intelmpi modulefile is used to allow one to indicate that the Intel MPI library is desired. The automated module handling mode can again allow the switch functionality work properly, as in
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load pgi/18.4
[mod4 (homebrewed)]$ module load openmpi/3.1
[mod4 (homebrewed)]$ module load foo/1.1
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 2) openmpi/3.1 3) foo/1.1
[mod4 (homebrewed)]$ foo
foo 1.1 (pgi/18.4, openmpi/3.1)
[mod4 (homebrewed)]$ module switch --auto pgi intel/2018
Switching from pgi/18.4 to intel/2018
Unloading dependent: foo/1.1 openmpi/3.1
Reloading dependent: openmpi/3.1 foo/1.1
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2018 2) openmpi/3.1 3) foo/1.1
[mod4 (homebrewed)]$ foo
foo 1.1 (intel/2018, openmpi/3.1)
[mod4 (homebrewed)]$ mpirun
mpirun (openmpi/3.1, intel/2018)
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load intel/2019
[mod4 (homebrewed)]$ module load foo
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (homebrewed)]$ module load openmpi
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4 3) openmpi/4.0
[mod4 (homebrewed)]$ foo
foo 2.4 (intel/2019, nompi)
Here we note a deficiency in the switch support as compared to Flavours Strategy. In the last example
after loading intel/2019
and foo, we have the non-MPI build of foo as expected. However, upon
subsequently loading the openmpi module, we still have the non-MPI version of foo loaded, as evidenced
by the output of the dummy foo command. I.e., the foo package was not automatically reloaded, as
there was no prereq in the foo modulefile on an MPI library (as in the non-MPI build there is no MPI
library to prereq). Also note that module list does not really inform one of this fact.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load foo
**** ERROR *****:
foo/2.4 does not appear to be built for compiler gcc/8.2.0 and MPI nompi
Please select a different openmpi version or different compiler/MPI library combination.
Loading foo/2.4
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
No Modulefiles Currently Loaded.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load foo/1.1
Loading foo/1.1
Loading requirement: gcc/8.2.0
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) foo/1.1
[mod4 (homebrewed)]$ foo
foo 1.1 (gcc/8.2.0, nompi)
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load pgi/18.4
[mod4 (homebrewed)]$ module load foo
**** ERROR *****:
foo/2.4 does not appear to be built for compiler pgi/18.4 and MPI nompi
Please select a different openmpi version or different compiler/MPI library combination.
Loading foo/2.4
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4
Above, we see once more that the compiler can be defaulted, but that the defaulting mechanism is not smart enough to default the version of foo based on the compiler loaded (or defaulted to).
The situation with bar is basically the same; with a compiler and simd module loaded, the environment for the appropriate build of bar is loaded when you module load bar.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load gcc/9.1.0
[mod4 (homebrewed)]$ module load simd/avx2
[mod4 (homebrewed)]$ module load bar/5.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) simd/avx2 3) bar/5.4
[mod4 (homebrewed)]$ bar
bar 5.4 (gcc/9.1.0, avx2)
[mod4 (homebrewed)]$ module unload bar
[mod4 (homebrewed)]$ module switch --auto simd simd/avx
[mod4 (homebrewed)]$ module load bar/5.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) simd/avx 3) bar/5.4
[mod4 (homebrewed)]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4 (homebrewed)]$ module unload bar
[mod4 (homebrewed)]$ module switch --auto simd simd/sse4.1
[mod4 (homebrewed)]$ module load bar/5.4
**** ERROR *****:
foo/5.4 does not appear to be built for compiler gcc/9.1.0 and simd/sse4.1
Please select a different openmpi version or different compiler/simd combination.
Loading bar/5.4
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) simd/sse4.1
And an error is generated if there is no build for that combination of compiler and simd. The automatic handling of modules again allows the switch command to work as expected:
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load gcc/9.1.0
[mod4 (homebrewed)]$ module load simd/avx
[mod4 (homebrewed)]$ module load bar/5.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) simd/avx 3) bar/5.4
[mod4 (homebrewed)]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4 (homebrewed)]$ module switch --auto simd simd/avx2
Switching from simd/avx to simd/avx2
Unloading dependent: bar/5.4
Reloading dependent: bar/5.4
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) simd/avx2 3) bar/5.4
[mod4 (homebrewed)]$ bar
bar 5.4 (gcc/9.1.0, avx2)
and both the simd level and compiler can be defaulted, but one still has to choose a version of bar which supports the defaults.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load bar
[INFO] Setting simd to simd/sse4.1
**** ERROR *****:
foo/5.4 does not appear to be built for compiler gcc/8.2.0 and simd/sse4.1
Please select a different openmpi version or different compiler/simd combination.
Loading bar/5.4
ERROR: Module evaluation aborted
[mod4 (homebrewed)]$ module list
No Modulefiles Currently Loaded.
[mod4 (homebrewed)]$ module purge
[mod4 (homebrewed)]$ module load bar/4.7
[INFO] Setting simd to simd/sse4.1
Loading bar/4.7
Loading requirement: gcc/8.2.0 simd/sse4.1
[mod4 (homebrewed)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) simd/sse4.1 3) bar/4.7
[mod4 (homebrewed)]$ bar
bar 4.7 (gcc/8.2.0, sse4.1)
Summary of Homebrewed flavors strategy¶
- The Automated module handling feature (introduced in Environment Modules
4.2
) allows for the switching out of a dependency (e.g. a compiler) to cause the reload of all modulefiles depending on it. Without the automated module handling (as is default for 4.x, and the only option for 3.x), the switching of a compiler only changes the compiler and leaves the modulefiles that depend on the compiler unchanged. - The various Tcl procedures make it somewhat easy to determine which compiler, MPI, etc. modules have been loaded and set the paths appropriately. Not as elegant or easy to use as Flavours Strategy, but not difficult
- Like the Flavours package, the module avail output is concise, only e.g. giving package name and version rather than listing a separate modulefile for each combination of package, version, compiler+version, MPI library+version, etc.
- Modules will fail with an error message if user tries to load a package which was not built for the values of the dependency packages loaded.
- With Automated module handling mode, the dependencies of a module asked for load could automatically be loaded. But it requires that these dependencies are clearly specified with mention of the versions for which a build is available.
- It does not include a mechanism for more intelligent defaulting. I.e., if
an user requests to load a package without specifying the version desired,
the version will be defaulted to the latest version (or whatever
the
.modulerc
file specifies) without regard for which versions support the versions of the compiler and other prereq-ed packages the user has loaded. - Note that future releases of Environment Modules will introduce additional mechanisms to the Automated module handling mode, which will improve the user experience on such Homebrewed flavors setup.
Modulerc-based Strategy¶
The previous two strategies used additional code in the modulefile to
determine which compiler, etc. was loaded and adjust the values for
PATH
, etc. accordingly. The Modulerc-based strategy instead uses
.modulerc
files to direct the module command to the proper modulefile
depending on what compiler, etc. was previously loaded. Because of
this, there are a number of differences in behavior and what is seen
by the user, most notably many, many more modulefiles. Whether this is good
or bad is a matter of taste.
Implementation¶
Whereas the Homebrewed Flavors Strategy had the modulefile invoke
a Tcl procedure to determine which, if any, version of a module like a compiler
was loaded and then adjust paths, the Modulerc-based strategy instead
uses the same Tcl procedures to default the modulefile which will be loaded.
This implies that there is a distinct modulefile for every build of the package,
and an immediate consequence is that this strategy has many more modulefiles
than the others. We make use of the techniques in the cookbook
Tips for Code Reuse in Modulefiles to reduce the total amount of code; the actual modulefiles
for each build are typically small stubfiles defining a couple of Tcl variables
and then sourcing a common
script (unique to each package) which does all
the real work.
The modules will be named with components for the different dependencies,
so the one for openmpi version 4.0
built with gcc version 9.1.0
would
be openmpi/4.0/gcc/9.1.0
; similarly the module for foo version 1.1
built for pgi version 18.4
and mvapich 2.1
would be
foo/1.1/pgi/18.4/mvapich/2.1
.
The .modulerc
files themselves are not trivial, but these
can generally be written in a generic fashion, usable by multiple packages,
and can just be symlinked to the appropriate locations.
We define five such files which can be linked as .modulerc
:
Two of these files can be linked in the module tree
at various places as .modulerc
for defaulting the compiler. One to
default to the family portion of the compiler (e.g. gcc, intel, or pgi),
and one for the version. For the family portion of the compiler,
we have the file modulerc.select_compiler_family
as below:
#%Module
# Choose compiler family
#
# This check if any compiler was previously "module loaded", or if no compiler
# previously loaded, will use the default compiler. Either way, it will check
# if there is a subdirectory matching the compiler family name, and if so
# will default to that.
#
# If no subdirectory matching compiler family name is found, we just return
# without defaulting. The modulecmd will default based on its internal rules,
# and it is up to the resulting module file to either load an appropriate
# compiler if no compiler is loaded or to abort with appropriate error
# messages if it wants an incompatible compiler.
#
# Usage:
# In most cases, can simply symlink .modulerc to this file
#
# In more complicated cases, .modulerc can source this file, and can
# then test the variable _did_default, which will be true if we set
# a default for modules for the next level, or false otherwise (in which
# case your .modulerc can set one)
# Source some required Tcl procedures here. Hack for cookbook
# making use of environment variable for location.
# In production, this should ideally be in a site config file.
# At minimum, hardcode the path
set rootdir $::env(MOD_GIT_ROOTDIR)
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
set moduledir [file dirname $ModulesCurrentModulefile]
set baseComponent [ file tail $moduledir ]
# Get the currently loaded compiler, or default comp. Don't module load/prereq it
set fullCompilerTag [ GetLoadedCompiler 1 1 ]
set tmpCompTag [ GetPackageFamilyVersion $fullCompilerTag ]
set compilerFamily [ lindex $tmpCompTag 0 ]
set compFamList "$compilerFamily"
# Allow either gnu or gcc for GCC compilers
if { $compilerFamily eq {gcc} || $compilerFamily eq {gnu} } {
set compFamList "gnu gcc"
}
# _did_default will be true if we actually default something
# Useful in case a .modulerc sources us, and wants to set a default if we
# did not
set _did_default false
if { $compilerFamily ne {} } {
# Default to the family of currently loaded compiler
set firstChild [ FirstChildModuleInList $compFamList ]
if { $firstChild ne {} } {
# Compiler family found, so default to it
module-version $baseComponent/$firstChild default
set _did_default true
}
}
The file starts by sourcing a set of useful Tcl procedures. For the purpose
of the example for this cookbook this is done based on the MOD_GIT_ROOTDIR
environment variable. If you were to use this in production, it is
recommended that the Tcl procedures be placed in a site configuration script
and exposed to modulefiles via the techniques described in the cookbook
Expose procedures and variables to modulefiles. At the minimum, it is
recommended to hardcode the path to the common_utilities.tcl
file.
The modulerc script then determines the directory it is in using the
Tcl variable ModulesCurrentModulefile
. It then uses the
GetLoadedCompiler
Tcl procedure (which was discussed in the section
on the Homebrewed Flavors Strategy. We then parse the resulting module
name into family and version pieces (we will discuss the procedure
GetPackageFamilyVersion
later; for now suffice to say it takes
a module name and returns a Tcl list with family and version).
We do some trickery to support the use of either gcc or gnu as family names for
the GNU compiler suite, and then see if there is a directory or modulefile
underneath the directory containing the .modulerc
file, and if so defaults
to it. For this purpose, we use the Tcl procedure FirstChildModuleInList
(defined in common_utilities.tcl
). This and a related procedure are
defined as:
#--------------------------------------------------------------------
# FirstChildModuleInList
#
# Given a list of names of modulefile components, returns the
# first one found in the directory of the current modulefile
# (typically a .modulerc file). Returns empty string if none
# of them were found.
# NOTE: we do NOT check for module magic signature or even that symlink
# targets exist.
proc FirstChildModuleInList { modlist } {
global ModulesCurrentModulefile
# Get directory for current modulefile
set moduledir [ file dirname $ModulesCurrentModulefile ]
# See if any names in $modlist in moduledir
foreach mcomp $modlist {
if [ file exists $moduledir/$mcomp ] { return $mcomp }
}
# Nothing found
return
}
#--------------------------------------------------------------------
# ChildModuleExists
#
# Takes a module path component, and returns true if that path component
# exists beneath the current level, i.e. in the directory from which
# this .modulerc file was called.
# NOTE: we do NOT check for module magic signature or even that symlink
# targets exist.
proc ChildModuleExists { pathcomponent } {
global ModulesCurrentModulefile
# Get directory for current modulefile
set moduledir [ file dirname $ModulesCurrentModulefile ]
# See if file exists in moduledir
return [ file exists $moduledir/$pathcomponent ]
}
and basically make use of the Tcl variable ModulesCurrentModulefile
. They
are limited, however, in that they will not work properly if the module is
split across multiple modulepaths. That is, ChildModuleExists
and
FirstChildModuleInList
will only detect children in the same directory
as the modulerc file they are called from; e.g., if two paths in the MODULEPATH
both have directories for openmpi, one with an intel subdirectory and one
with a pgi subdirectory and the modulerc invoking ChildModuleExists
, the
ChildModuleExists procedure will not see the intel directory.
The modulerc.select_compiler_version
file is similar,
#%Module
# Choose compiler version
#
# This check if any compiler was previously "module loaded", or if no compiler
# previously loaded, will use the default compiler. Either way, it will check
# if there is a subdirectory matching the compiler family name, and if so
# will default to that.
#
# If no subdirectory matching compiler family name is found, we just return
# without defaulting. The modulecmd will default based on its internal rules,
# and it is up to the resulting module file to either load an appropriate
# compiler if no compiler is loaded or to abort with appropriate error
# messages if it wants an incompatible compiler.
#
# Usage:
# In most cases, can simply symlink .modulerc to this file
#
# In more complicated cases, .modulerc can source this file, and can
# then test the variable _did_default, which will be true if we set
# a default for modules for the next level, or false otherwise (in which
# case your .modulerc can set one)
# Source some required Tcl procedures here. Hack for cookbook
# making use of environment variable for location.
# In production, this should ideally be in a site config file.
# At minimum, hardcode the path
set rootdir $::env(MOD_GIT_ROOTDIR)
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
set moduledir [file dirname $ModulesCurrentModulefile]
set parentdir [ file tail $moduledir ]
# _did_default will be true if we actually default something
# Useful in case a .modulerc sources us, and wants to set a default if we
# did not
set _did_default false
# Get the currently loaded compiler or default, but do not load/prereq it
set compilerTag [ GetLoadedCompiler 1 1 ]
if { $compilerTag ne {} } {
# Compiler loaded or defaulted
# Make sure it matches our parent dir
set tmpCompTag [ GetPackageFamilyVersion $compilerTag ]
set compilerFamily [ lindex $tmpCompTag 0 ]
set compilerVersion [ lindex $tmpCompTag 1 ]
# Convert any gnus to gccs
set tmp1 $compilerFamily
if { $tmp1 eq {gnu} } { set tmp1 gcc }
set tmp2 $parentdir
if { $tmp2 eq {gnu} } { set tmp2 gcc }
if { $tmp1 eq $tmp2 } {
# If reach here, our parent dir agrees with
# the family of our loaded/defaulted compiler
if { $compilerVersion ne {} } {
# We have a version, does a modulefile/dir exist for it
if [ ChildModuleExists $compilerVersion ] {
# There is a modulefile/dir for this compiler version, default to it
module-version $compilerFamily/$compilerVersion default
set _did_default true
}
}
}
}
Again, we source the common_utitilies.tcl
file and use
ModulesCurrentModulefile
to get the directory in which the .modulerc
script resides. It then uses GetLoadedCompiler
to determine what
if any compiler was loaded. If one was, we split into family and version,
and ensure that the directory containing the .modulerc
file matches the
family name. If so, it checks if there is a directory or modulefile in that
directory matching the version name, and if so defaults to it.
For both of the .modulerc
scripts we examined, we note that in case of
errors, etc., the script just exits without defaulting. One might be
tempted to have the .modulerc
script actually return an error in such
cases (perhaps using module-info mode
to only have it output during
load operations). This, however, runs into issues:
- For Environment Modules 3.x: for some reason, when modulecmd processes
.modulerc
scripts,module-info mode load
always returns true. Because of this, users would get spurious errors when doing amodule avail
if the.modulerc
scripts error-ed, because they all get processed regardless of what compiler is loaded. - For versions 4.x: the modulecmd process tends to process all
.modulerc
files underneath the package root during a load, which will similarly generate spurious errors if the.modulerc
scripts throw errors.
Because of this, if an user explicitly requests a modulefile that conflicts
with the loaded compiler (e.g. the user does a module load pgi/19.4
followed by a module load openmpi/4.0/intel/2019
), the modulefile needs
to detect this and error appropriately. A similar situation can happen if
one of the .modulerc
scripts fail to default, presumably because there is no
appropriate build for the requested package; the modulecmd will default to
something, but likely not what is wanted. To facilitate this, we define
the Tcl procedure LoadedCompilerMatches
:
#--------------------------------------------------------------------
# LoadedCompilerMatches:
#
# Takes the tag of the desired compiler $wanted (in form of FAMILY/VERSION)
# Checks if any compiler is loaded, and will throw error if one is
# loaded and it does not match $wanted.
# If compilers match, it will prereq the compiler if $requireIt set
# If no compiler is loaded, will load if optional boolean parameter
# $loadIt is set (default unset), and prereq if $requireIt is set, and
# then return.
# Option parameters:
# requireIt: boolean, default false. If set, require $wanted
# loadIt: boolean, default false. If set, load $wanted if no compiler
# already loaded
# modTag: string, defaults go [module-info specified]. Used in error messages
proc LoadedCompilerMatches { wanted {requireIt 0} { loadIt 0 } {modTag {} } } {
# Default modTag
if { $modTag eq {} } { set modTag [ module-info specified ] }
# If no compiler given in $wanted, just return
if { $wanted eq {} } { return }
# Get loaded compiler (w/out defaults)
set loaded [ GetLoadedCompiler 0 0 ]
# If no compiler is loaded, then require it if asked, and return
if { $loaded eq {} } {
if { $loadIt } {
RequireCompiler $wanted
if { $requireIt } { prereq $wanted }
}
return
}
# Have a loaded compiler, split into family and version
set tmpLoaded [ GetPackageFamilyVersion $loaded ]
set loadedFam [ lindex $tmpLoaded 0 ]
set loadedVer [ lindex $tmpLoaded 1 ]
# Always use 'gcc' not 'gnu'
if { $loadedFam eq {gnu} } { set loadedFam gcc }
# Split wanted into family and version
set tmpWanted [ split $wanted / ]
set wantedLen [ llength $tmpWanted ]
#Nothing to do if no components to wanted
if { $wantedLen < 1 } { return }
set wantedFam [ lindex $tmpWanted 0 ]
# Always use 'gcc' not 'gnu'
if { $wantedFam eq {gnu} } { set wantedFam gcc }
# Ensure families match
if { $loadedFam ne $wantedFam } {
PrintLoadError "Compiler Mismatch
Package $modTag does not appear to be built for currently
loaded compiler $loaded."
}
# OK, families match
# If no version specified in $wanted, we are basically done
if { $wantedLen < 2 } {
if { $requireIt } { prereq $wanted }
return
}
# Ensure versions match
set wantedVer [ lindex $tmpWanted 1 ]
if { $loadedVer eq $wantedVer } {
if { $requireIt } { prereq $wanted }
return
}
# Versions don't match
PrintLoadError "Compiler Mismatch
Package $modTag does not appear to be built for currently
loaded compiler $loaded."
}
The procedure takes a string for the family and version of the compiler
that the modulefile expects, and ensures that if a compiler is loaded, they
match. If they match, the procedure just returns, and if not, it spits out
an error indicating a compiler mismatch. It also takes optional boolean flags:
requireIt
to determine if the procedure should prereq
the compiler
before returning, and loadIt
to determine if, when no compiler was
previously loaded, whether the procedure should load it (using
RequireCompiler
so it can properly handle the default compiler specially
if needed). The requireIt
flag should generally be set for Environment
Modules 4.x (as that will allow the automatic handling of modules to
properly recognize dependencies, even though as we will see that does not
work too well for this strategy as yet), and should not be set for versions
3.x (as the loading of modules with loadIt
does not occur until after
the prereq
, causing module loads to fail).
The resulting modulefile for something depending only on the compiler, using mvapich as an example, then would look like:
# Common modulefile for mvapich
# Using "modulerc based" strategy
# Expects the following variables to have been
# previously defined:
# version: version of mvapich
# compilerTag: the compiler to use
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
# Also get location of and load common procedures
# This is a hack for the cookbook examples, in production
# one should either
# 1) declare the procedures in a site config file (preferred)
# 2) hardcode the path to $tcllibdir and common_utilities.tcl
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
proc ModulesHelp { } {
global version compilerTag
puts stderr "
mvapich: Test dummy version of mvapich $version
mvapich version: $version
Compiler: $compilerTag
For testing packages depending on compilers/MPI
"
}
module-whatis "Dummy mvapich $version (built for $compilerTag)"
# Make sure loadedCompiler matches what we want. And
# load compiler if no compiler loaded
LoadedCompilerMatches $compilerTag 1 1
# For Env Modules 3.x, set requireIt to 0
#LoadedCompilerMatches $compilerTag 0 1
# Compute the installation prefix
set pkgroot $swroot/mvapich
set vroot $pkgroot/$version
set prefix $vroot/$compilerTag
# Set environment variables
setenv MPI_DIR $prefix
set bindir $prefix/bin
set libdir $prefix/lib
set incdir $prefix/include
prepend-path PATH $bindir
prepend-path LIBRARY_PATH $libdir
prepend-path LD_LIBRARY_PATH $libdir
prepend-path CPATH $incdir
Basically, the modulefile knows what compiler it wants (in the above example,
that is set by the stubfile and passed as the Tcl variable compilerTag
into the common
script above), and then calls the LoadedCompilerMatches
procedure
above to ensure the loaded compiler matches what the modulefile wants (and
to load it if no compiler is loaded).
So the mvapich directory in the MODULEPATH
consists of subdirectories for
each version of mvapich supported (e.g. 2.1
and 2.3.1
). In each of the
version subdirectories, we symlink modulerc.select_compiler_family
as
.modulerc
, and create an additional layer of subdirectories, one for
each compiler family for which the version of mvapich is built (e.g.
gcc, intel, pgi). In each compiler family directory under each mvapich
version, we symlink modulerc.select_compiler_version
as .modulerc
,
and create a stub modulefile named for the compiler version. The stub
modulefile then defines some Tcl variables for the version of mvapich
and the compiler family/version, and sources the common
file above.
E.g., for mvapich/2.3.1/intel/2019
, the stubfile would look like
#%Module
# Dummy modulefile for mvapich
set version 2.3.1
set compilerTag intel/2019
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/../../common
So the mvapich directory in MODULEPATH
would have a structure like
mvapich
├── 2.1
│ ├── gcc
│ │ ├── 8.2.0
│ │ ├── 9.1.0
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2018
│ │ ├── 2019
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 18.4
│ ├── 19.4
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── 2.3.1
│ ├── gcc
│ │ ├── 9.1.0
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2019
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 19.4
│ └── .modulerc -> symlink to modulerc.select_compiler_version
└── common
With this directory structure, an user can load a compiler and then module load a specific version of mvapich, and if a build of that version of mvapich exists for that compiler, the environment will be set up properly, and otherwise an error reported. However, if the user module loads mvapich without specifying a version, it will simply default the version to the latest version of mvapich available, regardless of whether there is a build of that version of mvapich for the loaded compiler. Ideally, we would like it so that if one issues a module load of a package without specifying a version, it should load the latest version available that is compatible with any loaded compilers or other modules.
A simple change can enable that. We add a symlink to
modulerc.select_compiler_family
as .modulerc
directly under the
mvapich directory, and create an additional subdirectory under the mvapich
directory for each compiler family. We symlink
modulerc.select_compiler_version
as .modulerc
under each compiler
family subdirectory, along with a subdirectory for each version of that
compiler family that a version of mvapich is built for. We then symlink
the various stub modulefiles under the mvapich/VERSION
into the
corresponding mvapich/COMPILER_FAMILY/COMPILER_VERSION
directory, with
the symlink's name being the mvapich version number. So the mvapich
directory tree will now look like:
mvapich
├── 2.1
│ ├── gcc
│ │ ├── 8.2.0
│ │ ├── 9.1.0
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2018
│ │ ├── 2019
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 18.4
│ ├── 19.4
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── 2.3.1
│ ├── gcc
│ │ ├── 9.1.0
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2019
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 19.4
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── common
├── gcc
│ ├── 8.2.0
│ │ └── 2.1 -> symlink to ../../2.1/gcc/8.2.0
│ ├── 9.1.0
│ │ ├── 2.1 -> symlink to ../../2.1/gcc/9.1.0
│ │ └── 2.3.1 -> symlink to ../../2.3.1/gcc/9.1.0
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── intel
│ ├── 2018
│ │ └── 2.1 -> symlink to ../../2.1/intel/2018
│ ├── 2019
│ │ ├── 2.1 -> symlink to ../../2.1/intel/2019
│ │ └── 2.3.1 -> symlink to ../../2.3.1/intel/2019
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── .modulerc -> symlink to modulerc.select_compiler_family
└── pgi
├── 18.4
│ └── 2.1 -> symlink to ../../2.1/pgi/18.4
├── 19.4
│ ├── 2.1 -> symlink to ../../2.1/pgi/19.4
│ └── 2.3.1 -> symlink to ../../2.3.1/pgi/19.4
└── .modulerc -> symlink to modulerc.select_compiler_version
When one attempts to module load mvapich without specifying a version,
the .modulerc
file will default to the family of the loaded compiler (or
the default compiler if none loaded). It then descends into the corresponding
compiler family directory, where the .modulerc
there will default to the
version of the loaded or defaulted compiler. After descending into the
compiler version directory, there is no .modulerc
, so the standard modulecmd
defaulting mechanism will select the latest version.
We now have two ways to refer to the same build of mvapich, namely one using the traditional form
PACKAGE/PKGVERSION/COMPILER_FAMILY/COMPILER_VERSION
(e.g. mvapich/2.3.1/pgi/19.4)
and a new one giving the compiler family and version immediately after package name, with the version of the package coming last
PACKAGE/COMPILER_FAMILY/COMPILER_VERSION/PKGVERSION
(e.g. mvapich/pgi/19.4/2.3.1)
These both refer to the same build of the package (e.g. version 2.3.1
of mvapich, built for version 19.4
of the PGI compiler suite).
Indeed, through the judicious use of symlinks, these actually refer to the
modulefile on disk, but with two distinct names depending on the path
used to get to it. In general, we allow for
modules to be named with multiple dependency packages and/or flags if
doing so would make it easier for a user to default to the correct package.
This is the primary reason for the procedure GetPackageFamilyVersion
---
it splits a module name into components and takes the first component
as the family name. It then examines the second component, and if it
matches the name of a known package (like a compiler family), it uses
the last component as the version. Otherwise, the second component is
assumed to be the version. The code is as follows:
#--------------------------------------------------------------------
# GetPackageFamilyVersion
#
# Given the fully qualified spec for a modulefile, returns a list
# with the package family name and version.
#
# E.g., for foo/1.1/gcc/8.2.0/openmpi/3.1 would return {foo 1.1}
# But also handles stuff like foo/gcc/8.2.0/openmpi/3.1/1.1 (returning
# again {foo 1.1})
proc GetPackageFamilyVersion { tag } {
# Return empty list if given empty tag
if { $tag eq {} } { return {} }
# Split tag into components
set components [ split $tag / ]
set compLen [ llength $components ]
if { $compLen < 1 } { return {} }
# Family should always be first
set family [ lindex $components 0 ]
if { $compLen < 2 } { return $family }
# First guess, version immediately follows family
set version [ lindex $components 1 ]
# Check if it matches known non-version stuff following family
# Compilers, MPIs, other things branch on
set nonVers { gnu gcc pgi intel openmpi ompi intelmpi impi mvapich
mvapich2 avx avx2 sse4.1 sse3 python perl hdf hdf4 hdf5 }
set tmp [ lsearch $nonVers $version ]
if { $tmp > -1 } {
# The component immediately following family was NOT a version
# Use last component as version
set version [ lindex $components end ]
}
return "$family $version"
}
Similarly, there are two corresponding .modulerc
scripts for defaulting
the MPI library: one to default the family (e.g. openmpi, mvapich, intelmpi)
and one to default the version. The family version, shown below:
#%Module
# Choose MPI family
#
# This check if any MPI lib was previously "module loaded"
#
# If no MPI library was previously module loaded (and intel compiler suite
# was not loaded, see below) and nompiFlag is set (default is set), then
# if a "nompi" subdirectory exists, we will default to that.
# If nompiFlag is not set, then we just return w/out setting any default
# (allowing modulecmd to default on its own. It is the responsibility
# and the resulting modulefile to lado/require the MPI lib it needs or err
# as appropriate).
#
# If an MPI library was loaded, then we check for a subdirectory named after
# the family of the loaded MPI library, and if such exists, default to that.
# If it does not exist, we return w/out defaulting, allowing modulecmd to
# default according to its own rules. The resulting modulefile is responsible
# for aborting/complaining about the MPI library mismatch.
#
# Special handling is needed for intel MPI, as it does not get explicitly
# loaded if the Intel compiler suite is being used. So if no MPI library
# is loaded, we check to see if an Intel compiler was loaded. If so, we
# check for an "intelmpi" or similar subdirectory, and if found default to
# that. If not found, we proceed as above for the no MPI library case
# (defaulting to "nompi" if found and nompiFlag set, or just returning w/out
# defaulting otherwise).
#
# Usage:
# In most cases, can simply symlink .modulerc to this file
#
# In more complicated cases, .modulerc can source this file, and can
# then test the variable _did_default, which will be true if we set
# a default for modules for the next level, or false otherwise (in which
# case your .modulerc can set one)
# Source some required Tcl procedures here. Hack for cookbook
# making use of environment variable for location.
# In production, this should ideally be in a site config file.
# At minimum, hardcode the path
set rootdir $::env(MOD_GIT_ROOTDIR)
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
#Default nompiFlag to set
if ![info exists nompiFlag] { set nompiFlag true }
# _did_default will be true if we actually default something
# Useful in case a .modulerc sources us, and wants to set a default if we
# did not
set _did_default false
set moduledir [file dirname $ModulesCurrentModulefile]
set baseComponent [ file tail $moduledir ]
# Get the currently loaded MPI library
set fullMpiTag [ GetLoadedMPI 0 ]
set tmpMpiTag [ GetPackageFamilyVersion $fullMpiTag ]
set mpiFamily [ lindex $tmpMpiTag 0 ]
if { $mpiFamily eq {} } {
# No MPI module loaded
# What compiler is loaded (default from path if needed, but not GetDefaultCompiler)
set fullComp [ GetLoadedCompiler 1 0 ]
set tmpComp [ GetPackageFamilyVersion $fullComp ]
set compFam [ lindex $tmpComp 0 ]
if { $compFam eq {intel} } {
# OK, no MPI explicitly loaded, but using Intel compiler
# So set mpiFamily to first found in list below
set mpiList {intelmpi impi intel intelmpi-mt impi-mt intel-mp}
set mpiFamily [ FirstChildModuleInList $mpiList ]
}
}
if { $mpiFamily eq {} } {
# No MPI lib was explicitly loaded, and if intel compiler was loaded,
# did not find a subdir matching intelmpi or one of its variants
# Looks for a "nompi" dir if $nompiFlag is set
if { $nompiFlag } {
if [ ChildModuleExists nompi ] {
# nompi subdir exists, default to it
module-version $baseComponent/nompi default
set _did_default true
}
}
} else {
# Either MPI lib was explicitly loaded, or implied intelmpi
# Default to the subdir named after MPI family, if it exists
if [ ChildModuleExists $mpiFamily ] {
module-version $baseComponent/$mpiFamily default
set _did_default true
}
}
is similar to the corresponding compiler version, but contains additional logic to handle the intelmpi case. We treat intelmpi specially, because in our example here we assume the environment for Intel MPI is setup properly when the user loads the intel module. If no MPI library is explicitly loaded, but the intel module is loaded, than we look for a subdirectory named intelmpi (or one of its aliases) and default to it if it exists. Otherwise, if no MPI module is loaded, it looks for and will default to a directory or modulefile named nompi if it exists.
The modulerc.select_mpi_version
script is also similar to its compiler
counterpart,
#%Module
# Choose MPI version
#
# This check if any MPI lib was previously "module loaded"
#
# If an MPI library was loaded, and the family of loaded MPI lib matches
# the name of the parent dir for this .modulerc, and there is a subdir
# of that directory matching the MPI version, then we default to that
# subdir.
#
# If no MPI library was previously module loaded, or the loaded MPI family
# does not match the name of the parent directory, or no subdir matching
# the MPI version is found, then we just return w/out defaulting.
# The modulecmd will then default according to its own rules, and it is
# up to the resulting modulefile to either load the appropriate MPI library
# or abort/complain about an MPI mismatch as appropriate.
#
# NOTE: no special handling is needed for intelmpi, as we assume that if
# intelmpi is selected because the intel compiler was loaded, then we
# are to use the intelmpi that shipped with the compiler suite, and so
# there is no needed for additional versioning of the intelmpi beneath
# the intelmpi subdir. If intelmpi is being used with a non-intel compiler,
# then it is assumed intelmpi was explicitly loaded.
#
# Usage:
# In most cases, can simply symlink .modulerc to this file
#
# In more complicated cases, .modulerc can source this file, and can
# then test the variable _did_default, which will be true if we set
# a default for modules for the next level, or false otherwise (in which
# case your .modulerc can set one)
# Source some required Tcl procedures here. Hack for cookbook
# making use of environment variable for location.
# In production, this should ideally be in a site config file.
# At minimum, hardcode the path
set rootdir $::env(MOD_GIT_ROOTDIR)
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
# _did_default will be true if we actually default something
set _did_default false
set moduledir [file dirname $ModulesCurrentModulefile]
set parentDir [ file tail $moduledir ]
# Get the currently loaded compiler, w/out defaulting
set fullMpiTag [ GetLoadedMPI 0 ]
if { $fullMpiTag ne {} } {
# We have an MPI module loaded
set tmpMpiTag [ GetPackageFamilyVersion $fullMpiTag ]
set mpiFamily [ lindex $tmpMpiTag 0 ]
set mpiVersion [ lindex $tmpMpiTag 1 ]
# Canonicalize intelmpi variants in parentDir and mpiFamily for comparison
set intelList "intelmpi impi intel intelmpi-mt impi-mt intel-mt"
set tmpMpiFamily $mpiFamily
if { [lsearch $intelList $tmpMpiFamily] > -1 } {
set tmpMpiFamily intelmpi
}
set tmpParentDir $parentDir
if { [lsearch $intelList $tmpParentDir] > -1 } {
set tmpParentDir intelmpi
}
if { $tmpParentDir eq $tmpMpiFamily } {
# The loaded MPI lib family name matches parentDir
# So see if have subdir matching version, and if so, default it
if { $mpiVersion ne {} } {
if [ ChildModuleExists $mpiVersion ] {
module-version $mpiFamily/$mpiVersion default
set _did_default true
}
}
}
}
It checks if any MPI library was explicitly loaded, and if so it checks
if the family of the loaded MPI module matches the name of the parent directory
of this .modulerc
file. If so, it checks for the existence of a subdirectory
matching the version, and if found it defaults to it. There is no special
handling needed for the nompi
case, as since there is no version attached
to the MPI library in the nompi case, this .modulerc
is not present there.
Similarly, for the case of Intel MPI when the Intel compiler suite is loaded, we
expect the Intel MPI version to be that from the Intel compiler suite, so
no version or this .modulerc
is needed.
As the MPI modules depend themselves on the compiler, it is assumed that any package depending on the MPI libraries also depend on the compiler, and so will have a structure like the one described below for foo
foo
├── 1.1
│ ├── gcc
│ │ ├── 8.2.0
│ │ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ │ ├── mvapich
│ │ │ │ ├── 2.1
│ │ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ │ ├── nompi
│ │ │ └── openmpi
│ │ │ ├── 3.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2018
│ │ │ ├── intelmpi
│ │ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ │ ├── mvapich
│ │ │ │ ├── 2.1
│ │ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ │ ├── nompi
│ │ │ └── openmpi
│ │ │ ├── 3.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 18.4
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── mvapich
│ │ │ ├── 2.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ ├── nompi
│ │ └── openmpi
│ │ ├── 3.1
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── 2.4
│ ├── gcc
│ │ ├── 9.1.0
│ │ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ │ ├── mvapich
│ │ │ │ ├── 2.3.1
│ │ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ │ ├── nompi
│ │ │ └── openmpi
│ │ │ ├── 4.0
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── intel
│ │ ├── 2019
│ │ │ ├── intelmpi
│ │ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ │ ├── mvapich
│ │ │ │ ├── 2.3.1
│ │ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ │ ├── nompi
│ │ │ └── openmpi
│ │ │ ├── 4.0
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ ├── .modulerc -> symlink to modulerc.select_compiler_family
│ └── pgi
│ ├── 19.4
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── nompi
│ │ └── openmpi
│ │ ├── 3.1
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── common
├── gcc
│ ├── 8.2.0
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── mvapich
│ │ │ ├── 2.1
│ │ │ │ └── 1.1 -> ../../../../1.1/gcc/8.2.0/mvapich/2.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ ├── nompi
│ │ │ └── 1.1 -> ../../../1.1/gcc/8.2.0/nompi
│ │ └── openmpi
│ │ ├── 3.1
│ │ │ └── 1.1 -> ../../../../1.1/gcc/8.2.0/openmpi/3.1
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ ├── 9.1.0
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── mvapich
│ │ │ ├── 2.3.1
│ │ │ │ └── 2.4 -> ../../../../2.4/gcc/9.1.0/mvapich/2.3.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ ├── nompi
│ │ │ └── 2.4 -> ../../../2.4/gcc/9.1.0/nompi
│ │ └── openmpi
│ │ ├── 4.0
│ │ │ └── 2.4 -> ../../../../2.4/gcc/9.1.0/openmpi/4.0
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── intel
│ ├── 2018
│ │ ├── intelmpi
│ │ │ └── 1.1 -> ../../../1.1/intel/2018/intelmpi
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── mvapich
│ │ │ ├── 2.1
│ │ │ │ └── 1.1 -> ../../../../1.1/intel/2018/mvapich/2.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ ├── nompi
│ │ │ └── 1.1 -> ../../../1.1/intel/2018/nompi
│ │ └── openmpi
│ │ ├── 3.1
│ │ │ └── 1.1 -> ../../../../1.1/intel/2018/openmpi/3.1
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ ├── 2019
│ │ ├── intelmpi
│ │ │ └── 2.4 -> ../../../2.4/intel/2019/intelmpi
│ │ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ │ ├── mvapich
│ │ │ ├── 2.3.1
│ │ │ │ └── 2.4 -> ../../../../2.4/intel/2019/mvapich/2.3.1
│ │ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ │ ├── nompi
│ │ │ └── 2.4 -> ../../../2.4/intel/2019/nompi
│ │ └── openmpi
│ │ ├── 4.0
│ │ │ └── 2.4 -> ../../../../2.4/intel/2019/openmpi/4.0
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── .modulerc -> symlink to modulerc.select_compiler_family
└── pgi
├── 18.4
│ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ ├── mvapich
│ │ ├── 2.1
│ │ │ └── 1.1 -> ../../../../1.1/pgi/18.4/mvapich/2.1
│ │ └── .modulerc -> symlink to modulerc.select_mpi_version
│ ├── nompi
│ │ └── 1.1 -> ../../../1.1/pgi/18.4/nompi
│ └── openmpi
│ ├── 3.1
│ │ └── 1.1 -> ../../../../1.1/pgi/18.4/openmpi/3.1
│ └── .modulerc -> symlink to modulerc.select_mpi_version
├── 19.4
│ ├── .modulerc -> symlink to modulerc.select_mpi_family
│ ├── nompi
│ │ └── 2.4 -> ../../../2.4/pgi/19.4/nompi
│ └── openmpi
│ ├── 3.1
│ │ └── 2.4 -> ../../../../2.4/pgi/19.4/openmpi/3.1
│ └── .modulerc -> symlink to modulerc.select_mpi_version
└── .modulerc -> symlink to modulerc.select_compiler_version
Although the directory tree above is somewhat lengthy, it is similar
to the case for a module depending only on the compiler, but expanded
to handle MPI dependencies as well. There is a subdirectory under foo
for each version of foo. Each of these subdirectories have further subdirectories
for the compiler families for which that version of foo was built, and under
the subdirectories for each compiler family are subdirectories for each version
of that compiler family for which foo was built. Underneath these
are stub modulefiles for nompi (and for intel compilers, intelmpi) builds of
the package, and subdirectories for each MPI family, containing stub modulefiles
for each version of the MPI family the package was built for.
Additionally, there are subdirectories directly under foo
for each compiler
family the package was built for, with each having subdirectories for the
version of the compiler. Beneath each of those are one or two more layers
of subdirectories for the MPI family and version (the version layer is omitted
in the nompi or intelmpi cases), underneath which are symlinks to the corresponding
stub modulefile from the foo/FOOVERSION
path.
By placing the appropriate .modulerc
files (actually, symlinks to the correct
modulerc file), when the user enters a partial modulename the modulecmd will
descend this directory tree based on the previously loaded compiler and MPI
library to get to correct build of the package, if it exists. If no MPI library
was previously loaded, it will search for an intelmpi build if an intel compiler
was loaded, or a nompi build if no intelmpi build found or a non-intel compiler
was used. If only MPI builds were made, it will default (using standard
module defaulting rules) to one of the MPI builds, and the appropriate MPI
library will be loaded when the foo module gets loaded (via the LoadedMPIMatches
Tcl procedure described below). If a compiler and MPI library were loaded but no
build for that combination exists, again a modulefile will be defaulted to
(using standard module defaulting rules), but an error will be generated by
the one of the LoadedCompilerMatches
or LoadedMPIMatches
calls in the
foo modulefile (see below).
The common code of the modulefile is fairly standard, as shown below
# Common stuff for "foo" modulefiles
# Using "modulerc based" strategy
#
# This file expects the following Tcl variables to have been
# previously set:
# version: version of foo
# compilerTag: compiler was built for
# mpiTag: mpi was built for
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
# Also get location of and load common procedures
# This is a hack for the cookbook examples, in production
# one should either
# 1) declare the procedures in a site config file (preferred)
# 2) hardcode the path to $tcllibdir and common_utilities.tcl
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
proc ModulesHelp { } {
global version compilerTag mpiTag
puts stderr "
foo: Test dummy version of foo $version
For testing packages depending on compilers/MPI
Foo: $version
Compiler: $compilerTag
MPI: $mpiTag
"
}
module-whatis "Dummy foo $version ($compilerTag, $mpiTag)"
# Make sure loaded compiler and MPI match what we want.
# And load them if not already loaded
LoadedCompilerMatches $compilerTag 1 1
# But don't load intelmpi if compiler is intel
LoadedMpiMatches $mpiTag 1 1 1
# For Env Modules 3.x, set requireIt to false
#LoadedCompilerMatches $compilerTag 0 1
#LoadedMpiMatches $mpiTag 0 1 1
# Compute the installation prefix
set pkgroot $swroot/foo
set vroot $pkgroot/$version
set prefix $vroot/$compilerTag/$mpiTag
# Set environment variables
setenv FOO_DIR $prefix
set bindir $prefix/bin
set libdir $prefix/lib
set incdir $prefix/include
prepend-path PATH $bindir
prepend-path LIBRARY_PATH $libdir
prepend-path LD_LIBRARY_PATH $libdir
prepend-path CPATH $incdir
conflict foo
The main difference from a standard modulefile is the inclusion of the
invocations of LoadedCompilerMatches
and LoadedMpiMatches
. This
is needed to ensure that the compiler and MPI for the modulefile being
processed are compatible with any which are loaded. The LoadedMpiMatches
procedure is defined by:
#--------------------------------------------------------------------
# LoadedMpiMatches:
#
# Takes the tag of the desired MPI library $wanted (in form of FAMILY/VERSION)
# Checks if any MPI is loaded, and will throw error if one is
# loaded and it does not match $wanted.
# If MPIs match, it will prereq the MPI lib if $requireIt set
# If no MPI is loaded, will load if optional boolean parameter
# $loadIt is set (default unset), and prereq if $requireIt is set, and
# then return.
# Option parameters:
# requireIt: boolean, default false. If set, will prereq $wanted
# loadIt: boolean, default false. If set, load $wanted
# if no MPI is already loaded
# noLoadIntel: boolean, passed to RequireMPI. If set,
# will not attempt to load intelmpi variants if compiler is intel
# forceNoMpi: boolean, default false. If set and $wanted is 'nompi',
# insist that no MPI module is loaded
# modTag: string, defaults go [module-info specified]. Used in error messages
proc LoadedMpiMatches { wanted {requireIt 0} { loadIt 0 } { noLoadIntel 0 }
{ forceNoMpi 0 } {modTag {} } } {
# Default modTag
if { $modTag eq {} } { set modTag [ module-info specified ] }
# If no MPI given in $wanted, just return
if { $wanted eq {} } { return }
# Get loaded MPI, no defaulting to intelmpi
set loaded [ GetLoadedMPI 0 ]
# If wanted is nompi, no need to do anything unless forceNoMpi set
if { $wanted eq {nompi} } {
if { $forceNoMpi } {
# Complain if any MPI loaded
if { $loaded ne {} } {
PrintLoadError "MPI Mismatch
You have an MPI library loaded ($loaded), but package $modTag
really insists that no MPI library be loaded.
Please unload the MPI library and try again."
}
}
return
}
# If no MPI is loaded, then load it if $loadIt (this is valid even
# in edge cases of nompi or intelmpi), prereq it if $requireIt,
# abd return
if { $loaded eq {} } {
if { $loadIt } {
RequireMPI $wanted $noLoadIntel
if { $requireIt } { prereq $wanted }
}
return
}
# Have a loaded MPI, split into family and version
set tmpLoaded [ GetPackageFamilyVersion $loaded ]
set loadedFam [ lindex $tmpLoaded 0 ]
set loadedVer [ lindex $tmpLoaded 1 ]
# Split wanted into family and version
set tmpWanted [ split $wanted / ]
set wantedLen [ llength $tmpWanted ]
#Nothing to do if no components to wanted
if { $wantedLen < 1 } { return }
set wantedFam [ lindex $tmpWanted 0 ]
# Ensure families match
if { $loadedFam ne $wantedFam } {
PrintLoadError "MPI Mismatch
Package $modTag does not appear to be built for currently
loaded MPI library $loaded."
}
# OK, families match
# If no version specified in $wanted, we are basically done
if { $wantedLen < 2 } {
if { $requireIt } { prereq $wanted }
return
}
# Ensure versions match
set wantedVer [ lindex $tmpWanted 1 ]
if { $loadedVer eq $wantedVer } {
if { $requireIt } { prereq $wanted }
return
}
# Versions don't match
PrintLoadError "MPI Mismatch
Package $modTag does not appear to be built for currently
loaded MPI library $loaded."
}
Basically, it determines what if any MPI library was previously module loaded.
If one was loaded, it ensures the family and version match what was expected,
and if not exit with an error. The use of the GetPackageFamilyVersion
procedure is important, because as discussed previously packages can be
represented by more than one name (e.g. the modulefile for version 4.0
of
openmpi for gcc/9.1.0
could be named openmpi/4.0/gcc/9.1.0
or
openmpi/gcc/9.1.0/4.0
) and we need to ensure either is recognized.
Although we only showed cases for compilers and MPI libraries, the techniques
above can be adapted to other cases as well. For simple cases, where everything
falls under a single package name, one can use GetTagOfModuleLoaded
to
determine the version of the package loaded in the .modulerc
and in the
modulefile to ensure the version matches.
For bar, we added variants on CPU vectorization support. Rather than add a simd modulefile, we just add variants to the bar modules. So the bar modulefile tree would look like:
bar
├── 4.7
│ ├── gcc
│ │ ├── 8.2.0
│ │ │ ├── avx
│ │ │ ├── .modulerc -> symlink to modulerc.default_lowest_simd
│ │ │ └── sse4.1
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ └── .modulerc -> symlink to modulerc.select_compiler_family
├── 5.4
│ ├── gcc
│ │ ├── 9.1.0
│ │ │ ├── avx
│ │ │ └── avx2
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ └── .modulerc -> symlink to modulerc.select_compiler_family
├── avx
│ ├── gcc
│ │ ├── 8.2.0
│ │ │ └── 4.7 -> ../../../4.7/gcc/8.2.0/avx
│ │ ├── 9.1.0
│ │ │ └── 5.4 -> ../../../5.4/gcc/9.1.0/avx
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ └── .modulerc -> symlink to modulerc.select_compiler_family
├── avx2
│ ├── gcc
│ │ ├── 9.1.0
│ │ │ └── 5.4 -> ../../../5.4/gcc/9.1.0/avx2
│ │ └── .modulerc -> symlink to modulerc.select_compiler_version
│ └── .modulerc -> symlink to modulerc.select_compiler_family
├── common
├── gcc
│ ├── 8.2.0
│ │ ├── avx
│ │ │ └── 4.7 -> ../../../4.7/gcc/8.2.0/avx
│ │ ├── .modulerc -> symlink to modulerc.default_lowest_simd
│ │ └── sse4.1
│ │ └── 4.7 -> ../../../4.7/gcc/8.2.0/sse4.1
│ ├── 9.1.0
│ │ ├── avx
│ │ │ └── 5.4 -> ../../../5.4/gcc/9.1.0/avx
│ │ ├── avx2
│ │ │ └── 5.4 -> ../../../5.4/gcc/9.1.0/avx2
│ │ └── .modulerc -> symlink to modulerc.default_lowest_simd
│ └── .modulerc -> symlink to modulerc.select_compiler_version
├── .modulerc -> symlink to modulerc.select_compiler_family
└── sse4.1
├── gcc
│ ├── 8.2.0
│ │ └── 4.7 -> ../../../4.7/gcc/8.2.0/sse4.1
│ └── .modulerc -> symlink to modulerc.select_compiler_version
└── .modulerc -> symlink to modulerc.select_compiler_family
Here we added yet another alternate set of module names. So the module
for bar version 5.4
built with gcc version 9.1.0
and avx2
support can be
called:
bar/5.4/gcc/9.1.0/avx2
bar/gcc/9.1.0/avx2/5.4
bar/avx2/gcc/9.1.0/5.4
Due to this multiplicity of names, if an user does a module load bar, the
.modulerc
immediately under bar will cause modulecmd to default along the
path for the loaded (or defaulted) compiler, and then the
modulerc.default_lowest_simd
will default to the lowest simd level.
If the user module loads bar/VERSION, it will find the build for that version
of bar with the appropriate compiler (and again, default to the lowest simd
level). And if the user module loads bar/avx
or another simd level, then
it will load the latest version of bar built for the loaded compiler and
simd specified.
The modulerc.default_lowest_simd
script looks like:
#%Module
# Default to lowest SIMD support available
#
# Defaults to first of sse4.1, avx, or avx2 found
#
# Usage:
# In most cases, can simply symlink .modulerc to this file
#
# In more complicated cases, .modulerc can source this file, and can
# then test the variable _did_default, which will be true if we set
# a default for modules for the next level, or false otherwise (in which
# case your .modulerc can set one)
# Source some required Tcl procedures here. Hack for cookbook
# making use of environment variable for location.
# In production, this should ideally be in a site config file.
# At minimum, hardcode the path
set rootdir $::env(MOD_GIT_ROOTDIR)
set tcllibdir $rootdir/doc/example/compiler-etc-dependencies/tcllib
source $tcllibdir/common_utilities.tcl
set moduledir [file dirname $ModulesCurrentModulefile]
set baseComponent [ file tail $moduledir ]
# _did_default will be true if we actually default something
# Useful in case a .modulerc sources us, and wants to set a default if we
# did not
set _did_default false
set simdList {sse4.1 avx avx2}
set firstChild [ FirstChildModuleInList $simdList ]
if { $firstChild ne {} } {
module-version $baseComponent/$firstChild default
set _did_default true
}
It will default to the lowest SIMD level, but could easily be adapted to do something else.
Examples¶
We now look at the example modulefiles for the Modulerc-based strategy.
As noted previously, the best choice of whether to set the requireIt
flag
to LoadedCompilerMatches
and LoadedMPIMatches
(instructing them to
to a prereq
on the requesting compiler/MPI module) depends on whether
one is using a 3.x or 4.x version of Environment Modules. Due to this,
we provide two modulefile trees, one for 3.x and one for 4.x; they are
basically identical except for that matter. This leads to slightly
different instructions on how to use the examples, depending on which
version of Environment Modules is being used, namely:
- Set (and export)
MOD_GIT_ROOTDIR
to where you git-cloned the modules source - Do a
module purge
- If using Environment Modules 3.x, set your
MODULEPATH
to$MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc3
- If using Environment Modules 4.x, set your
MODULEPATH
to$MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc4
As with the previous cases, we start with a module avail
command, and here
we see the first big difference:
[mod4 (modulerc)]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc4 -
bar/4.7/gcc/(default) foo/intel/2019/intelmpi/2.4
bar/4.7/gcc/8.2.0/(default) foo/intel/2019/mvapich/2.3.1/2.4
bar/4.7/gcc/8.2.0/avx foo/intel/2019/nompi/2.4
bar/4.7/gcc/8.2.0/sse4.1(default) foo/intel/2019/openmpi/4.0/2.4
bar/5.4/gcc/(default) foo/pgi/18.4/mvapich/2.1/1.1
bar/5.4/gcc/9.1.0/avx foo/pgi/18.4/nompi/(default)
bar/5.4/gcc/9.1.0/avx2 foo/pgi/18.4/nompi/1.1
bar/avx/gcc/(default) foo/pgi/18.4/openmpi/3.1/1.1
bar/avx/gcc/8.2.0/(default) foo/pgi/19.4/nompi/(default)
bar/avx/gcc/8.2.0/4.7 foo/pgi/19.4/nompi/2.4
bar/avx/gcc/9.1.0/5.4 foo/pgi/19.4/openmpi/3.1/2.4
bar/avx2/gcc/(default) gcc/8.2.0
bar/avx2/gcc/9.1.0/5.4 gcc/9.1.0
bar/gcc/(default) intel/2018
bar/gcc/8.2.0/(default) intel/2019
bar/gcc/8.2.0/avx/4.7 mvapich/2.1/gcc/(default)
bar/gcc/8.2.0/sse4.1/(default) mvapich/2.1/gcc/8.2.0(default)
bar/gcc/8.2.0/sse4.1/4.7 mvapich/2.1/gcc/9.1.0
bar/gcc/9.1.0/avx/(default) mvapich/2.1/intel/2018
bar/gcc/9.1.0/avx/5.4 mvapich/2.1/intel/2019
bar/gcc/9.1.0/avx2/5.4 mvapich/2.1/pgi/18.4
bar/sse4.1/gcc/(default) mvapich/2.1/pgi/19.4
bar/sse4.1/gcc/8.2.0/(default) mvapich/2.3.1/gcc/(default)
bar/sse4.1/gcc/8.2.0/4.7 mvapich/2.3.1/gcc/9.1.0
foo/1.1/gcc/(default) mvapich/2.3.1/intel/2019
foo/1.1/gcc/8.2.0/(default) mvapich/2.3.1/pgi/19.4
foo/1.1/gcc/8.2.0/mvapich/2.1 mvapich/gcc/(default)
foo/1.1/gcc/8.2.0/nompi(default) mvapich/gcc/8.2.0/(default)
foo/1.1/gcc/8.2.0/openmpi/3.1 mvapich/gcc/8.2.0/2.1
foo/1.1/intel/2018/intelmpi(default) mvapich/gcc/9.1.0/2.1
foo/1.1/intel/2018/mvapich/2.1 mvapich/gcc/9.1.0/2.3.1
foo/1.1/intel/2018/nompi mvapich/intel/2018/2.1
foo/1.1/intel/2018/openmpi/3.1 mvapich/intel/2019/2.1
foo/1.1/pgi/18.4/mvapich/2.1 mvapich/intel/2019/2.3.1
foo/1.1/pgi/18.4/nompi(default) mvapich/pgi/18.4/2.1
foo/1.1/pgi/18.4/openmpi/3.1 mvapich/pgi/19.4/2.1
foo/2.4/gcc/(default) mvapich/pgi/19.4/2.3.1
foo/2.4/gcc/9.1.0/mvapich/2.3.1 openmpi/3.1/gcc/(default)
foo/2.4/gcc/9.1.0/nompi(default) openmpi/3.1/gcc/8.2.0(default)
foo/2.4/gcc/9.1.0/openmpi/4.0 openmpi/3.1/gcc/9.1.0
foo/2.4/intel/2019/intelmpi(default) openmpi/3.1/intel/2018
foo/2.4/intel/2019/mvapich/2.3.1 openmpi/3.1/intel/2019
foo/2.4/intel/2019/nompi openmpi/3.1/pgi/18.4
foo/2.4/intel/2019/openmpi/4.0 openmpi/3.1/pgi/19.4
foo/2.4/pgi/19.4/nompi(default) openmpi/4.0/gcc/(default)
foo/2.4/pgi/19.4/openmpi/3.1 openmpi/4.0/gcc/9.1.0
foo/gcc/(default) openmpi/4.0/intel/2019
foo/gcc/8.2.0/(default) openmpi/4.0/pgi/19.4
foo/gcc/8.2.0/mvapich/2.1/1.1 openmpi/gcc/(default)
foo/gcc/8.2.0/nompi/(default) openmpi/gcc/8.2.0/(default)
foo/gcc/8.2.0/nompi/1.1 openmpi/gcc/8.2.0/3.1
foo/gcc/8.2.0/openmpi/3.1/1.1 openmpi/gcc/9.1.0/3.1
foo/gcc/9.1.0/mvapich/2.3.1/2.4 openmpi/gcc/9.1.0/4.0
foo/gcc/9.1.0/nompi/(default) openmpi/intel/2018/3.1
foo/gcc/9.1.0/nompi/2.4 openmpi/intel/2019/3.1
foo/gcc/9.1.0/openmpi/4.0/2.4 openmpi/intel/2019/4.0
foo/intel/2018/intelmpi/(default) openmpi/pgi/18.4/3.1
foo/intel/2018/intelmpi/1.1 openmpi/pgi/19.4/3.1
foo/intel/2018/mvapich/2.1/1.1 openmpi/pgi/19.4/4.0
foo/intel/2018/nompi/1.1 pgi/18.4
foo/intel/2018/openmpi/3.1/1.1 pgi/19.4
foo/intel/2019/intelmpi/(default)
[mod4 (modulerc)]$ module avail mvapich
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc4 -
mvapich/2.1/gcc/(default) mvapich/gcc/(default)
mvapich/2.1/gcc/8.2.0(default) mvapich/gcc/8.2.0/(default)
mvapich/2.1/gcc/9.1.0 mvapich/gcc/8.2.0/2.1
mvapich/2.1/intel/2018 mvapich/gcc/9.1.0/2.1
mvapich/2.1/intel/2019 mvapich/gcc/9.1.0/2.3.1
mvapich/2.1/pgi/18.4 mvapich/intel/2018/2.1
mvapich/2.1/pgi/19.4 mvapich/intel/2019/2.1
mvapich/2.3.1/gcc/(default) mvapich/intel/2019/2.3.1
mvapich/2.3.1/gcc/9.1.0 mvapich/pgi/18.4/2.1
mvapich/2.3.1/intel/2019 mvapich/pgi/19.4/2.1
mvapich/2.3.1/pgi/19.4 mvapich/pgi/19.4/2.3.1
Unlike the previous cases wherein only package names and versions were shown
(because a single modulefile handled all the builds for that package and
version), here we see a listing for every build of a package and version.
Indeed, we not only see one such listing, but multiple listings per
build in many cases (e.g. openmpi/3.1/intel/2018
and
openmpi/intel/2018/3.1
).
While admittedly the output of a module avail
command without
specifying any package is rather overwhelming, when a package is specified
the output tends to be more reasonable, informing one of which builds
of the package are available. This strategy deliberately opts for the
presentation of more rather than less information.
The standard functionality of selecting the correct build of a package based on the loaded compiler, e.g.
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load pgi/19.4
[mod4 (modulerc)]$ module load openmpi/4.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0/pgi/19.4(default)
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (modulerc)]$ module unload openmpi
[mod4 (modulerc)]$ module switch --auto pgi intel/2019
[mod4 (modulerc)]$ module load openmpi/4.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0/intel/2019(default)
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4 (modulerc)]$ module unload openmpi
[mod4 (modulerc)]$ module switch --auto intel gcc/9.1.0
[mod4 (modulerc)]$ module load openmpi/4.0
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/4.0, gcc/9.1.0)
[mod4 (modulerc)]$ module unload openmpi
[mod4 (modulerc)]$ module switch --auto gcc gcc/8.2.0
[mod4 (modulerc)]$ module load openmpi/4.0
**** ERROR *****:
Compiler Mismatch
Package openmpi/4.0 does not appear to be built for currently
loaded compiler gcc/8.2.0.
Loading openmpi/4.0/gcc/9.1.0
ERROR: Module evaluation aborted
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0
works as expected (and fails with the expected error when one attempts to load a module not compatible with the loaded compiler). The only significant difference between the previously examined strategies is that the module list command provides information about what variant of each package is loaded.
The module switch
command, however, does not work as well as one would
like. While it indeed switches the specified module, it does not
successfully reload the modules which depend on the replaced module, even
with the Automated module handling
feature enabled. As currently implemented,
the automated module handling feature attempts to reload dependent modules
using the fully qualified module name, and as in this strategy the fully
qualified modulename includes the information about the module that was switched
out (e.g. pgi/19.4
in the example below), it will be incompatible with the
replacement module (e.g. intel/2019
in example below). It
is hoped a future version of modulecmd will allow for reloading based on the
name specified when the module was loaded. But as things currently stand,
the automatic module handling will throw an error attempting to reload the
depend module, resulting in the the dependent modules being unloaded.
Without automated module handling mode (i.e. for older Environment Modules or without the --auto flag), the dependent modules remain loaded and there is inconsistency in the loaded modules. But at least module list clearly shows such.
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load pgi/19.4
[mod4 (modulerc)]$ module load openmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/pgi/19.4/4.0
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (modulerc)]$ module switch --auto pgi intel/2019
**** ERROR *****:
Compiler Mismatch
Package openmpi/pgi/19.4/4.0 does not appear to be built for currently
loaded compiler intel/2019.
Loading openmpi/pgi/19.4/4.0
ERROR: Module evaluation aborted
Switching from pgi/19.4 to intel/2019
WARNING: Reload of dependent openmpi/pgi/19.4/4.0 failed
Unloading dependent: openmpi/pgi/19.4/4.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019
[mod4 (modulerc)]$ mpirun
mpirun: command not found
The defaulting of modules is more successful, however, as seen below:
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load openmpi/3.1
Loading openmpi/3.1/gcc/8.2.0
Loading requirement: gcc/8.2.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) openmpi/3.1/gcc/8.2.0(default)
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/3.1, gcc/8.2.0)
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load gcc/8.2.0
[mod4 (modulerc)]$ module load openmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) openmpi/gcc/8.2.0/3.1
[mod4 (modulerc)]$ mpirun
mpirun (openmpi/3.1, gcc/8.2.0)
Here it not only defaults to the default compiler, but if one tries to load openmpi without specifying a version, it will find and load the latest version compatible with the loaded compiler.
The situation is similar for foo:
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load pgi/19.4
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) foo/2.4/pgi/19.4/nompi(default)
[mod4 (modulerc)]$ foo
foo 2.4 (pgi/19.4, nompi)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module load openmpi/3.1
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 3) foo/2.4/pgi/19.4/openmpi/3.1(default)
2) openmpi/3.1/pgi/19.4(default)
[mod4 (modulerc)]$ foo
foo 2.4 (pgi/19.4, openmpi/3.1)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module unload openmpi
[mod4 (modulerc)]$ module switch --auto pgi intel/2019
[mod4 (modulerc)]$ module load foo/2.4
Loading foo/2.4/intel/2019/intelmpi
ERROR: foo/2.4/intel/2019/intelmpi cannot be loaded due to missing prereq.
HINT: the following module must be loaded first: intelmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019
[mod4 (modulerc)]$ foo
foo: command not found
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module load foo/2.4/intel/2019/nompi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4/intel/2019/nompi
[mod4 (modulerc)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module switch --auto intelmpi mvapich/2.3.1
[mod4 (modulerc)]$ module load foo/2.4
Loading foo/2.4/intel/2019/intelmpi
ERROR: foo/2.4/intel/2019/intelmpi cannot be loaded due to missing prereq.
HINT: the following module must be loaded first: intelmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) mvapich/2.3.1/intel/2019(default)
[mod4 (modulerc)]$ foo
foo: command not found
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module switch --auto mvapich openmpi/4.0
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019
2) openmpi/4.0/intel/2019(default)
3) foo/2.4/intel/2019/openmpi/4.0(default)
[mod4 (modulerc)]$ foo
foo 2.4 (intel/2019, openmpi/4.0)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module unload openmpi
[mod4 (modulerc)]$ module switch --auto intel/2019 gcc/9.1.0
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) foo/2.4/gcc/9.1.0/nompi(default)
[mod4 (modulerc)]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module load mvapich/2.3.1
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 3) foo/2.4/gcc/9.1.0/nompi(default)
2) mvapich/2.3.1/gcc/9.1.0(default)
[mod4 (modulerc)]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4 (modulerc)]$ module unload foo
[mod4 (modulerc)]$ module switch --auto mvapich openmpi/4.0
[mod4 (modulerc)]$ module load foo/2.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 3) foo/2.4/gcc/9.1.0/openmpi/4.0(default)
2) openmpi/4.0/gcc/9.1.0(default)
[mod4 (modulerc)]$ foo
foo 2.4 (gcc/9.1.0, openmpi/4.0)
As expected, the correct version of foo is loaded depending on the previously
loaded compiler and MPI libraries. Note however that there is no dummy
module for Intel MPI, and that when the intel compiler is loaded but no MPI
library is explicitly loaded, module load foo/2.4 gets the Intel MPI build.
Such only occurs if there is an Intel MPI build in the tree of modulefiles;
otherwise a nompi build will be loaded if present. If both versions are
present, as in this case, one needs to give the explicit
foo/2.4/intel/2019/nompi
specification.
Again, the module switch
command only succeeds in switching the
specified module, and does not successfully reload the modules depending
on the switched module. With automated module handling mode, there will be errors
reported and the dependent modules will be unloaded; without it the dependent
modules will not get unloaded, and there will be inconsistent dependencies
(but at least module list will show such).
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load pgi/18.4
[mod4 (modulerc)]$ module load openmpi/3.1
[mod4 (modulerc)]$ module load foo/1.1
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 3) foo/1.1/pgi/18.4/openmpi/3.1(default)
2) openmpi/3.1/pgi/18.4(default)
[mod4 (modulerc)]$ foo
foo 1.1 (pgi/18.4, openmpi/3.1)
[mod4 (modulerc)]$ module switch --auto pgi intel/2018
**** ERROR *****:
Compiler Mismatch
Package openmpi/3.1/pgi/18.4 does not appear to be built for currently
loaded compiler intel/2018.
Loading openmpi/3.1/pgi/18.4
ERROR: Module evaluation aborted
**** ERROR *****:
Compiler Mismatch
Package foo/1.1/pgi/18.4/openmpi/3.1 does not appear to be built for currently
loaded compiler intel/2018.
Loading foo/1.1/pgi/18.4/openmpi/3.1
ERROR: Module evaluation aborted
Switching from pgi/18.4 to intel/2018
WARNING: Reload of dependent openmpi/3.1/pgi/18.4 failed
WARNING: Reload of dependent foo/1.1/pgi/18.4/openmpi/3.1 failed
Unloading dependent: foo/1.1/pgi/18.4/openmpi/3.1 openmpi/3.1/pgi/18.4
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2018
[mod4 (modulerc)]$ foo
foo: command not found
[mod4 (modulerc)]$ mpirun
mpirun: command not found
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load intel/2019
[mod4 (modulerc)]$ module load foo
Loading foo/intel/2019/intelmpi/2.4
ERROR: foo/intel/2019/intelmpi/2.4 cannot be loaded due to missing prereq.
HINT: the following module must be loaded first: intelmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019
[mod4 (modulerc)]$ foo
foo: command not found
[mod4 (modulerc)]$ module load openmpi
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/intel/2019/4.0
[mod4 (modulerc)]$ foo
foo: command not found
The defaulting of modules works relatively well, as shown below:
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load foo
Loading foo/gcc/8.2.0/nompi/1.1
Loading requirement: gcc/8.2.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) foo/gcc/8.2.0/nompi/1.1
[mod4 (modulerc)]$ foo
foo 1.1 (gcc/8.2.0, nompi)
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load foo/1.1
Loading foo/1.1/gcc/8.2.0/nompi
Loading requirement: gcc/8.2.0
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) foo/1.1/gcc/8.2.0/nompi(default)
[mod4 (modulerc)]$ foo
foo 1.1 (gcc/8.2.0, nompi)
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load pgi/18.4
[mod4 (modulerc)]$ module load foo
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 2) foo/pgi/18.4/nompi/1.1
[mod4 (modulerc)]$ foo
foo 1.1 (pgi/18.4, nompi)
If one attempts to load foo without specifying a version or having previously loaded a compiler
module, the compiler will be defaulted (to gcc/8.2.0
compiler, as that is what
we declared via the GetDefaultCompiler
Tcl procedure), and the latest
version of foo compatible with that compiler (and no MPI) will be loaded.
The situation with bar is similar. We do not have a dummy simd module,
so the builds with different CPU vectorization support are specified by
appending /avx
, etc. to the bar package name. As with previous strategies,
if one attempts to load a simd variant which was not built for the compiler
loaded, an error will occur.
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module load gcc/9.1.0
[mod4 (modulerc)]$ module load bar/avx2
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) bar/avx2/gcc/9.1.0/5.4
[mod4 (modulerc)]$ bar
bar 5.4 (gcc/9.1.0, avx2)
[mod4 (modulerc)]$ module unload bar
[mod4 (modulerc)]$ module load bar/avx
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) bar/avx/gcc/9.1.0/5.4
[mod4 (modulerc)]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4 (modulerc)]$ module unload bar
[mod4 (modulerc)]$ module load bar/sse4.1
**** ERROR *****:
Compiler Mismatch
Package bar/sse4.1 does not appear to be built for currently
loaded compiler gcc/9.1.0.
Loading bar/sse4.1/gcc/8.2.0/4.7
ERROR: Module evaluation aborted
[mod4 (modulerc)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0
Summary of Modulerc-based strategy¶
- The modulefiles are fairly standard. The only extra logic needed is to ensure that any loaded compiler/MPI or other dependency matches what the modulefile expects, and that can be handled fairly easily with the addition of one or two calls to Tcl procedures.
- The
.modulerc
files do the work of routing partial specifications to the correct modulefile, and follow a fairly standard pattern. For the most part, these are generic/independent of the package, and typically can be written once and symlinked to the appropriate places in the directory tree. - This strategy involves the use of many more modulefiles than the previously examined strategies, having at least one modulefile per build, and in some cases multiple per build. The output of the module avail command without any module specified is rather overwhelming, although when a module is specified, module avail will provide information about what builds are available.
- Because each build has a specific module, the module list command shows exactly what builds of the various modules are loaded.
- The module switch command does not work very well. In
particular, when one switches out a module on which other modules depend,
the dependent modules are not successfully reloaded. Even with the
Automated module handling
feature (introduced in
4.2
), the dependent modules are unloaded but do not get reloaded properly since currently this feature attempts to reload based on the fully qualified name of the loaded module (which includes a dependency on the module switched out), not the specification used when the module was loaded. - In general, when the user tries to load a module based on a partially
specified modulename, the
.modulerc
files handle it well, and the latest version of the module consistent with the specification and previously loaded modules will be used. If no compiler was previously loaded, will use the default compiler, or the latest compiler if nothing matches the default compiler. - Modules will fail with an error message if user tries to load a package which was not built for the values of the dependency packages loaded.
Modulepath-based Strategy¶
This strategy makes use of the ability of modules to support multiple
directories in the MODULEPATH
environment variable. Every time a module is loaded
on which other modules might depend, a new path is added to MODULEPATH
containing the modulefiles which depend on the newly added module.
This is basically similar to the strategy that is used in the hierarchical modulefile approach of Lmod.
Implementation¶
The Homebrewed flavors and Modulerc-based strategies were based on modifying the modulefiles of modules which depended on other modules. The Modulepath-based strategy, in contrast, is based on modifying the modulefiles for modules which other modules might depend on.
To begin with, we set MODULEPATH
to a Core
directory containing
modulefiles for modules which do not depend on any other modules.
The modulefiles for compilers will typically be put in here.
For this example, we opt not to use a dummy simd module (for reasons
explained later), but instead add avx
, avx2
, sse4.1
variants to the
bar modules, but otherwise they might belong here. Other modules which
do not depend on compilers, etc. could be place in here as well, e.g.
applications which do not expose libraries, etc. So the directory
structure would look like:
Core
├── gcc
│ ├── 8.2.0
│ ├── 9.1.0
│ └── common
├── intel
│ ├── 2018
│ ├── 2019
│ └── common
└── pgi
├── 18.4
├── 19.4
└── common
A typical common file for the gcc compiler would be something like
# Example modulefiles for compiler-etc-dependency cookbook
# For "modulepath based" strategyy
#
# Common stuff for gcc
#
# Expects version to have been previously set
proc ModulesHelp { } {
global version
puts stderr "
This is the dummy GNU compiler suite modulefile for the cookbook
Handling Compiler and other Package Dependencies
It does not actually do anything
gcc version: $version
"
}
module-whatis "Dummy Gnu $version for cookbook"
# Find the software root. In production, you should
# hardcode to your real software root
set gitroot $::env(MOD_GIT_ROOTDIR)
set swroot $gitroot/doc/example/compiler-etc-dependencies/dummy-sw-root
set pkgroot $swroot/gcc
set vroot $pkgroot/$version
set bindir $vroot/bin
prepend-path PATH $bindir
# don't load multiple versions of this module (or other compilers)
conflict gcc
conflict gnu
conflict pgi
conflict intel
# Add the proper modulepath
# In production this should be hard-coded, but using $gitroot for cookbook
set modpathroot $gitroot/doc/example/compiler-etc-dependencies/modulepath
set newmodpath $modpathroot/Compiler/gcc/$version
module use $newmodpath
The most interesting aspect is the module use
at the end. We add
to MODULEPATH
a directory under Compiler
for this specific compiler
and version. Other compilers/versions would add their own specific path
to MODULEPATH
.
In each of these compiler specific directories, modulefile directory trees exist for the supported MPI libraries and bar. We also include a foo directory containing the non-MPI variants of foo. It would look like:
Compiler
├── gcc
│ ├── 8.2.0
│ │ ├── bar
│ │ │ ├── 4.7
│ │ │ │ ├── avx
│ │ │ │ ├── .modulerc -> symlink to modulerc.default_lowest_simd
│ │ │ │ └── sse4.1
│ │ │ └── common -> symlink to bar/common
│ │ ├── foo
│ │ │ ├── 1.1
│ │ │ └── common -> symlink to foo/common
│ │ ├── mvapich
│ │ │ ├── 2.1
│ │ │ └── common -> symlink to mvapich/common
│ │ └── openmpi
│ │ ├── 3.1
│ │ └── common -> symlink to openmpi/common
│ └── 9.1.0
│ ├── bar
│ │ ├── 5.4
│ │ │ ├── avx
│ │ │ ├── avx2
│ │ │ └── .modulerc -> symlink to modulerc.default_lowest_simd
│ │ └── common -> symlink to bar/common
│ ├── foo
│ │ ├── 2.4
│ │ └── common -> symlink to foo/common
│ ├── mvapich
│ │ ├── 2.1
│ │ ├── 2.3.1
│ │ └── common -> symlink to mvapich/common
│ └── openmpi
│ ├── 3.1
│ ├── 4.0
│ └── common -> symlink to openmpi/common
├── intel
│ ├── 2018
│ │ └── ... modules depending on compiler=intel/2018
│ └── 2019
│ └── ... modules depending on compiler=intel/2019
└── pgi
├── 18.4
│ └── ... modules depending on compiler=pgi/18.4
└── 19.4
└── ... modules depending on compiler=pgi/18.4
For brevity, we only show the directory structure for the modules depending on the two versions of gcc in detail; the other compilers will have similar structures.
Basically, there is a separate modulepath for each compiler, containing only the
modulefiles depending on that specific build of the compiler (and not also depending
on something else, like MPI library).
This certainly enforces the consistency of loaded modules; one could not load
a specific version of gcc (say gcc/9.1.0
) and an incompatible version of foo (e.g. foo/1.1
),
because all of the foo modulefiles are in compiler specific module trees and there is
no foo/1.1
in the gcc/9.1.0
module tree. Conflict statements in the compiler modulefiles
will prevent one from loading multiple compilers, thereby preventing multiple compiler
specific modulepaths (unless the user explicitly does a module use
or similar, and
there is only so far one can go in preventing users from shooting themselves in the foot).
The modulefiles for foo and bar are fairly straightforward; we have a common file which
does the heavy lifting (and since this can be made independent of version and compiler, this
is actually a symlink to a package specific common file in a common
directory external
to the modulepath trees).
We then add some small stubfiles which set variables for the specific build information, which
mostly are determined by their position in the tree structure (e.g. the stubfiles under
Compiler/gcc/9.1.0
are all going to set compilerTag
to gcc/9.1.0
, etc), and
then invoke the common file.
The modulefiles for openmpi are largely similar. E.g., for gcc/9.1.0
we have a small
stubfile like the following (for version 4.0
)
#%Module
# Dummy modulefile for openmpi
set version 4.0
set compilerTag gcc/9.1.0
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/common
which defines the version and compilerTag variables for the OpenMPI version and compiler version, and then invokes the common script
# Common modulefile for openmpi
# Using "modulepath" strategy
# Expects the following variables to have been
# previously defined:
# version: version of openmpi
# compilerTag: compiler being used with
# Declare the path where the packages are installed
# The reference to the environment variable is a hack
# for this example; normally one would hard code a path
set rootdir $::env(MOD_GIT_ROOTDIR)
set swroot $rootdir/doc/example/compiler-etc-dependencies/dummy-sw-root
proc ModulesHelp { } {
global version compilerTag
puts stderr "
openmpi: Test dummy version of OpenMPI $version
For testing packages depending on compilers/MPI
Version: $version
Compiler: $compilerTag
"
}
module-whatis "Dummy openmpi $version (for $compilerTag)"
# Find the software root. In production, you should
# hardcode to your real software root
set gitroot $::env(MOD_GIT_ROOTDIR)
set swroot $gitroot/doc/example/compiler-etc-dependencies/dummy-sw-root
# Compute the installation prefix
set pkgroot $swroot/openmpi
set vroot $pkgroot/$version
set prefix $vroot/$compilerTag
# We need to prereq the compiler to allow autohandling to work
prereq $compilerTag
# Set environment variables
setenv MPI_DIR $prefix
set bindir $prefix/bin
set libdir $prefix/lib
set incdir $prefix/include
prepend-path PATH $bindir
prepend-path LIBRARY_PATH $libdir
prepend-path LD_LIBRARY_PATH $libdir
prepend-path CPATH $incdir
# Add the proper modulepath
# In production this should be hard-coded, but using $gitroot for cookbook
set modpathroot $gitroot/doc/example/compiler-etc-dependencies/modulepath
set newmodpath $modpathroot/CompilerMPI/$compilerTag/openmpi/$version
module use $newmodpath
which does the usual stuff (define a help function, whatis string, and sets assorted environment
variables like PATH
, LIBRARY_PATH
, etc. for using OpenMPI), and then adds another directory
to the MODULEPATH
. This new directory, under CompilerMPI
is for modulefiles which
depend on the compiler AND the MPI library. (It is assumed that all modulefiles depending on
MPI libraries also depend on the compiler). This new branch in the modulepath would have
a structure like
CompilerMPI
├── gcc
│ ├── 8.2.0
│ │ ├── mvapich
│ │ │ └── 2.1
│ │ │ └── foo
│ │ │ ├── 1.1
│ │ │ └── common -> symlink to foo/common
│ │ └── openmpi
│ │ └── 3.1
│ │ └── foo
│ │ ├── 1.1
│ │ └── common -> symlink to foo/common
│ └── 9.1.0
│ ├── mvapich
│ │ └── 2.3.1
│ │ └── ... modules depending on gcc/9.1.0 and mvapich/2.3.1
│ └── openmpi
│ └── 4.0
│ └── ... modules depending on gcc/9.1.0 and openmpi/4.0
├── intel
│ ├── 2018
│ │ ├── intelmpi
│ │ │ └── default
│ │ │ └── ... modules depending on intel/2018 and its included MPI lib
│ │ ├── mvapich
│ │ │ └── 2.1
│ │ │ └── ... modules depending on intel/2018 and mvapich/2.1
│ │ └── openmpi
│ │ └── 3.1
│ │ └── ... modules depending on intel/2018 and openmpi/3.1
│ └── 2019
│ ├── intelmpi
│ │ └── default
│ │ └── ... modules depending on intel/2019 and its included MPI lib
│ ├── mvapich
│ │ └── 2.3.1
│ │ └── ... modules depending on intel/2019 and mvapich/2.3.1
│ └── openmpi
│ └── 4.0
│ └── ... modules depending on intel/2019 and openmpi/4.0
└── pgi
├── 18.4
│ ├── mvapich
│ │ └── 2.1
│ │ └── ... modules depending on pgi/18.4 and mvapich/2.1
│ └── openmpi
│ └── 3.1
│ └── ... modules depending on pgi/18.4 and openmpi/3.1
└── 19.4
└── openmpi
├── 3.1
│ └── ... modules depending on pgi/19.4 and openmpi/3.1
└── 4.0
└── ... modules depending on pgi/19.4 and openmpi/3.1
Basically, there is a separate modulepath for each combination of compiler and MPI library, listing all modulefiles depending on that compiler and MPI library. The modulefiles underneath each directory simply do what is needed to load that version of the package built with the specified compiler and MPI library.
This process could be continued further, as needed. E.g., if you had packages which
depended on NetCDF, and you had multiple builds of NetCDF for a given compiler/MPI
combination, you could add another modulepath tree, e.g. CompilerMPINetCDF
,
branching on each compiler, MPI, and NetCDF triplet. But things can also get
unwieldy if carried too far.
One could also add modulepath trees for disjoint features like SIMD level, but this turns out to be a bit tricky. E.g., if you had a simd branch as well as a compiler branch, with both simd and compiler appearing in Core, things are fine for the Simd and Compiler trees. However, if there were to be modules depending on both, e.g. a CompilerSimd branch, then because compiler and simd are disjoint and could be loaded in either order, the modulefiles for both would need to handle adding the CompilerSimd branch depending on whether the other was previously loaded.
Examples¶
We now look at the example usage for the Modulepath-based strategy. To use these examples, you must:
- Set (and export)
MOD_GIT_ROOTDIR
to where you git-cloned the modules source - Do a
module purge
- Set your
MODULEPATH
to$MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Core
Note that we set the MODULEPATH
to the Core subdirectory; the Core branch is for those modulefiles
that do not depend on compiler or MPI library, and that should be available from the start.
As with the previous cases, we start with a module avail
command, and here
we see the first big difference:
[mod4 (modulepath)]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Core -
gcc/8.2.0 gcc/9.1.0 intel/2018 intel/2019 pgi/18.4 pgi/19.4
[mod4 (modulepath)]$ module load gcc/9.1.0
[mod4 (modulepath)]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Compiler/gcc/9.1.0 -
bar/5.4/avx(default) foo/2.4 mvapich/2.3.1 openmpi/4.0
bar/5.4/avx2 mvapich/2.1 openmpi/3.1
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Core -
gcc/8.2.0 gcc/9.1.0 intel/2018 intel/2019 pgi/18.4 pgi/19.4
[mod4 (modulepath)]$ module load openmpi/4.0
[mod4 (modulepath)]$ module avail
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/CompilerMPI/gcc/9.1.0/openmpi/4.0 -
foo/2.4
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Compiler/gcc/9.1.0 -
bar/5.4/avx(default) foo/2.4 mvapich/2.3.1 openmpi/4.0
bar/5.4/avx2 mvapich/2.1 openmpi/3.1
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Core -
gcc/8.2.0 gcc/9.1.0 intel/2018 intel/2019 pgi/18.4 pgi/19.4
When we first do a module avail
, we only see the modulefiles for the compilers.
The MPI libraries, foo, bar, etc. all depend on at least the compiler, and so
will not become "available" until a compiler (and possibly MPI library as well) is loaded.
In a production environment there would likely be other modulefiles available in Core
(i.e. an application which is only used as a standalone application and does not
provide an API/libraries to link against would likely be placed in Core), but in our
simple example, only the compilers appear in Core. As we load a compiler and then an
MPI library, additional modulefiles appear available. In a production environment, one
might wish to set things up so that a compiler (and maybe MPI library) modulefile is
automatically loaded when the user logs in.
The downside of this is that it becomes difficult for an user to know what software
is available, at least via the module command. I.e., if application foobar is only built
for a single compiler/MPI combination, it will not show up in module avail unless that
specific compiler/MPI combination were previously loaded. Lmod adds a module spider
command which allows the user to list all packages installed for any compiler/MPI
combination, and can be used to also find out which compiler/MPI combinations are needed
to access a specific modulefile, but Environment Modules does not have a comparable function
at this time. If you were to use this strategy in a production environment, you would
likely need to generate lists of available packages (and their compiler/MPI/etc dependencies)
in a web page or other documentation area which can be frequently updated.
The standard functionality of selecting the correct build of a package based on the loaded compiler, e.g.
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load pgi/19.4
[mod4 (modulepath)]$ module load openmpi/4.0
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (modulepath)]$ module unload openmpi
[mod4 (modulepath)]$ module switch --auto pgi intel/2019
[mod4 (modulepath)]$ module load openmpi/4.0
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4 (modulepath)]$ module unload openmpi
[mod4 (modulepath)]$ module switch --auto intel gcc/9.1.0
[mod4 (modulepath)]$ module load openmpi/4.0
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/4.0, gcc/9.1.0)
[mod4 (modulepath)]$ module unload openmpi
[mod4 (modulepath)]$ module switch --auto gcc gcc/8.2.0
[mod4 (modulepath)]$ module load openmpi/4.0
ERROR: Unable to locate a modulefile for 'openmpi/4.0'
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0
works as expected. As shown in the last command above, when requesting a module not
built for the loaded compiler (e.g. openmpi/4.0
when gcc/8.2.0
is loaded), the module command
simply returns Unable to locate a modulefile
as there is no corresponding modulefile
in the current list of MODULEPATHS.
The functionality of the module switch
command depends on version and/or settings
of Environment Modules. For version 3.x, or 4.x with the Automated module handling
feature disabled, it does not work well, modules which depend on the switched out module
are not reloaded, leading to inconsistent environments. But for 4.x versions with
the automated module handling feature enabled (as indicated by the --auto after the
switch, although that can be made the default), it works as expected. Modules depending
on the module being switched out get unloaded and reloaded if possible, as shown below:
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load pgi/19.4
[mod4 (modulepath)]$ module load openmpi
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/4.0
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/4.0, pgi/19.4)
[mod4 (modulepath)]$ module switch --auto pgi intel/2019
Switching from pgi/19.4 to intel/2019
Unloading dependent: openmpi/4.0
Reloading dependent: openmpi/4.0
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/4.0, intel/2019)
[mod4 (modulepath)]$ module switch --auto intel intel/2018
Switching from intel/2019 to intel/2018
ERROR: Unable to locate a modulefile for 'openmpi/4.0'
WARNING: Reload of dependent openmpi/4.0 failed
Unloading dependent: openmpi/4.0
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2018
[mod4 (modulepath)]$ mpirun
mpirun: command not found
The modulefiles themselves basically have no support for defaulting a compiler; the modulefiles for the various MPI libraries are simply not even available until a modulefile for a compiler is loaded, as seen below:
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load openmpi/3.1
ERROR: Unable to locate a modulefile for 'openmpi/3.1'
[mod4 (modulepath)]$ module list
No Modulefiles Currently Loaded.
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load gcc/8.2.0
[mod4 (modulepath)]$ module load openmpi
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) openmpi/3.1
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/3.1, gcc/8.2.0)
However, this could be somewhat mitigated by having the modulefile for the default compiler automatically loaded for the user upon login (e.g. in their dot files).
The situation is similar for foo:
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load pgi/19.4
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (pgi/19.4, nompi)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module load openmpi/3.1
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/19.4 2) openmpi/3.1 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (pgi/19.4, openmpi/3.1)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module unload openmpi
[mod4 (modulepath)]$ module switch --auto pgi intel/2019
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module load intelmpi
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) intelmpi/default 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, intelmpi)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module switch --auto intelmpi mvapich/2.3.1
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) mvapich/2.3.1 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, mvapich/2.3.1)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module switch --auto mvapich openmpi/4.0
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) openmpi/4.0 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, openmpi/4.0)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module unload openmpi
[mod4 (modulepath)]$ module switch --auto intel/2019 gcc/9.1.0
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (gcc/9.1.0, nompi)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module load mvapich/2.3.1
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) mvapich/2.3.1 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (gcc/9.1.0, mvapich/2.3.1)
[mod4 (modulepath)]$ module unload foo
[mod4 (modulepath)]$ module switch --auto mvapich openmpi/4.0
[mod4 (modulepath)]$ module load foo/2.4
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) openmpi/4.0 3) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (gcc/9.1.0, openmpi/4.0)
As expected, the correct version of foo is loaded depending on the previously
loaded compiler and MPI libraries. Here again we use an intelmpi
modulefile
to indicate when we wish to use Intel MPI libraries, even though they are enabled
by the intel
module. The intelmpi
modulefile basically just adds the modulepath
for the intel-compiler and intelmpi dependent modules.
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load pgi/18.4
[mod4 (modulepath)]$ module load openmpi/3.1
[mod4 (modulepath)]$ module load foo/1.1
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 2) openmpi/3.1 3) foo/1.1
[mod4 (modulepath)]$ foo
foo 1.1 (pgi/18.4, openmpi/3.1)
[mod4 (modulepath)]$ module switch --auto pgi intel/2018
Switching from pgi/18.4 to intel/2018
Unloading dependent: foo/1.1 openmpi/3.1
Reloading dependent: openmpi/3.1 foo/1.1
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2018 2) openmpi/3.1 3) foo/1.1
[mod4 (modulepath)]$ foo
foo 1.1 (intel/2018, openmpi/3.1)
[mod4 (modulepath)]$ mpirun
mpirun (openmpi/3.1, intel/2018)
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load intel/2019
[mod4 (modulepath)]$ module load foo
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, nompi)
[mod4 (modulepath)]$ module load openmpi
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4 3) openmpi/4.0
[mod4 (modulepath)]$ foo
foo 2.4 (intel/2019, nompi)
Note again the same deficiency in the switch report as the Homebrewed Flavors Strategy
had; in the last case above wherein we loaded foo with intel/2019
loaded
but no MPI module. As expected, a non-MPI build of foo was loaded. However, when an
openmpi module is subsequently loaded, foo does not get reloaded and we still have
the non-MPI build of foo, as evidenced by the output of the foo command. And that
this fact is not obvious from the module list output.
The behavior when defaulting is nicer. Without any compiler or MPI libraries
Here we note a deficiency in the switch support as compared to Flavours. In the last example
after loading intel/2019
and foo, we have the non-MPI build of foo as expected. However, upon
subsequently loading the openmpi module, we still have the non-MPI version of foo loaded, as evidenced
by the output of the dummy foo command. I.e., the foo package was not automatically reloaded, as
there was no prereq in the foo modulefile on an MPI library (as in the non-MPI build there is no MPI
library to prereq). Also note that module list does not really inform one of this fact.
The ability to default partial modulenames in this strategy is mixed. Without any compiler loaded, most modulefiles are not even visible/available. However, once a compiler is loaded, trying to load a module without specifying the version will end up loading the latest version compatible with the loaded compiler (as no incompatible versions are visible) as seen below:
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load foo
ERROR: Unable to locate a modulefile for 'foo'
[mod4 (modulepath)]$ module load gcc/8.2.0
[mod4 (modulepath)]$ module load foo
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) foo/1.1
[mod4 (modulepath)]$ foo
foo 1.1 (gcc/8.2.0, nompi)
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load gcc/8.2.0
[mod4 (modulepath)]$ module load openmpi
[mod4 (modulepath)]$ module load foo
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) openmpi/3.1 3) foo/1.1
[mod4 (modulepath)]$ foo
foo 1.1 (gcc/8.2.0, openmpi/3.1)
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load foo/1.1
ERROR: Unable to locate a modulefile for 'foo/1.1'
[mod4 (modulepath)]$ module list
No Modulefiles Currently Loaded.
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load pgi/18.4
[mod4 (modulepath)]$ module load foo
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) pgi/18.4 2) foo/1.1
[mod4 (modulepath)]$ foo
foo 1.1 (pgi/18.4, nompi)
This is better than in the Flavours or Homebrewed flavors strategies. If one were to use this strategy in production, it is recommended to have a default compiler module (and maybe even an MPI library, etc) automatically loaded when the user logs in, thereby allowing for a reasonable defaulting ability (and more reasonable module avail output).
The situation with bar is similar. We do not have a dummy simd module,
so the builds with different CPU vectorization support are specified by
appending /avx
, etc. to the bar package name. As with previous strategies,
if one attempts to load a simd variant which was not built for the compiler
loaded, an error will occur.
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load gcc/9.1.0
[mod4 (modulepath)]$ module load bar/5.4/avx2
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) bar/5.4/avx2
[mod4 (modulepath)]$ bar
bar 5.4 (gcc/9.1.0, avx2)
[mod4 (modulepath)]$ module unload bar
[mod4 (modulepath)]$ module load bar/5.4/avx
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) bar/5.4/avx(default)
[mod4 (modulepath)]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4 (modulepath)]$ module unload bar
[mod4 (modulepath)]$ module load bar/5.4/sse4.1
ERROR: Unable to locate a modulefile for 'bar/5.4/sse4.1'
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0
Defaulting is handled well, as shown
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load gcc/9.1.0
[mod4 (modulepath)]$ module load bar
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/9.1.0 2) bar/5.4/avx(default)
[mod4 (modulepath)]$ bar
bar 5.4 (gcc/9.1.0, avx)
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load gcc/8.2.0
[mod4 (modulepath)]$ module load bar/4.7
[mod4 (modulepath)]$ module list
Currently Loaded Modulefiles:
1) gcc/8.2.0 2) bar/4.7/sse4.1(default)
[mod4 (modulepath)]$ bar
bar 4.7 (gcc/8.2.0, sse4.1)
In particular, one case specify bar/avx2
or bar/avx
or bar/sse4.1
and the
latest version of bar consistent with the specification and any previously
loaded compiler (or default compiler) will be loaded
Summary of Modulepath-based strategy¶
- It is quite difficult for an user to get an inconsistent environment, at least when automated module handling mode is used. The modulepaths are managed so that only modulefiles consistent with the previously loaded compiler/MPI library are visible.
- With automated module handling mode, the module switch command is very nicely supported.
- The module command does not lend itself to readily seeing all the packages
which are installed on the system, nor seeing for which compiler/MPI combinations
a certain package is built. The module avail command just does not show
any modules not compatible with the currently loaded compiler and/or MPI
libraries. Lmod needed to add a
module spider
command to address this, but no such functionality currently exists in Environment Modules. If one were to use this in production, you would need to provide something similar to the Lmod spider sub-command, or at least provide frequently updated web pages or similar with this information. - This strategy involves the use of many more modulepaths than the previously examined strategies, having at least one modulepath per compiler installed, and typically also one for each compiler/MPI library combination. If you add additional layers of dependency, things get even more complicated, which can be limiting. It is especially problematic if you have two disjoint dependencies -- i.e. neither dependencies is dependent on the other; in this case you might load one or the other, or both (in either order). If there are modulefiles dependent on both of these dependencies, the last one loaded (and only the last one) needs to handle adding the appropriate modulepath for the modulefiles depending on both.
- In general, a module will fail to load with an error message
if any dependent module is not already loaded. The error will actually
state that the module cannot be found, as the modulepath containing it will
not be added to the
MODULEPATH
until the modules depended on are loaded. So if you need to default a compiler, etc., you will need to have the user's initialization scripts automatically load the appropriate modulefile upon login. - However, what we have been referring to as "more intelligent defaulting" is effectively supported. I.e., if a user requests to load a package without specifying the version desired, the version will be defaulted to the latest version compatible with the currently loaded compiler and other dependencies. This is because the incompatible versions are not visible in the module tree.
Comparison of Strategies¶
All of the strategies discussed above have their peculiar strengths and weaknesses. The decision of which strategy to use will depend on how these strengths and weaknesses impact your design goals. It is advised to play around in the sandbox environments a bit, as actual use tends to help make clear which downsides you are willing to accept and which you are not.
With the exception of the Flavours, which works best with Environment Modules version 3.x, all of the other strategies work as well or better on the newer 4.x versions of Environment Modules. This difference is most visible in the discussion of features around the module switch command. So in the following discussions we will assume Environment Modules version 3.x for the Flavours strategies, as that is the version it works best with. For all other strategies, we assume Environment Modules version 4.x, with automated module handling mode enabled, as these strategies work best in that scenario.
The Homebrewed flavors, Modulerc-based, and Modulepath-based strategies all require a significant amount of "assembly" in order to get them working for a production environment; the example scripts and procedures provided here should help significantly, but should not be considered as a polished product. You will likely need to customize and extend for your environment. The Flavours Strategy, on the other hand, has been packaged to present as a finished product and so requires less "assembly" to get working, but does not appear to be actively maintained, so the reduced up-front work might be neutralized by the costs of self support.
Basic Dependency Handling¶
All of the strategies discussed support a basic level of dependency handling. If a user attempts to load a package, they get the build of the package appropriate for the previously loaded compiler or other dependencies, or, if no appropriate build is found, an error message indicating such. E.g, if the user does:
module load gcc/8.2.0
module load foo/1.1
their environment will be set up to run foo version 1.1
built
with gcc version 8.2.0
.
All of the strategies discussed meet this criterion, with both 3.x and 4.x versions of Environment Modules.
Advanced Dependency Handling (e.g. the module switch sub-command)¶
Things are more complicated when we allow for the modules upon which other loaded modules might depend to be changed. This generally involves the module switch command.
While all of the strategies handle well the easy case, when we switch a module upon which no other loaded modules depend, the trick comes when one or more currently loaded modules depend on the module being switched out. E.g., if we assume that module foo depends on the previously loaded compiler, then ideally, we would like for a sequence like:
module load intel/2019
module load foo
module switch intel pgi/18.4
to have the same effective outcome as if the user issued the commands:
module load pgi/18.4
module load foo
I.e., switching out the compiler
will cause foo to be reloaded with the new compiler dependency. And ideally
in this example we would have pgi/18.4
loaded along with the latest version
of foo compatible with that compiler.
This is handled reasonably well with the Flavours (using Environment Modules
3.x) and the Homebrewed flavors and
Modulepath-based (both using Environment
Modules 4.x) strategies. For the Homebrewed flavors and
Modulepath-based
strategies, this relies on the Automated module handling feature (As of
version 4
, this is disabled by default. It can be enabled in modulecmd.tcl
,
or by running module config auto_handling 1
, or by adding the --auto
flag
to the modules command.)
For these strategies, swapping out a compiler or other module upon which a loaded module depends will cause the the module with a dependency to be unloaded, the module being switched being swapped out, and the module that had a dependency being reloaded.
Our example sequence above actually exposes a subtle issue. For the Flavours
and Homebrewed flavors strategies, the sequence of loading pgi/18.4
followed
by foo (using our example software library) would fail, as foo would be defaulted to
version 2.4
and as there was no build of foo/2.4
for pgi/18.4
, the module load foo
would fail. And indeed, the switch sequence above would not be completely successful
under either strategy: for the Homebrewed Flavors Strategy, the compiler would be
swapped out and the reload of foo would fail with an error (so effectively
equivalent to the second sequence). For the Flavours Strategy, it detects that
it would be unable to reload foo, and the switch command fails (i.e. the compiler
remains intel/2019
).
For the Modulepath-based Strategy, the second sequence (loading pgi/18.4
then foo) would
actually work, as the modulepath exposed by loading pgi/18.4
only has versions of
foo that are compatible with pgi/18.4
. But the switch command does not work
as well as would be desired. This is because that as currently implemented, when the
automated module handling code does the reload of the module that was unloaded
due to dependencies, it attempts to reload based on the fully qualified name of the
module that was loaded, and not based on the (possibly partial) name specified
when the module was originally loaded. So, after the module load intel/2019
,
the module load foo will result in foo/2.4
being loaded. When we switch out intel/2019
for pgi/18.4
, foo gets unloaded, but after the compiler swap, it tries to reload
foo/2.4
. As there is no build of foo/2.4
for pgi/18.4
(and thus no modulefile in
the current modulepath), the module is not found and is unable to be loaded.
As in the Homebrewed flavors case, the compiler is switched but foo is left unloaded
(with an appropriate warning to that effect).
This same issue prevents the Automated module handling feature as currently implemented from being very useful with the Modulerc-based. Basically, whenever you have a module loaded that depends on another module, switching out the module depended upon will fail to reload the other module. This is true even in less pathological cases, like:
module load intel/2019
module load foo
module switch intel pgi/19.4
which succeeds under the other three strategies (as foo/2.4
is built for pgi/19.4
).
This is because when foo is initially loaded in the above scenario, the actual modulename
loaded is foo/intel/2019/2.4
. With the switch command, foo gets unloaded, the compilers
are switched, and the automated modules handling code tries to reload foo/intel/2019/2.4
.
That modulename clearly depends on intel/2019
, not pgi/19.4
, and so will fail to load
(with an error message). The net result is that the compiler gets switched, but any
modules depending on the compiler (or whatever module being switched) get unloaded
(with a warning to that effect). It is hoped that a future version of the
Automated module handling feature will have an option to reload the dependent
modules using the modulename they were loaded with; this should allow for the
switch command to work well in the Modulerc-based Strategy, as well as make
edges case (like the pgi/18.4
example discussed above) work better with the
Modulepath-based Strategy.
There is another edge case which only the Flavours Strategy handles well. Consider a scenario like:
module purge
module load intel/2019
module load foo
foo
# this should be foo/2.4 built for intel/2019 without MPI
module load openmpi
foo
# What build is this, with or without MPI?
With the Flavours Strategy, the final foo will be built for intel/2019
with openmpi support; i.e. Flavours supports the concept of optional prerequisites, and foo has
an optional prerequisite on the MPI libraries, so when openmpi is loaded, any previously loaded modules
which depend on it (through a regular or optional prerequisite) get reloaded.
All of the other strategies rely on automated module handling mode for automatic reloads, and in this case no reload of foo will be initiated as foo does not have MPI libraries listed as a prerequisite (otherwise a no MPI version could not be loaded). This is especially problematic for the Homebrewed flavors and Modulepath-based strategies, since it is not easily to tell from a module list or similar command which version of foo the environment is set for (for the Modulerc-based Strategy, the full modulename from module list will indicate that).
However, despite some potential issues with some edge cases, the Flavours, Homebrewed flavors, and Modulepath-based strategies all handle this challenge well. The Modulerc-based approach has a poor showing (although at least the modules depending on the module switched out will be unloaded, so the set of loaded modules is consistent).
Note also that this topic shows the most dependence on the version of Environment Modules. For the Flavours Strategy, the switching of a module upon which other modules depended does not work (the wrapper script returned weird errors). The other strategies all rely on the Automated module handling feature to enable the unload and reload of modules which depend on the module being switched out. Thus for 3.x versions of Environment Modules, the switch of a compiler, etc. will only result in the compiler being replaced, and any modules which depend on the compiler will not be reloaded. This means they will still be pointing to versions built for the old compiler, leading to an inconsistent set of modules being loaded. This is particularly bad in the Homebrewed flavors case, as a module load will not even inform one of that fact. Even if automated module handling mode is disabled on version 4.x of Environment Modules situation is better as loaded environment consistency is assured: the switch of a compiler will be denied since a dependent module is detected loaded.
Visibility into what packages are available¶
Another set of criteria to weigh has to do with visibility into the available packages. We are interested in
- Viewing all of the packages installed on a system
- Determining what versions of a specific package are available for a given compiler/MPI/etc combination.
- Seeing what compiler/MPI/etc combinations a specific version of a package
- For packages that we have currently loaded, determining which compiler/MPI/etc they were built for.
In terms of seeing all of packages that are available, the Flavours and
Homebrewed flavors strategies
are probably the best. The module avail
command will list all modulefiles available, which will
typically just be a list of packagename/version for each installed version. On a production system
with many packages installed, even this can be a bit overwhelming to the user.
The module avail
command will also list all modulefiles for every installed package in the
Modulerc-based Strategy, but here every build of every version of every package will have a distinct modulefile. I.e.,
you will not just have foo/1.1
and foo/2.4
listings, but foo/1.1/gcc/8.2.0/nompi
, foo/1.1/gcc/8.2.0/mvapich/2.1
,
foo/1.1/gcc/8.2.0/openmpi/3.1
, foo/1.1/intel/2018/nompi
, foo/1.1/intel/2018/intelmpi
, etc. modulefiles.
Actually, the situation is even worse than that, as in this strategy there are often multiple
modulefiles for the same build in order to ease navigation of the module tree, e.g. we could have
foo/1.1/gcc/8.2.0/nompi
and foo/gcc/8.2.0/nompi/1.1
representing the same build of the same package.
Whereas an unqualified module avail
in the Flavours or
Homebrewed flavors strategies can be a bit overwhelming
in a large environment, with the Modulerc-based Strategy it can become practically unusable.
While an unqualified module avail
in the Flavours,
Homebrewed flavors, and especially Modulerc-based strategies
can inundate the user with modulenames, the Modulepath-based Strategy has the opposite problem.
With the Modulepath-based Strategy strategy, the modulefiles are split across multiple, often mutually incompatible, modulepaths, so the module avail
command will never return a list of all modulefiles installed, only those available given the previously loaded
compiler/MPI libraries/etc. E.g., if a package foobar is only installed for a particular compiler/MPI combination,
it will not appear in any module avail listing unless that particular compiler and MPI were previously loaded.
While the number of modulefiles listed in an unqualified module avail
command in the Modulerc-based Strategy
is unwieldy, if one adds a partial package specification argument, the number of modulefiles returned is greatly
reduced. This smaller list can provide information about which compilers/MPI/etc. are compatible with
a specific version of a package. For example, to see the compilers for which foo/2.4
is built, we can
do something like:
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module avail foo/2.4
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc4 -
foo/2.4/gcc/(default) foo/2.4/intel/2019/mvapich/2.3.1
foo/2.4/gcc/9.1.0/mvapich/2.3.1 foo/2.4/intel/2019/nompi
foo/2.4/gcc/9.1.0/nompi(default) foo/2.4/intel/2019/openmpi/4.0
foo/2.4/gcc/9.1.0/openmpi/4.0 foo/2.4/pgi/19.4/nompi(default)
foo/2.4/intel/2019/intelmpi(default) foo/2.4/pgi/19.4/openmpi/3.1
Similarly, to see the builds of foo using gcc compilers, one can do something like:
[mod4 (modulerc)]$ module purge
[mod4 (modulerc)]$ module avail foo/gcc
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulerc4 -
foo/gcc/(default) foo/gcc/8.2.0/openmpi/3.1/1.1
foo/gcc/8.2.0/(default) foo/gcc/9.1.0/mvapich/2.3.1/2.4
foo/gcc/8.2.0/mvapich/2.1/1.1 foo/gcc/9.1.0/nompi/(default)
foo/gcc/8.2.0/nompi/(default) foo/gcc/9.1.0/nompi/2.4
foo/gcc/8.2.0/nompi/1.1 foo/gcc/9.1.0/openmpi/4.0/2.4
The other strategies do not readily provide that information. The next best case is the Modulepath-based Strategy, because here at least a module avail will tell you what versions of a package are compatible with the currently loaded compiler/MPI/etc, e.g.:
[mod4 (modulepath)]$ module purge
[mod4 (modulepath)]$ module load intel/2019
[mod4 (modulepath)]$ module avail foo/2.4
- $MOD_GIT_ROOTDIR/doc/example/compiler-etc-dependencies/modulepath/Compiler/intel/2019 -
foo/2.4
But the Flavours and Homebrewed flavors strategies do not readily show what versions of packages are built for which compilers, etc. You would need to load a compiler/MPI/etc combination, and then try loading a particular version of a package.
Lastly, with the Modulerc-based Strategy, the module list command explicitly shows information about the compiler/MPI/etc used to build the loaded modules, as that is part of the full modulename. This information is not explicitly visible in the other three strategies, but that is usually not a problem. As long as the various user commands result in a set of modules wherein every module depending on either a compiler or MPI library, etc. is built for the currently loaded compiler/MPI library/etc., that information is redundant.
The only cases where this is potentially an issue are the sort of edge cases described in the previous section, e.g. if one were to do something like:
module purge
module load intel/2019
module load foo
foo
# this should be foo/2.4 built for intel/2019 without MPI
module load openmpi
foo
# What build is this, with or without MPI?
In the above example, for the Flavours, Homebrewed flavors, and Modulepath-based strategies a module list at the end would simply list something like:
Currently Loaded Modulefiles:
1) intel/2019 2) foo/2.4 3) openmpi/4.0
For the Flavours Strategy, foo would be built with MPI support, but for the other two, foo would still be the non-MPI build, which is not readily apparent from the above output (although possibly could be inferred by the ordering of the modules).
Conclusions¶
We have presented four strategies for dealing with modulefiles for packages with multiple builds depending on compiler, MPI, and/or other factors. All four strategies can deal with the basic requirement of loading of the correct build of a package depending on the previously loaded dependencies, or failing with a reasonable error message if no such build is available. They all have their own strengths and weaknesses. This document tried to present these strategies objectively and has been made to help you to evaluate how to handle this issue at your site.
Ensure user fully qualify the modules they use¶
When managing a vast software catalog accessible by multiple users, it is often desired that these users understand exactly what are the software they enable in their environment. This is especially important when new software versions are introduced in the catalog.
On a regular Modules installation, if multiple versions of a given module are
available, latest version is selected when user load this software module by
specifying its generic name (module load software
). So when a new version
is installed for software, users automatically end up with this new version
enabled in their environment.
Depending on software, a precise version control may be required to avoid issues. In this case the implicit default version selection done by Modules is not desired. This recipe describe the way to handle this kind of situation.
Implementation¶
Starting version 4.3 of Modules, a new option called
implicit_default
is introduced. When enabled (which means
configuration option is set to 1) if a module is specified by its generic name
an implicit default is automatically defined (latest version) if no explicit
default is defined. When implicit_default
configuration option is disabled
(when set to 0), no implicit default is computed and an error is returned to
user in case module has been specified by its generic name but no default
version has been set.
So to ensure user fully qualify the modules they use, this
implicit_default
configuration option should be disabled. It could be
achieved by setting the option in the initrc
file installed in the
configuration directory (or in the modulerc
file installed in the
initialization script directory if this location is preferred).
#%Module
module config implicit_default 0
It may be desired to lock this option, to ensure users do not alter it
afterward. The locked_configs
configuration option fills this need.
By setting this option and the implicit_default
in a site-specific
configuration script, users will not be able to change the
implicit_default
behavior you configure.
# disable implicit_default option
setConf implicit_default 0
# forbid `implicit_default` config option superseding
lappendConf locked_configs implicit_default
Compatible with Modules v4.3+
Installation¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the initialization RC file of this recipe:
$ cp example/ensure-user-qualify-modules/initrc /etc/environment-modules/
Or if you want to enforce the implicit_default
disablement setup for
users, copy there the site-specific configuration script of this recipe:
$ cp example/ensure-user-qualify-modules/siteconfig.tcl /etc/environment-modules/
If you currently use Modules version 4.3, copy the configuration script specific to this version:
$ cp example/ensure-user-qualify-modules/siteconfig.tcl-4.3 /etc/environment-modules/siteconfig.tcl
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the value of the siteconfig
option:
$ module config siteconfig
Once file is installed, you could verify option value is correct:
$ module config implicit_default
Modules Release 4.3.0 (2019-07-26)
- Config. name ---------.- Value (set by if default overridden) ---------------
implicit_default 0 (locked)
Usage example¶
Enable the modulepath where the example modulefiles are located:
$ module use example/ensure-user-qualify-modules/modulefiles
Attempt to load a module, which does not defined a default version, by its generic name:
$ module load -v softa
ERROR: No default version defined for 'softa'
Load succeed if module is fully qualified:
$ module load -v softa/1
Loading softa/1
For modules which define explicitly a default version, they can still be loaded by their generic name:
$ module load -v softb
Loading softb/1
Expose procedures and variables to modulefiles¶
Same piece of code may be relevant for multiple modulefiles in your setup. Sharing code (procedures and variables) is preferred to redefining it in each modulefile. The following recipe describes an efficient way to define Tcl procedures and variables that will be then available from the modulefile evaluation context.
Implementation¶
To expose site-specific procedures and variables across all modulefiles during their evaluation a site-specific configuration script is proposed.
This script exposes registered procedures to the Tcl interpreters that evaluate either modulerc or modulefile scripts.
By using the env
global array, which holds environment variables,
variables could also be exposed to those Tcl interpreters. Variables exposed
this way, will be found set within modulefile or modulerc evaluation context
but will not be exported to the environment changes the modulecmd.tcl
script produces.
# append site-specific procedures referenced in the g_siteProcsToExposeToItrp
# variable defined below to the list of procedures exposed in the modulefile
# and modulerc evaluation interpreters
proc addSiteProcsToItrpAliasList {itrpaliasvname keyname args} {
# ensure this proc is only called once at itrpaliasvname initialization
trace remove variable $itrpaliasvname write addSiteProcsToItrpAliasList
upvar #0 $itrpaliasvname itrpaliasv
# register each site-specific procedure
foreach procname $::g_siteProcsToExposeToItrp {
if {$keyname ne {}} {
set itrpaliasv($procname) $procname
} else {
lappend itrpaliasv $procname $procname
}
}
}
trace add variable ::g_modfileBaseAliases write addSiteProcsToItrpAliasList
trace add variable ::g_modrcAliases write addSiteProcsToItrpAliasList
# Define here site-specific procedures that should be exposed to modulefile
# and modulerc interpreter contexts
# *Beware* not to override an existing procedure of modulecmd.tcl script
proc mysiteproc {} {
return sitevalue
}
# list all site-specific procedures to expose to modulefile and modulerc
# interpreter contexts
set g_siteProcsToExposeToItrp [list mysiteproc]
# Define here site-specific variables that should be exposed to modulefile
# and modulerc interpreter contexts. Use environment variable env array to
# transmit these variables
# *Beware* not to override an existing environment variable
set env(mysitevar) sitevarvalue
Compatible with Modules v4.2+
Installation¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/expose-procs-vars-to-modulefiles/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the value of the siteconfig
option on Modules
version 4.3 or above:
$ module config siteconfig
On older version of Modules, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
The configuration script proposed should then be adapted to your needs:
- define your own procedures
- register them into the
g_siteProcsToExposeToItrp
list variable to expose them to the modulefile and modulerc evaluation contexts - define your own variables using the
env
array variable
Usage example¶
Enable the modulepath where the example modulefiles are located:
$ module use example/expose-procs-vars-to-modulefiles/modulefiles
Display one of the example modulefiles that makes use of the site-specific
procedure and variable defined in the siteconfig.tcl
script:
$ module show foo
-------------------------------------------------------------------
.../modulefiles/foo/1:
setenv FOO1 sitevalue
setenv FOO2 sitevarvalue
-------------------------------------------------------------------
Load one example modulefile and check that the environment variable it defines, which rely on the site-specific procedure and variable, are well set:
$ module load bar
$ echo $BAR1
sitevalue
$ echo $BAR2
sitevarvalue
Hide and forbid modules¶
module is often used to give access to hundreds of different software to a large variety of users, each of them provided in several versions. In such situation users ends up facing thousands of modulefiles which could be confusing.
On the other side, site's staff needs to decommission older software version to ensure for instance that only the best matches for their hardware resources remain. Such work needs specific care to avoid breaking the computing workflow of users.
This recipe provides examples on how to hide or/and forbid modulefiles to better cope with software life cycles and help both user and staff to get their bearings in large environments.
Implementation¶
The module-hide
and module-forbid
modulefile commands block
respectively the visibility or the load evaluation of the modulefiles they
target. These two commands have a variety of options to inhibit their action
or display specific messages. Combining both commands enables to hide and
forbid specified modulefiles.
Compatible with Modules v4.6+
Note
Modules v4.7+ is required to use the --hidden-loaded
option of
module-hide
command.
Usage examples¶
The use cases below describe situations where hiding or/and forbidding use of modulefiles can be helpful.
The following set of modules will be used in the examples of this recipe. Each
use case will progressively add module-hide
and
module-forbid
statements in modulepath's .modulerc
file to
improve adapt module visibility or forbid access to them.
$ module avail
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 bioappA/1.0 chemappA/1.0 deplibA/1.0
appA/2.0 bioappA/2.0 chemappA/2.0 deplibA/2.0
appB/1.0 bioappB/1.0 chemappB/1.0 deplibB/1.0
appB/2.0 bioappB/2.0 chemappB/2.0 deplibB/2.0
Limiting view to the useful software only¶
With a large number of available modules it is interesting to reduce user's visibility to only report the modules of interest.
Some modules may require other to be loaded as dependency. This is the case
for appA
and appB
which depend on deplibA
or deplibB
. These
two dependency libraries are not interesting by themselves so they could be
hidden by default but they should stay findable for appA
or appB
modules to load their dependency.
module-hide --soft
could be used to address this need.
Designated module will be hidden unless searched. Following lines are added to
modulepath's .modulerc
file
# hide modules only loaded as dependency
module-hide --soft deplibA
module-hide --soft --hidden-loaded deplibB
As a result deplibA
and deplibB
are not returned anymore on a global
avail
sub-command:
$ module avail
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 appB/2.0 bioappB/1.0 chemappA/2.0
appA/2.0 bioappA/1.0 bioappB/2.0 chemappB/1.0
appB/1.0 bioappA/2.0 chemappA/1.0 chemappB/2.0
Yet these modules are still found when loading the modules of the application requiring them:
$ module load appA
Loading appA/2.0
Loading requirement: deplibA/2.0
In some cases it is desirable to hide such dependency modules also when they
are loaded. This could be achieved by using the --hidden-loaded
option of
the module-hide
command. Hidden loaded modules do not appear by
default on list
sub-command output unless --all
is set.
Queries like is-loaded
still detect such modules as loaded even if
hidden. In addition loading or unloading informational messages related to
these modules are not reported unless a verbosity
mode
higher than verbose
is configured.
$ module load appB
$ module list
Currently Loaded Modulefiles:
1) appB/2.0
$ module list --all
Currently Loaded Modulefiles:
1) deplibB/2.0 2) appB/2.0
$ module is-loaded deplibB
$ echo $?
0
Going further, among scientific applications some are only useful for a given scientific field. A site may provide many software covering many scientific fields but a user may only be concerned by one of these fields. In our example software are provided for biology users (bioappA and bioappB) and other software for chemistry users (chemappA and chemappB).
Say every biology users are part of a bio
Unix group and every chemistry
users are member of a chem
Unix group. Available software visibility could
be improved by only reporting the bio software to the bio users and the
chem software to the chem users.
# hide modules not from user's scientific field
module-hide --soft --not-group bio bioappA bioappB
module-hide --soft --not-group chem chemappA chemappB
With the above statements put in modulepath's .modulerc
file, the
bio software are not seen anymore by chem users:
$ module avail
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 appB/1.0 chemappA/1.0 chemappB/1.0
appA/2.0 appB/2.0 chemappA/2.0 chemappB/2.0
However as they are softly hidden, these modules can still be seen if queried
or if --all
option is used:
$ module avail bioappA
-- ../example/hide-and-forbid-modules/modulefiles --
bioappA/1.0 bioappA/2.0
$ module avail --all
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 bioappA/1.0 chemappA/1.0 deplibA/1.0
appA/2.0 bioappA/2.0 chemappA/2.0 deplibA/2.0
appB/1.0 bioappB/1.0 chemappB/1.0 deplibB/1.0
appB/2.0 bioappB/2.0 chemappB/2.0 deplibB/2.0
Software requiring administrative actions prior usage¶
Some software may require an administrative step to get allowed to use them, like the signature of a user agreement. Such software should be reported among the available modules but should not be used prior the administrative step achieved.
In our example, the chemappA
application requires a user charter to be
signed and then sent to the site staff. The access to the chemappA
is
controlled by the chemappA
Unix group: a user needs to be part of this
group to access and use the application.
# forbid use of modules unless software user agreement is signed
set msg {User agreement for ChemAppA application must be validated to use it
1. Please connect to https://ChemAppA.example.org
2. Read the Term of Use and sign it
3. Send back this signed agreement to our service desk}
module-forbid --not-group chemappA --message $msg chemappA
With the above module-forbid
statement put in modulepath's
.modulerc
file, the software is still visible but its load is denied
unless if the user is part of the chemappA
group.
$ module avail chemappA
-- ../example/hide-and-forbid-modules/modulefiles --
chemappA/1.0 chemappA/2.0
$ module load chemappA
ERROR: Access to module 'chemappA/2.0' is denied
User agreement for ChemAppA application must be validated to use it
1. Please connect to https://ChemAppA.example.org
2. Read the Term of Use and sign it
3. Send back this signed agreement to our service desk
A specific message is provided through the --message
option to guide the
user to complete the required administrative step. Once group membership is
acquired, the module can be seamlessly loaded.
$ id --groups --name
chemappA chem
$ module load -v chemappA
Loading chemappA/2.0
Note
Do not forget to protect the access to the directory where the software is installed to really ensure that only allowed users can use it.
Software limited to particular users¶
Some applications may be restricted to a limited set of users. For instance because such application should not be disclosed or because it requires a license that is paid only by a few users.
In our example, the appC
application works with token-based licenses. The
only users that can use this software are those that have paid for a license
token. Other users should not access nor even see the availability of this
application. Users that have bought a license token are added to the appC
Unix group.
# fully hide and forbid modules unless user owns a license token
module-hide --hard --not-group appC appC
set msg {Access is restricted to owners of license token}
module-forbid --not-group appC --message $msg appC
The above statements have been added in modulepath's .modulerc
file.
The module-hide --hard
command is used to completely
remove visibility for non-authorized users.
$ module avail
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 appB/1.0 chemappA/1.0 chemappB/1.0
appA/2.0 appB/2.0 chemappA/2.0 chemappB/2.0
$ module avail appC
$ module load appC
ERROR: Unable to locate a modulefile for 'appC'
The module-forbid
statement added for appC
helps to get a clear
error message for the non-authorized users that are aware of the existence of
the module name and version (instead of getting a modulefile location error).
$ module load appC/2.0
ERROR: Access to module 'appC/2.0' is denied
Access is restricted to owners of license token
Alternatively such restrictions on modulefiles can be achieved by adapting
file permission mode instead of adding statements in modulepath's
.modulerc
file.
$ chmod 640 ../example/hide-and-forbid-modules/modulefiles/appC/*
$ chgrp appC ../example/hide-and-forbid-modules/modulefiles/appC/*
However restricting file permission mode does not enable to authorize several
Unix groups or users to access those modulefiles or to have specific error
messages unlike when module-hide
and module-forbid
commands
are used.
Note
Do not forget to protect the access to the directory where the software is installed to really ensure that only the authorized users can use it.
Software life cycle¶
When providing a new software version, it may be interesting to have a test phase, for instance during one week, to make this new version checked by some some pilot users prior the general availability.
In our example, we are currently November 13th and chempappB/2.0
has been
installed two days ago. A test phase is ongoing and users that are member of
the pilot
Unix group can already access this software prior its general
availability set for November 18th.
# test new version of chemappB prior general availability
module-hide --before 2020-11-18 --not-group pilot chemappB/2.0
With the above statement added to modulepath's .modulerc
file, common
users will not see the new module until November 18th.
$ date
Fri 13 Nov 2020 02:04:21 PM CET
$ module avail chemappB
-- ../example/hide-and-forbid-modules/modulefiles --
chemappB/1.0
At some point software need to be decommissioned to ensure for instance that buggy or under-optimized versions are not used anymore by users.
In our example, appA/1.0
needs to be removed as a newer version is
available for appA and this new version fixes a lot of issues that were
encountered with version 1.0. Decommission date for appA/1.0
is planned on
November 18th.
# decommission of old version of appA
set nearmsg {appA/1.0 will be decommissioned, please use appA/2.0}
set msg {appA/1.0 is decommissioned, please use appA/2.0}
module-hide --hard --after 2020-11-18 --not-group eol appA/1.0
module-forbid --after 2020-11-18 --not-group eol \
--nearly-message $nearmsg --message $msg appA/1.0
The above statements added to modulepath's .modulerc
file will remove
visibility and access to the decommissioned module on November 18th. Only
users part of the eol
Unix group will still keep an access to the software
(which is useful in case some users are unfortunately stuck on this specific
version of appA). Specific messages are set to guide users toward selecting
another version for appA.
$ module avail appA
-- ../example/hide-and-forbid-modules/modulefiles --
appA/1.0 appA/2.0
$ module load appA/1.0
Loading appA/1.0
WARNING: Access to module will be denied starting '2020-11-18'
appA/1.0 will be decommissioned, please use appA/2.0
Loading requirement: deplibA/1.0
Prior decommission date, module will still be visible and loadable. However
when loading the module a warning message will appear when the expiry date
will be close. The nearly_forbidden_days
module configuration defines starting when such warning message should be
reported prior decommission date (14 days by default).
$ module config nearly_forbidden_days
Modules Release 4.6.0 (2020-09-16)
- Config. name ---------.- Value (set by if default overridden) ---------------
nearly_forbidden_days 14
Once the decommissioned date is over, appA/1.0
has disappeared unless for
users member of the eol
Unix group.
$ date
Thu 19 Nov 2020 02:46:27 PM CET
$ module avail appA
-- ../example/hide-and-forbid-modules/modulefiles --
appA/2.0
$ module load appA/1.0
ERROR: Access to module 'appA/1.0' is denied
appA/1.0 is decommissioned, please use appA/2.0
Note
Do not forget to protect the access to the directory where the software is installed prior its general availability and after its decommissioned date.
Inhibit output of informative messages¶
Since Modules v4.2, additional module load or unload triggered by the load or the unload of a modulefile are reported to the user to help understand what happened automatically. These informative messages may not be desired sometimes and here is a proposed way to inhibit them.
Implementation¶
Starting version v4.3, a verbosity
configuration option is
introduced to increase or decrease the variety of the messages produced by the
module
command. To inhibit the output of the info-level messages, the
concise
verbosity level should be selected:
$ module config verbosity concise
For v4.2 versions, a site-specific configuration script is proposed to inhibit the output of the info-level messages.
set g_inhibit_inforeport 1 ;# Non-critical info reporting disabled if == 1
# override 'reportInfo' procedure to inhibit messages if g_inhibit_inforeport
# is set to 1
proc reportInfo {message {title INFO}} {
if {!$::g_inhibit_inforeport} {
# use reportError for convenience but there is no error here
reportError $message 0 $title 0
}
}
Compatible with Modules v4.2
Installation (only for version older than v4.3)¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/inhibit-report-info/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
Usage example¶
With a bare bar
modulefile:
#%Module
And a foo
modulefile that pre-requires bar
:
#%Module
prereq bar
Enable the modulepath where the example modulefiles are located:
$ module use example/inhibit-report-info/modulefiles
Load foo
with auto handling mode enabled. The info-level message
inhibition should let foo
load quiet:
$ module load --auto foo
$
Log module command¶
It is sometimes desired to better understand the module
usage on the
system we manage. Especially to determine what are the modulefiles most used
and what are those never used that could be removed. This recipe describes a
way to track the module
usage by logging each request made.
Implementation¶
Logging module commands is implemented by the use of a site-specific configuration that traces every call to a modulefile evaluation.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | proc logModfileInterp {cmdstring code result op} {
# parse context
lassign $cmdstring cmdname modfile modname
set mode [currentState mode]
if {[info level] > 1} {
set caller [lindex [info level -1] 0]
} else {
set caller {}
}
# only log load and unload modulefile evaluation
if {$mode in {load unload}} {
# add info on load mode to know if module is auto-loaded or not
if {$mode eq {load} && $caller eq {cmdModuleLoad}} {
upvar 1 uasked uasked
set extra ", \"auto\": [expr {$uasked ? {false} : {true}}]"
} else {
set extra {}
}
# produced log entry (formatted as a JSON record)
execLogger "{ \"user\": \"[get-env USER]\", \"mode\": \"$mode\",\
\"module\": \"$modname\"${extra} }"
}
}
# run log procedure after each modulefile interpretation call
trace add execution execute-modulefile leave logModfileInterp
|
This code defines a logModfileInterp
procedure which is set to be
evaluated after each evaluation of the execute-modulefile
procedure with
the trace Tcl command. Thanks to the trace
mechanism
logModfileInterp
receives the arguments passed to execute-modulefile
.
The logModfileInterp
procedure applies filter to only log load and
unload modulefile evaluations. It may be extended to the other evaluation
modes (help, display, test, whatis and refresh) by adapting the
following line:
36 37 | # only log load and unload modulefile evaluation
if {$mode in {load unload}} {
|
In the proposed code, log entries are formatted as a JSON record which is convenient to push these logs in a search and analytics engine like Elasticsearch or Splunk. Such tools help to globally monitor the whole set of log entries produced from thousands of computing nodes.
47 48 49 | # produced log entry (formatted as a JSON record)
execLogger "{ \"user\": \"[get-env USER]\", \"mode\": \"$mode\",\
\"module\": \"$modname\"${extra} }"
|
The logger command is run to generate the log message. This is done
through a specific execLogger
procedure ensuring that the current user
environment does not confuse logger with unexpected version of the
libraries it requires.
13 14 15 16 17 18 19 20 21 22 23 24 | proc execLogger {msg} {
# ensure logger command is executed with system libs
if {[info exists ::env(LD_LIBRARY_PATH)]} {
set ORIG_LD_LIBRARY_PATH $::env(LD_LIBRARY_PATH)
unset ::env(LD_LIBRARY_PATH)
}
exec logger -t module $msg
# restore current user lib setup
if {[info exists ORIG_LD_LIBRARY_PATH]} {
set ::env(LD_LIBRARY_PATH) $ORIG_LD_LIBRARY_PATH
}
}
|
Example code also defines a logModuleCmd
procedure which is set to be
evaluated after each evaluation of the module
and the ml
procedures
with trace Tcl command.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | proc logModuleCmd {cmdstring code result op} {
# parse context
set args [lassign $cmdstring cmdname]
if {[info level] > 1} {
set caller [lindex [info level -1] 0]
} else {
set caller {}
}
# skip duplicate log entry when ml command calls module
if {$cmdname ne {module} || $caller ne {ml}} {
# produced log entry (formatted as a JSON record)
execLogger "{ \"user\": \"[get-env USER]\", \"cmd\": \"$cmdname\",\
\"args\": \"$args\" }"
}
}
# run log procedure after each module or ml command
trace add execution module leave logModuleCmd
trace add execution ml leave logModuleCmd
|
Note
This code example may be extended to log for instance additional
information in each message. The upvar Tcl command may be used to
retrieve variables from the calling context. However beware that the
internal code of Modules may change, so if you rely on internal variables
please re-check the code in the siteconfig.tcl
file deployed after
each upgrade of Modules.
Compatible with Modules v4.2+
Installation¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/log-module-commands/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the value of the siteconfig
option on Modules
version 4.3 or above:
$ module config siteconfig
On older version of Modules, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
Usage example¶
Listing available modulefiles, then loading a bare modulefile, then another one with a dependency and purging everything in the end:
$ ml av --------------- /path/to/modulefiles --------------- bar/1.0 foo/1.0 qux/1.0 $ ml foo $ module load bar Loading bar/1.0 Loading requirement: qux/1.0 $ module purge
A log entry can then be retrieved from system log files:
$ journalctl -q -t module
Sep 12 20:24:01 hostname module[9925]: { "user": "username", "cmd": "ml", "args": "av" }
Sep 12 20:24:02 hostname module[9925]: { "user": "username", "mode": "load", "module": "foo/1.0", "auto": false }
Sep 12 20:24:02 hostname module[9925]: { "user": "username", "cmd": "ml", "args": "foo" }
Sep 12 20:24:03 hostname module[9925]: { "user": "username", "mode": "load", "module": "qux/1.0", "auto": true }
Sep 12 20:24:03 hostname module[9925]: { "user": "username", "mode": "load", "module": "bar/1.0", "auto": false }
Sep 12 20:24:03 hostname module[9925]: { "user": "username", "cmd": "module", "args": "load bar" }
Sep 12 20:24:04 hostname module[9925]: { "user": "username", "mode": "unload", "module": "bar/1.0" }
Sep 12 20:24:04 hostname module[9925]: { "user": "username", "mode": "unload", "module": "qux/1.0" }
Sep 12 20:24:04 hostname module[9925]: { "user": "username", "mode": "unload", "module": "foo/1.0" }
Sep 12 20:24:04 hostname module[9925]: { "user": "username", "cmd": "module", "args": "purge" }
Return file basename on module-info name for full path modulefile¶
When module name is specified as a full pathname, the
module-info name
command used in modulefile was
returning the file basename on Modules compatibility version. Starting version
4 of Modules, the full pathname is returned when module is specified this way
as once loaded this module is identified by its full pathname. This recipe
describes a way to get back the behavior of Modules compatibility version for
the module-info name
modulefile command.
Implementation¶
Return file basename on module-info name
for modules
specified as full path modulefile is implemented by the use of a
site-specific configuration that supersedes the definition of the
module-info name
command to return modulefile basename
instead of full pathname.
# override 'module-info' procedure to return file basename for 'name' action
# when modulefile is specified as a full path file
rename ::module-info ::__module-info
proc module-info {what {more {}}} {
if {$what eq {name}} {
set name [currentModuleName]
if {[isModuleFullPath $name]} {
return [file tail $name]
} else {
return $name
}
} else {
return [__module-info $what $more]
}
}
Compatible with Modules v4.2+
Installation¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/module-info-name-return-basename/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the value of the siteconfig
option on Modules
version 4.3 or above:
$ module config siteconfig
On older version of Modules, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
Usage example¶
With an info/name
modulefile that sets an environment variable with the
result of the module-info name
modulefile command:
#%Module
setenv MODNAME [module-info name]
Load info/name
by its full pathname then check value of the environment
variable set:
$ module load ./example/module-info-name-return-basename/modulefiles/info/name
$ echo $MODNAME
name
Version control your Modulefiles using Git¶
The Modules concept is a great way to manage versions of tools on a common server, but managing the Modulefiles themselves is error-prone when not controlled using a SCM like Git.
Goals¶
- To be able to create, edit, and test Modulefiles without the risk of breaking other users.
- To be able to track changes to the system-wide Modulefiles using Git.
- To enable testing of new tool versions (with their associated Modulefiles) before making the new version generally available (since the new Modulefile will not be public until pushed).
Assumptions¶
Details are tweakable via TCL variables
You have Environment Modules version 4.1 or later installed on your system, and Git version 2.4 or later.
You have a Unix user named
modules
that exists only for managing the Modulefiles, and controlling updates to them.The path
/home/modules/modulefiles
is in yourmodulerc
file:module use --append /home/modules/modulefiles
Other Unix users (not named
modules
) use the modules from/home/modules/modulefiles
.
Principles of Operation¶
First we create a git repo for the Modulefiles.
Then we install a Modulefile named localmodules
that, when loaded,
switches MODULEPATH
to a locally-created git clone of the
Modulefiles. When unloaded, it switches MODULEPATH
back to the
default.
After this, any time a user wants to edit the Modulefiles, he works in
his local git repo. After editing, testing, and committing to the local
git repo, git push
updates the main repository, which (assuming the
user knows the password for user modules
) automatically updates
/home/modules/modulefiles
.
Implementation¶
#%Module4.1
##
## When loaded, use a local git repo for our Modulefiles,
## instead of the system-wide location that is typically used.
##
## This is useful for editing and testing Modulefiles.
##
## Tune to your system:
## $specialuser, $localmoddir, $globalmodfetch, $globalmodpush
##
## Author: Scott Johnson <scottjohnsoninsf@gmail.com>
##
## Originally developed at:
## github.com/scottj97/environment-modules-in-git
eval set [array get env HOME]
# Special Unix username that owns the main Modulefiles repository
set specialuser modules
# Where each user's local copy should go:
set localmoddir $HOME/modulefiles
# Where `git fetch` can find the main repository.
# This must be a filesystem path, since it will also be used by Modules:
set globalmodfetch /home/modules/modulefiles
# Where `git push` should write to the main repository:
set globalmodpush ssh://modules@localhost/home/modules/modulefiles
proc ModulesHelp {} {
global localmoddir
puts stderr "localmodules: switch to local Git repo for Modulefiles\n"
puts stderr {This is useful for editing and testing Modulefiles.}
puts stderr {Usage:}
puts stderr { $ module load localmodules}
puts stderr "Then edit and test modulefiles in $localmoddir"
puts stderr {When complete, git commit and push, then}
puts stderr { $ module unload localmodules}
}
module-whatis {switch MODULEPATH to local git repo}
# Runs `system` and dies if error code is nonzero
proc safeSystem cmd {
set retcode [system $cmd]
if {[expr {$retcode != 0}]} {
error "`$cmd` returned non-zero exit code: $retcode"
}
}
# Make sure $localmoddir is what we expect, so we don't clobber
# anybody's work if they happen to have something unexpected here
proc ensureProperLocalmoddir {} {
global localmoddir
global globalmodfetch
global globalmodpush
# Make sure it's a directory
if {![file isdirectory $localmoddir]} {
error "a file named $localmoddir already exists, and\
I don't want to clobber it"
}
# Make sure it has the expected .git remote setup
if {![file isdirectory [file join $localmoddir .git]]} {
error "expected git repo inside $localmoddir, found none"
}
safeSystem "if \[ `git -C $localmoddir remote get-url origin` !=\
\"$globalmodfetch\" ]; then exit 1; fi"
safeSystem "if \[ `git -C $localmoddir remote get-url --push origin` !=\
\"$globalmodpush\" ]; then exit 1; fi"
}
# No $localmoddir exists, so run `git clone` to create
proc createLocalmoddir {} {
global localmoddir
global globalmodfetch
global globalmodpush
safeSystem "git clone $globalmodfetch $localmoddir"
safeSystem "git -C $localmoddir remote set-url --push origin $globalmodpush"
}
proc checkRepoStatus {} {
global localmoddir
safeSystem "git -C $localmoddir remote update"
safeSystem "git -C $localmoddir status"
}
# Special modules user not allowed to load or unload this.
# Why? Because it would defeat the purpose of tracking changes, if the
# changes were committed by this anonymous special user.
eval set [array get env USER]
if {$USER == $specialuser} {
error "special user $specialuser should not load this module"
}
# create directory if necessary
if [module-info mode load] {
if {![file exists $localmoddir]} {
createLocalmoddir
}
ensureProperLocalmoddir
}
## These two work for load, but not for unload
## (the $globalmodfetch doesn't get put back in):
## remove-path MODULEPATH $globalmodfetch
## append-path MODULEPATH $localmoddir
## These two work for load, but not for unload
## (the $globalmodfetch doesn't get put back in):
## module unuse $globalmodfetch
## module use --append $localmoddir
## This method assumes that $MODULES_REPO is part
## of MODULEPATH, e.g. in your modulerc:
## setenv MODULES_REPO /home/modules/modulefiles
## module use /\$MODULES_REPO
if [module-info mode load] {
setenv MODULES_REPO $localmoddir
}
if [module-info mode unload] {
# unsetenv gets converted to setenv since we're unloading
unsetenv MODULES_REPO $globalmodfetch
}
if [module-info mode load] {
puts stderr "\nSwitched to local modulefiles in $localmoddir"
puts stderr {When editing and testing complete, git commit and push, then:}
puts stderr " $ module unload localmodules\n"
checkRepoStatus
}
Installation¶
First convert the existing Modulefiles into a git repo at
/home/modules/modulefiles
, as user modules
:
cd /home/modules/modulefiles
git init
git add .
git commit -m 'Initial checkin of existing Modulefiles'
# Enable updates when receiving pushes:
git config --local receive.denyCurrentBranch updateInstead
Edit your global $MODULESHOME/init/modulerc
file to use the new
env var MODULES_REPO
instead of hard-coding the path (requires
Modules 4.1). Your modulerc should have:
setenv MODULES_REPO /home/modules/modulefiles
module use /\$MODULES_REPO
(The extra slash required before $MODULES_REPO is a bug to be fixed in 4.2.3.)
Copy the localmodules
file from the Modules source tree to your
repo:
cd /home/modules/modulefiles
curl --output localmodules https://raw.githubusercontent.com/cea-hpc/modules/main/doc/example/modulefiles-in-git/modulefiles/localmodules
Edit paths in the top of localmodules
, if your installation
differs from the assumptions, then:
git add localmodules
git commit -m 'Add localmodules from github.com/cea-hpc/modules'
Usage example¶
As a regular user (i.e. anyone but user modules
):
module load localmodules
cd $HOME/modulefiles
Edit, test, then:
git commit -am 'Make some edits'
git push
module unload localmodules
After a successful push and unload, it is safe to delete your local
$HOME/modulefiles
directory if you wish.
Make defined modulepaths persist over sudo¶
When running a command as another user with sudo
, current user environment
is most of the time flushed for security concerns. As a result, if one would
like to use the modulecmd.tcl
script in such context, an error is returned
as modulecmd.tcl
does not find modulepath defined (MODULEPATH
variable is not set). Following recipe describes how to ensure the default
modulepaths are set every time the modulecmd.tcl
script is run.
Implementation¶
Every time the modulecmd.tcl
script is run, it evaluates during its
start-up phase a global RC file following the same kind of evaluation than for
modulefiles.
To ensure modulepaths are always defined, a check could be added in this
global RC file to verify at least one modulepath is set (thanks to the
is-used
Tcl modulefile command). If no modulepath is found set, the
.modulespath
configuration file, which contains the default modulepaths,
can be parsed to enable on the fly the default modulepaths (with module
use
Tcl modulefile command).
#%Module
# ensure MODULEPATH is always defined, use content of .modulespath config file
# to initialize it if not defined
if {![is-used] && [file readable /usr/share/Modules/init/.modulespath]} {
set fid [open /usr/share/Modules/init/.modulespath r]
set fdata [split [read $fid] "\n"]
close $fid
foreach fline $fdata {
if {[regexp "^\\s*(.*?)\\s*(#.*|)\$" $fline match patharg] == 1
&& $patharg ne {}} {
eval module use --append [split $patharg :]
}
}
}
Compatible with Modules v4.1+
Installation¶
Copy the global RC file of this recipe in the configuration directory:
$ cp example/modulepaths-persist-over-sudo/rc /etc/environment-modules/
The location of the .modulespath
file defined in the proposed RC script
should be adapted to reflect the location where this file is installed on your
setup.
Usage example¶
Without the proposed RC file installed, MODULEPATH
environment
variable is lost through the sudo
call:
$ sudo $MODULES_CMD bash avail >/dev/null
ERROR: No module path defined
Once RC file is installed, flushed MODULEPATH
is restored on the fly based
on .modulespath
configuration file:
$ sudo $MODULES_CMD bash use >/dev/null
Search path for module files (in search order):
/usr/share/Modules/modulefiles
/etc/modulefiles
/usr/share/modulefiles
Thus available modulefiles are found again:
$ sudo $MODULES_CMD bash avail >/dev/null
--------------- /usr/share/Modules/modulefiles ---------------
dot module-git module-info modules null use.own
Use new features without breaking old module command¶
When working on large infrastructure, sometimes the module
command is not
deployed with the same version everywhere. You may have for instance some old
cluster that still uses Modules version 3.2 and a newer supercomputer where
the latest version of Modules 4 is available. In such situation it may
however be desired to share the same modulefile catalog.
People providing software that build software and generate the modulefiles to access them fall in a similar situation: a large variety of Modules version may be in use by the end-users of their build product.
This recipe describes how to use features from the latest version of Modules 4 in modulefiles without breaking the use of these modulefiles from older Modules version.
Implementation¶
The Tcl language provides some introspection mechanisms that help to know what
Tcl procedures are available. In the modulefile or modulerc evaluation
context, it helps to determine what Tcl modulefile commands are known. So by
crafting a conditional test using such mechanism (with Tcl info commands
command) it is possible to test if a new feature is available prior using it.
#%Module
# use module-hide only if available
if {[info commands module-hide] eq {module-hide}} {
module-hide --after 2020-10-01 foo/1.1
}
# use module-forbid only if available
if {[info commands module-forbid] eq {module-forbid}} {
module-forbid --after 2020-10-01 foo/1.1
}
Compatible with Modules v3.2+
Starting version 4.7 of Modules, two new Tcl variables are introduced in the
modulefile and modulerc evaluation context: ModuleTool
and
ModuleToolVersion
. These two variables help to determine respectively
what is the module implementation running and what is its version. With this
knowledge it is possible to adapt modulefile and modulerc code to cope with a
behavior changing over module versions or with different behaviors between
different module implementation. The Tcl modulefile command
versioncmp
has been added along to help comparing software version
number (e.g. 4.10
is newer than 4.7
).
Starting its version 8.4.8
, the Lmod project also supports the
ModuleTool
and ModuleToolVersion
variables and the
versioncmp
modulefile command. It enables having modulefiles
compatible with both module implementations without restricting yourself from
using the advanced features from both projects.
Compatible with Modules v4.7+
Usage example¶
For this recipe, a foo module is available in version 1.1 and 1.2.
Version 1.1 is outdated and it has been decided to hide and forbid it
starting October 2020. For that, the new module-hide
and
module-forbid
modulefile commands introduced in Modules 4.6 are used.
Enable the modulepath where the example modulefiles are located:
$ module use example/new-features-without-breaking-old-module/modulefiles
By using the conditional test code in the modulepath rc file (see Implementation section above), the two new modulefile commands are not used. So older versions of Modules still in use do not benefit from the dynamic hiding and forbidding features however no error are obtained on these setups:
$ module -V | grep ^VERSION=
VERSION=3.2.13
$ module avail -t foo
/path/to/example/new-features-without-breaking-old-module/modulefiles:
foo/1.1
foo/1.2
Yet the dynamic hiding and forbidding features are enabled for setup using Modules 4.6 or newer version:
$ module -V
Modules Release 4.6.0 (2020-09-16)
$ module avail -t foo
/path/to/example/new-features-without-breaking-old-module/modulefiles:
foo/1.2
Now take a look at bar module which provides a version for each Unix group
the current user is member of. User group membership can be retrieved with the
usergroups
sub-command of module-info
starting Modules version
4.6. With older version of Modules, the external command groups
has to be
used to get this information. By using the ModuleTool
and
ModuleToolVersion
Tcl variables it will be possible to determine
if usergroups
sub-command is available on module-info
.
#%Module
if {[info exists ModuleTool] && $ModuleTool eq {Modules}
&& [versioncmp $ModuleToolVersion 4.6] >= 0} {
set grouplist [module-info usergroups]
} else {
set grouplist [exec groups]
}
foreach grp $grouplist {
module-virtual bar/$grp ./.common
}
Querying available bar module versions should match the list of groups of current user:
$ groups
grp1 grp2
$ module avail -t bar
/path/to/example/new-features-without-breaking-old-module/modulefiles:
bar/grp1
bar/grp2
Note
As the new Tcl variables are introduced in Modules 4.7, the use of the new
usergroups
sub-command will only be triggered starting Modules 4.7.
Reduce I/O load¶
With large module setup containing hundreds or even thousands of
modulefiles, the processing of commands module avail
or
module load
. This is especially the case when all these
modulefiles are hosted in a shared filesystem mounted on all nodes of a
supercomputer concurrently used by many users.
Such slowness comes from the analysis of the file hierarchy under each enabled modulepath that determines what files are modulefiles, what are the module aliases or symbolic versions set on them, etc. This analysis generates a significant number of I/O operations that linearly grow with the number of modulefiles. Slowness can be more or less observed depending on the underlying storage system and the number of available modulefiles.
This recipe provides examples of the features of Modules that could be leveraged to reduce the I/O load implied by modulepath analysis. It starts with the generation of an example modulefile setup that will be progressively tweaked to observe I/O load reduction.
A general assumption is made here that the more I/O operations there are, the slower the module commands could be. So reducing the number of these I/O operations leads to reducing the I/O load.
The strace utility, the Linux syscall tracer, will be used to watch the
I/O operations produced by each module command run. Examples will
focus on the module avail
command, which is one of the
most I/O intensive and widely utilized by users.
Implementation¶
Several features of Modules could be used to reduce the number of I/O operations to analyze the content of modulepath:
- Modules Tcl extension library
- Modulepath rc file
- mcookie_check configuration option
- Virtual modules
- Module cache
Each of the above features contributes to an I/O reduction as described in the following section. Combined use of all these features will give the biggest I/O operation save.
Example setup¶
For this recipe, a full modulefile setup has to be generated and it will be progressively modified for the different Modules features that will be used.
2 modulepaths are created with 15 module names in each, each provided in 4
different versions. In one modulepath a .version
rc file is set for
each module name to determine a default version. In the other modulepath a
.modulerc
file is set for each module name to define a symbolic
version.
mkdir -p example/reduce-io-load/applications
mkdir -p example/reduce-io-load/libraries
# create dummy application modulefiles
cd example/reduce-io-load/applications
for n in a b c d e f g h i j k l m n o; do
mkdir app$n;
for v in 1.0 2.0 3.0 4.0; do
echo '#%Module' >app$n/$v;
done;
# define default version with .version file
echo '#%Module' >app$n/.version
echo 'set ModulesVersion 2.0' >>app$n/.version
done
cd -
# create dummy library modulefiles
cd example/reduce-io-load/libraries
for n in a b c d e f g h i j k l m n o; do
mkdir lib$n;
for v in 1.0 2.0 3.0 4.0; do
echo '#%Module' >lib$n/$v;
done;
# define symbolic version with .modulerc file
echo -e '#%Module' >lib$n/.modulerc
echo -e "module-version lib$n/3.0 sym" >>lib$n/.modulerc
done
cd -
Some non-modulefile files are added within these modulepaths to simulate documentation files left by mistake in these directories:
touch example/reduce-io-load/applications/appg/README
touch example/reduce-io-load/applications/appl/README
touch example/reduce-io-load/libraries/libg/README
touch example/reduce-io-load/libraries/libl/README
The file permission mode of some modulefiles is set to protect them from being read and simulate a hidden modulefile:
chmod a-r example/reduce-io-load/applications/appg/1.0
chmod a-r example/reduce-io-load/applications/appl/1.0
chmod a-r example/reduce-io-load/libraries/libg/1.0
chmod a-r example/reduce-io-load/libraries/libl/1.0
Additional modulefiles are created with a magic cookie header telling that they are not compatible with the current version of Modules:
echo '#%Module99' >example/reduce-io-load/applications/appg/5.0
echo '#%Module99' >example/reduce-io-load/applications/appl/5.0
echo '#%Module99' >example/reduce-io-load/libraries/libg/5.0
echo '#%Module99' >example/reduce-io-load/libraries/libl/5.0
Once all of the above steps done, we end up with a small scale regular modulefile setup containing 116 modulefiles available to us.
$ module purge $ export MODULEPATH= $ module use example/reduce-io-load/applications $ module use example/reduce-io-load/libraries $ module -o "" avail -t | wc -l 116
Modules Tcl extension library¶
Modules is shipped by default with a Tcl extension library that extends the Tcl language in order to provide more optimized I/O commands to read a file or a directory content than native Tcl commands do.
Compatible with Modules v4.3+
If we rebuild Modules without this library enabled, we will see the benefits of having it enabled:
make distclean
./configure --disable-libtclenvmodules
make modulecmd-test.tcl
chmod +x modulecmd-test.tcl
eval $(tclsh ./modulecmd-test.tcl bash autoinit)
The strace tool gives the number and the kind of I/O operations
performed during the module avail
command:
$ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \
--silence=attach $MODULES_CMD bash avail 2>no_extlib.out
Once this first stat output is obtained, rebuild Modules with Tcl extension library enabled and fetch icdiff tool to compare results.
make distclean
./configure --enable-libtclenvmodules
make modulecmd-test.tcl lib/libtclenvmodules.so
chmod +x modulecmd-test.tcl
make icdiff
Then collect stats and compare results obtained:
$ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail 2>with_extlib.out $ ./icdiff --cols=76 no_extlib.out with_extlib.out no_extlib.out with_extlib.out calls errors syscall calls errors syscall --------- --------- ---------------- --------- --------- ---------------- 36 2 access 37 2 access 248 close 217 close 2 dup2 2 dup2 8 6 execve 8 6 execve 166 fcntl 12 fcntl 1 getcwd 2 getcwd 128 getdents64 64 getdents64 166 161 ioctl 12 7 ioctl 9 4 lseek 9 4 lseek 50 mmap 54 mmap 86 newfstatat 55 newfstatat 250 10 openat 219 10 openat 2 pipe 2 pipe 10 pread64 10 pread64 354 read 355 read 1452 1452 readlink 25 25 readlink 354 2 stat 196 2 stat 1 unlink 1 unlink 20 write 20 write --------- --------- ---------------- --------- --------- ---------------- 3335 1637 total 1292 56 total
Modules Tcl extension library greatly reduces the number of filesystem I/O
operations by removing unneeded ioctl
, fcntl
and readlink
system
calls done (by Tcl open
command) to read each file. Directory content read
is also improved by fetching hidden and regular files in one pass, which
divides by 2 the number of getdents
call. stat
calls are also reduced
as files found in directories are not checked prior attempting to opening
them.
Modulepath rc file¶
A .modulerc
file found at the root of an enabled modulepath directory is
now evaluated when modulepath is walked through to locate modulefiles. This
file could hold the rc definition of the whole modules located in the
modulepath, instead of having specific .modulerc
or .version
file for
each module directory within the modulepath.
Compatible with Modules v4.3+
Let's migrate the .modulerc
definition under each module directory in the
.modulerc
file at the root of the modulepath directory. And also translate
the content of .version
files in module-version
commands that
could be stored in this top-level rc file. Then all the .modulerc
and
.version
files under module directories are deleted to only keep one
.modulerc
per modulepath.
cd example/reduce-io-load/applications
echo '#%Module' >.modulerc
for n in *; do
v=$(grep set $n/.version | cut -d ' ' -f 3);
echo "module-version $n/$v default" >>.modulerc;
rm -f $n/.version
done
cd -
cd example/reduce-io-load/libraries
echo '#%Module' >.modulerc
for n in *; do
grep module-version $n/.modulerc >>.modulerc;
rm -f $n/.modulerc
done
cd -
Once this change on the module trees has been done, collect new statistics and compare them to those generated previously.
$ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail 2>with_modulepath_rc.out $ ./icdiff --cols=76 with_extlib.out with_modulepath_rc.out with_extlib.out with_modulepath_rc.out calls errors syscall calls errors syscall --------- --------- ---------------- --------- --------- ---------------- 37 2 access 9 2 access 217 close 189 close 2 dup2 2 dup2 8 6 execve 8 6 execve 12 fcntl 12 fcntl 2 getcwd 2 getcwd 64 getdents64 64 getdents64 12 7 ioctl 12 7 ioctl 9 4 lseek 9 4 lseek 54 mmap 54 mmap 55 newfstatat 55 newfstatat 219 10 openat 191 10 openat 2 pipe 2 pipe 10 pread64 10 pread64 355 read 299 read 25 25 readlink 25 25 readlink 196 2 stat 168 2 stat 1 unlink 1 unlink 12 write 12 write --------- --------- ---------------- --------- --------- ---------------- 1292 56 total 1124 56 total
With this change we have saved the access
, stat
, open
, read
and close
calls needed to analyze the 15 .modulerc
and 15 .version
files that have been removed and replaced by 2 top-level .modulerc
files.
mcookie_check configuration option¶
A new configuration option named mcookie_check
has been introduced
to control the verification made to files to determine if they are
modulefiles. By default this configuration option is set to always
and
when searching for modulefiles within enabled modulepaths each file below
these directories is opened to check if it starts with the Modules magic
cookie (i.e., #%Module
file signature).
These historical checks lead to a large number of I/O operations but if the
option is set to the eval
value, files are not checked anymore when
searching for modulefiles, only when evaluating them.
Compatible with Modules v5.1+
Here we are setting the mcookie_check
configuration to the eval
value to skip all test on files hosted in modulepath directories and see what
happens when listing available modulefiles:
$ module config mcookie_check eval $ module -o "" avail -t | wc -l 128 $ module avail -o "" appg appl libg libl appg/1.0 appg/2.0 appg/3.0 appg/4.0 appg/5.0 appg/README appl/1.0 appl/2.0 appl/3.0 appl/4.0 appl/5.0 appl/README libg/1.0 libg/2.0 libg/3.0(sym) libg/4.0 libg/5.0 libg/README libl/1.0 libl/2.0 libl/3.0(sym) libl/4.0 libl/5.0 libl/README
12 more modulefiles are returned. Indeed the file checks done by default are useful but we could disable them if a special care is given to the content of modulepath directories. First, we have to eliminate the non-modulefiles stored in these directories:
rm -f example/reduce-io-load/applications/appg/README
rm -f example/reduce-io-load/applications/appl/README
rm -f example/reduce-io-load/libraries/libg/README
rm -f example/reduce-io-load/libraries/libl/README
Then a module-hide
command in modulepath's .modulerc
file should
be added for each the modulefile that is read-protected through the use of
file permission modes. This way module will know that modulefile is
hidden.
cd example/reduce-io-load/applications
echo 'module-hide --hard appg/1.0' >>.modulerc
echo 'module-hide --hard appl/1.0' >>.modulerc
cd -
cd example/reduce-io-load/libraries
echo 'module-hide --hard libg/1.0' >>.modulerc
echo 'module-hide --hard libl/1.0' >>.modulerc
cd -
A module-hide
command in modulepath's .modulerc
file should also
be defined for each modulefile requiring a specific Modules version in its
magic cookie. module will skip such modulefiles in case its version
is not compatible with them.
cd example/reduce-io-load/applications
echo 'if {$ModuleToolVersion < 99} {' >>.modulerc
echo ' module-hide --hard appg/5.0' >>.modulerc
echo ' module-hide --hard appl/5.0' >>.modulerc
echo '}' >>.modulerc
cd -
cd example/reduce-io-load/libraries
echo 'if {$ModuleToolVersion < 99} {' >>.modulerc
echo ' module-hide --hard libg/5.0' >>.modulerc
echo ' module-hide --hard libl/5.0' >>.modulerc
echo '}' >>.modulerc
cd -
Once this specific setup has been achieved to get in full control of the
content of each modulepaths, we get the accurate listing result with the
eval mode of mcookie_check
.
$ module -o "" avail -t | wc -l 116 $ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail 2>mcookie_check_eval.out $ ./icdiff --cols=76 with_modulepath_rc.out mcookie_check_eval.out with_modulepath_rc.out mcookie_check_eval.out calls errors syscall calls errors syscall --------- --------- ---------------- --------- --------- ---------------- 9 2 access 9 2 access 189 close 65 close 2 dup2 2 dup2 8 6 execve 8 6 execve 12 fcntl 12 fcntl 2 getcwd 2 getcwd 64 getdents64 64 getdents64 12 7 ioctl 12 7 ioctl 9 4 lseek 9 4 lseek 54 mmap 54 mmap 55 newfstatat 55 newfstatat 191 10 openat 63 6 openat 2 pipe 2 pipe 10 pread64 10 pread64 299 read 175 read 25 25 readlink 25 25 readlink 168 2 stat 164 2 stat 1 unlink 1 unlink 12 write 12 write --------- --------- ---------------- --------- --------- ---------------- 1124 56 total 744 52 total
A significant drop in I/O calls can be observed from this finely tuned setup.
open
, read
and close
calls are saved for the 4 non-modulefiles
deleted, the 8 modulefiles made hidden and of course for the 116 regular
modulefiles available. As demonstrated, such gain requires a complete control
over the modulepath content and specific care for unsupported or
read-protected files.
Virtual modules¶
A virtual module stands for a module name associated to a modulefile. Instead
of looking for files under modulepaths to get modulefiles, a virtual module
is defined in .modulerc
file with the module-virtual
modulefile
command which saves walk down I/O operations to analyze modulepath directory
content.
Compatible with Modules v4.1+
Let's create 2 new modulepaths that will only contain a .modulerc
file in
which a virtual module is defined for each existing modulefile in initial
modulepath. Content of the .modulerc
in the initial modulepaths is also
copied in the .modulerc
of the virtual modulepaths.
mkdir example/reduce-io-load/applications-virt
mkdir example/reduce-io-load/libraries-virt
cd example/reduce-io-load/applications
echo '#%Module' >../applications-virt/.modulerc
for mod in */*; do
echo "module-virtual $mod ../applications/$mod" \
>>../applications-virt/.modulerc;
done
grep -v '#%Module' .modulerc >>../applications-virt/.modulerc
cd -
cd example/reduce-io-load/libraries
echo '#%Module' >../libraries-virt/.modulerc
for mod in */*; do
echo "module-virtual $mod ../libraries/$mod" \
>>../libraries-virt/.modulerc;
done
grep -v '#%Module' .modulerc >>../libraries-virt/.modulerc
cd -
Once the setup of the virtual modulepaths is finished, the environment of the module command has to be changed to use these new modulepaths instead of the original ones.
$ module unuse example/reduce-io-load/applications $ module unuse example/reduce-io-load/libraries $ module use example/reduce-io-load/applications-virt $ module use example/reduce-io-load/libraries-virt
Then we can check we obtain the same output as with the original setup, 116 modulefiles available. After that collect I/O operation statistics and compare them to those previously fetched.
$ module -o "" avail -t | wc -l 116 $ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail 2>with_virtual_modules.out $ ./icdiff --cols=76 mcookie_check_eval.out with_virtual_modules.out mcookie_check_eval.out with_virtual_modules.out ... calls errors syscall calls errors syscall --------- --------- ---------------- --------- --------- ---------------- 9 2 access 9 2 access 65 close 35 close 2 dup2 2 dup2 8 6 execve 8 6 execve 12 fcntl 12 fcntl 2 getcwd 2 getcwd 64 getdents64 4 getdents64 12 7 ioctl 12 7 ioctl 9 4 lseek 9 4 lseek 54 mmap 54 mmap 55 newfstatat 25 newfstatat 63 6 openat 33 6 openat 2 pipe 2 pipe 10 pread64 10 pread64 175 read 175 read 25 25 readlink 25 25 readlink 164 2 stat 10 2 stat 1 unlink 1 unlink 12 write 12 write --------- --------- ---------------- --------- --------- ---------------- 744 52 total 440 52 total
A large I/O operation drop is observed with the virtual modulepath setup.
The analysis of the 15 module directories under each of the 2 original
modulepaths is not anymore needed as the .modulerc
in the 2 virtual
modulepaths already point to the modulefile location. stat
, open
,
getdents
and close
I/O calls are saved due to that.
Module cache¶
Module cache can be built for every modulepaths with cachebuild
sub-command. When a cache file is found for an enabled modulepath, this file
is evaluated instead of walking down the content of the modulepath directory.
Compatible with Modules v5.3+
Here we start over the module setup at the end of the Modulepath rc file
section, restoring mcookie_check
configuration to default, building
cache and setting cache read buffer to maximum value.
$ module unuse example/reduce-io-load/applications-virt $ module unuse example/reduce-io-load/libraries-virt $ module use example/reduce-io-load/applications $ module use example/reduce-io-load/libraries $ module config mcookie_check always $ module cachebuild Creating example/reduce-io-load/libraries/.modulecache Creating example/reduce-io-load/applications/.modulecache $ module config cache_buffer_bytes 1000000
Once things are setup, new statistics are collected and compared between when cache is used or when it is ignored.
$ module -o "" avail -t | wc -l 116 $ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail 2>with_cache.out $ strace -f -c -S name -e trace=%file,%desc -U calls,errors,name \ --silence=attach $MODULES_CMD bash avail --ignore-cache 2>no_cache.out $ ./icdiff --cols=76 no_cache.out with_cache.out no_cache.out with_cache.out calls errors syscall calls errors syscall --------- --------- ---------------- --------- --------- ---------------- 9 2 access 10 2 access 183 close 29 close 2 dup2 2 dup2 9 7 execve 9 7 execve 12 fcntl 15 fcntl 1 getcwd 1 getcwd 64 getdents64 12 7 ioctl 15 10 ioctl 9 4 lseek 10 4 lseek 37 mmap 38 mmap 221 2 newfstatat 30 2 newfstatat 187 10 openat 33 10 openat 2 pipe2 2 pipe2 10 pread64 10 pread64 324 read 209 read 35 35 readlink 54 54 readlink 1 unlink 1 unlink 12 write 12 write --------- --------- ---------------- --------- --------- ---------------- 1130 67 total 480 89 total
When a cache is found, one file is read instead of checking all directories and files in modulepath directory. Only the modulefiles and directories that are not accessible for everyone are live checked after reading cache file to see if these elements are available to current user.
It explains the significant I/O call drop that can be observed here. Some I/O calls are slightly higher due to the evaluation of module cache files.
Wrap-up¶
Combining all the 4 first features or last one detailed above leads to a significant drop in I/O operations. Almost all remaining I/O calls are made for the initialization of the module command run.
It is advised to run this recipe code on your setup to observe the I/O load gain you could obtain. As said earlier the less I/O operations there are, the faster the module command could be. But this highly depends on your storage system, on the number of modulefiles and on the number of active users. You may not notice a big difference if your modulefiles are installed on a local SSD storage whereas it can be a game changer if instead the modulefiles are hosted on a shared HDD filesystem that is accessed by hundreds of users.
Source shell script in modulefile¶
When working with large software suite providing a shell script for their
enablement in user environment, it is usually desired to also provide access
to these software through module
. However these software enablement may be
complex and it may be wise to keep using the shell script provided by software
editor rather crafting a modulefile from scratch.
This recipe describes how to make modulefiles for such software by using the enablement shell script provided with them.
Implementation¶
Modules version 4.6 introduces a new sub-command named sh-to-mod
and
a new modulefile command named source-sh
. The sh-to-mod
outputs as a modulefile content the environment changes done by the evaluation
of a shell script passed as argument. On the other hand, the source-sh
modulefile command sources environment changes done by the evaluation of a
shell script passed as argument.
Both new features relies on the same mechanism that starts a designated shell to:
- get current environment state (environment variables, shell aliases, shell functions and current working directory)
- source designated shell script with defined arguments
- get resulting environment state
Once done, environment prior and after script source are compared to determine
the corresponding environment changes and translate those changes into
modulefile commands (setenv
, prepend-path
,
set-alias
, set-function
, ...).
sh-to-mod
outputs these resulting modulefile commands. This output
can be redirected into a file to create a modulefile. source-sh
on
the other hand sources the resulting modulefile commands to evaluate them as
if they were written in the modulefile calling source-sh
.
sh-to-mod
and source-sh
support the following shells: sh, dash,
csh, tcsh, bash, ksh, ksh93, zsh and fish.
Compatible with Modules v4.6+
Basic usage example¶
For this recipe, a dummy software named foo is used as example. foo is
installed in version 1.2 in example/source-script-in-modulefile/foo-1.2
directory and it provides a foo-setup.sh
script to activate itself in
user environment:
#!/bin/bash
export FOOENV="$1"
PATH=$(dirname "${BASH_SOURCE[0]}")/bin:$PATH
export PATH
alias foo='foobin -q -l'
First line of foo-setup.sh
script helps to identify which shell needs to
be used to evaluate it: bash
.
sh-to-mod
may be used to get this script translated as a
modulefile:
$ module sh-to-mod bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1 #%Module prepend-path PATH example/source-script-in-modulefile/foo-1.2/bin set-alias foo {foobin -q -l} setenv FOOENV arg1
Output could be redirected into a foo/1.2
file and make it the modulefile
to enable software foo:
$ mkdir -p modulefiles/foo $ module sh-to-mod bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1 >modulefiles/foo/1.2 $ module use ./modulefiles $ module show foo ------------------------------------------------------------------- modulefiles/foo/1.2: prepend-path PATH example/source-script-in-modulefile/foo-1.2/bin set-alias foo {foobin -q -l} setenv FOOENV arg1 -------------------------------------------------------------------
Instead of transforming shell script in modulefile, a modulefile using
source-sh
modulefile command to evaluate shell script at modulefile
evaluation time may be written:
#%Module4.6
source-sh bash example/source-script-in-modulefile/foo-1.2/foo-setup.sh arg1
When displaying a modulefile using source-sh
modulefile command,
modulefile commands resulting from source-sh
evaluation are reported:
$ module show foo/1.2 ------------------------------------------------------------------- .../modulefiles/foo/1.2: prepend-path PATH example/source-script-in-modulefile/foo-1.2/bin set-alias foo {foobin -q -l} setenv FOOENV arg1 -------------------------------------------------------------------
Loading this foo/1.2
module will enable access to software foo:
$ module load foo/1.2 $ alias foo alias foo='foobin -q -l' $ foo foo, version 1.2
Unloading foo/1.2
module will properly revert these environment settings:
$ module unload foo/1.2 $ alias foo bash: alias: foo: not found $ foobin bash: foobin: command not found
As conclusion, these new features enable to leverage the setup scripts that
are provided along with software to make them reachable from the module
environment.
Usage with shell-specific scripts¶
When the initialization script provided by software only defines environment
variables, this script could be used to setup the user environment through the
use of source-sh
in a modulefile whatever the shell ran by user, as the
module
command will accurately translate script changes into the language
of the running shell.
For instance the foo/1.2
module, that uses the source-sh
modulefile
command over the foo-setup.sh
bash script, could also be used when running
the tcsh
or fish
shell:
$ echo $version tcsh 6.22.03 (Astron) 2020-11-18 (x86_64-unknown-linux) ... $ module show foo/1.2 ------------------------------------------------------------------- .../modulefiles/foo/1.2: prepend-path PATH example/source-script-in-modulefile/foo-1.2/bin set-alias foo {foobin -q -l} setenv FOOENV arg1 ------------------------------------------------------------------- $ module load foo/1.2 $ foo foo, version 1.2
Software may sometimes provide a specific script for each shell they support as they do not perform their initialization the same way on every shell. Quite often a shell function is defined for sh shells whereas an alias is setup for csh shells (as such shells do not support shell function).
Dummy software bar is used to demonstrate this situation. bar is installed
in version 2.1 in example/source-script-in-modulefile/bar-2.1
directory
and it provides a bar-setup.sh
and a bar-setup.csh
scripts to activate
itself in user environment, depending on the shell kind used.
#!/bin/bash
PATH=$(dirname "${BASH_SOURCE[0]}")/bin:$PATH
export PATH
bar() {
barbin -q -l
}
#!/bin/tcsh
setenv PATH "example/source-script-in-modulefile/bar-2.1/bin:$PATH"
alias bar 'barbin -q -l'
To accurately initialize environment for bar software, the bar
module
needs to call the .sh
script if user is currently running a shell from the
sh family, or to call the .csh
script if user runs a csh-kind shell.
#%Module4.6
set scriptpath example/source-script-in-modulefile/bar-2.1
switch -- [module-info shelltype] {
sh {
source-sh bash $scriptpath/bar-setup.sh
}
csh {
source-sh tcsh $scriptpath/bar-setup.csh
}
}
This way the bar
shell function is initialized when loading module from a user
environment running a sh shell:
$ echo $BASH_VERSION 5.1.0(1)-release $ module use example/source-script-in-modulefile/modulefiles $ module show bar ------------------------------------------------------------------- .../modulefiles/bar/2.1: prepend-path PATH example/source-script-in-modulefile/bar-2.1/bin set-function bar { barbin -q -l} ------------------------------------------------------------------- $ module load bar $ type bar bar is a function bar () { barbin -q -l } $ bar bar, version 2.1
Whereas the bar
shell alias is setup on csh shell environment:
$ echo $version tcsh 6.22.03 (Astron) 2020-11-18 (x86_64-unknown-linux) ... $ module use example/source-script-in-modulefile/modulefiles $ module show bar ------------------------------------------------------------------- .../modulefiles/bar/2.1: prepend-path PATH example/source-script-in-modulefile/bar-2.1/bin set-alias bar {barbin -q -l} ------------------------------------------------------------------- $ module load bar $ alias bar barbin -q -l $ bar bar, version 2.1
Sticky modules¶
When providing a configurable environment to users, site's staff may require that some part of this environment remain loaded whatever the user does.
Such feature is for instance useful when every details of the user environment
are configured through the use of modulefiles. Even the core setup that is
usually configured through the /etc/profile.d
initialization scripts.
But by using modulefiles for core initialization, end users can fully see how
things are setup on their environment by using
module display
. When the environment core setup is achieved
by loading a specific modulefile, it is important that such module remains
loaded to keep this initial setup on whatever the module actions the user
performs over its environment.
This recipe describes how to keep modulefiles loaded by forbidding their unload. Such unloadable modules are called sticky modules.
Implementation¶
Sticky modules are simply modules that cannot be unloaded once loaded. Such behavior could be achieved by basically breaking the modulefile evaluation when attempting to unload the sticky module:
if {[module-info mode unload]} {
break
}
Using the break
Tcl command to stop the modulefile evaluation does not
require to install a recent version of Modules to get a basic sticky
mechanism.
To get a smoother sticky mechanism with two different level of stickiness, allowing to reload environment or to swap a sticky module by another version of the same module name, the sticky and super-sticky module tags have been introduced in Modules v4.7.
A modulefile is declared sticky by applying it the sticky
tag with the
module-tag
modulefile command. Such sticky module cannot be unloaded,
unless if the unload action is forced or if the module reloads after being
unloaded.
Modulefile can also be defined super-sticky
by applying the corresponding
module tag. Super-sticky module cannot be unloaded even if the unload action
is forced. It can only be unloaded if the module reloads afterward.
In case the stickiness applies to the generic module name (and does not target a specific module version or version-set), one version of the sticky or super-sticky module can be swapped by another version of this same module.
Compatible with Modules v4.7+
Usage examples¶
For this recipe, a core module acts as the initial setup of user's environment. This module must not be unloaded otherwise user's environment may be considered broken.
So this core module is tagged super-sticky with the module-tag
modulefile command in core/.modulerc
file:
module-tag super-sticky core
Once module got loaded, it cannot be unloaded even if these unload actions are forced.
$ module list Currently Loaded Modulefiles: 1) core/1.0 Key: super-sticky $ module unload core Unloading core/1.0 ERROR: Unload of super-sticky module 'core/1.0' skipped $ module purge -f Unloading core/1.0 ERROR: Unload of super-sticky module 'core/1.0' skipped $ module list Currently Loaded Modulefiles: 1) core/1.0 Key: super-sticky
However it is still possible to change version of this super-sticky module.
$ module switch core/2.0 $ module list Currently Loaded Modulefiles: 1) core/2.0 Key: super-sticky
In this recipe environment, the compiler module provides several flavors: compA and compB. Site's staff have decided that user's environment should always have a compiler module loaded by default.
So the compiler module is set sticky with the module-tag
modulefile command in compiler/.modulerc
file:
module-tag sticky compiler
As stickiness is defined over the generic compiler name, users can switch between available compiler flavors:
$ module list Currently Loaded Modulefiles: 1) core/2.0 2) compiler/compB/2.1 Key: super-sticky sticky $ module switch compiler/compA $ module list Currently Loaded Modulefiles: 1) core/2.0 2) compiler/compA/1.2 Key: super-sticky sticky
Unload attempt fails by default:
$ module unload compiler Unloading compiler/compA/1.2 ERROR: Unload of sticky module 'compiler/compA/1.2' skipped
However if a user really wants to get rid of the compiler module, the unload action can be forced:
$ module unload -f compiler Unloading compiler/compA/1.2 WARNING: Unload of sticky module 'compiler/compA/1.2' forced $ module list Currently Loaded Modulefiles: 1) core/2.0 Key: super-sticky
Last but not least, the sticky modules should get loaded when the user's shell
session initializes. So the core and compiler modules should be defined
for load in the initialization RC file /etc/environment-modules/initrc
:
#%Module
module use --append .../example/sticky-modules/modulefiles
module load core
module load compiler/compB
Testing Modulefiles¶
The following is an example for a ModulesTest
subroutine of a Modulefile and its output.
It checks whether the TESTDIR
is a directory, checks that it can enter it,
and whether a file TESTFILE
can successfully be created there.
This code gets executed when you use the module test modulefile
command.
Code¶
#%Module4.0 # -*- mode: tcl; -*-
proc ModulesTest { } {
set retcode 1 ;# default: 1 meaning PASS
puts stderr "Running ModulesTest for directory existence..."
if { [file isdirectory [getenv TESTDIR]] } {
puts stderr "Is a directory: [getenv TESTDIR]"
} else {
puts stderr "ERROR: Is not a directory: [getenv TESTDIR]"
set retcode 0
}
puts stderr "Running ModulesTest for directory existence...done"
puts stderr "Running ModulesTest for directory permissions..."
set cmd { cd [getenv TESTDIR] }
if { [catch $cmd errmsg] } {
puts stderr "ERROR: Was not able to enter directory [getenv TESTDIR]: ${errmsg}"
set retcode 0
} else {
puts stderr "Was able to enter directory [getenv TESTDIR]"
}
puts stderr "Running ModulesTest for directory permissions...done"
puts stderr "Running ModulesTest for file creation..."
set cmd { open [getenv TESTFILE] w }
if { [catch $cmd errmsg] } {
puts stderr "ERROR: Was not able to create file [getenv TESTFILE]: ${errmsg}"
set retcode 0
} else {
puts stderr "Was able to create file [getenv TESTFILE]"
}
puts stderr "Running ModulesTest for file creation...done"
return $retcode
}
setenv TESTDIR /tmp/[getenv USER]/testdir
setenv TESTFILE [getenv TESTDIR]/testfile
Usage example¶
Enable the modulepath where the example modulefiles are located:
$ module use example/test-modulefiles/modulefiles
Run the test both with the test directory not existing and existing:
$ module test test_dir_and_file
-------------------------------------------------------------------
Module Specific Test for .../modulefiles/test_dir_and_file:
Running ModulesTest for directory existence...
ERROR: Is not a directory: /tmp/testuser/testdir
Running ModulesTest for directory existence...done
Running ModulesTest for directory permissions...
ERROR: Was not able to enter directory /tmp/testuser/testdir: couldn't change working directory to "/tmp/testuser/testdir": no such file or directory
Running ModulesTest for directory permissions...done
Running ModulesTest for file creation...
ERROR: Was not able to create file /tmp/testuser/testdir/testfile: couldn't open "/tmp/testuser/testdir/testfile": no such file or directory
Running ModulesTest for file creation...done
Test result: FAIL
-------------------------------------------------------------------
$ mkdir /tmp/$USER/testdir
$ module test test_dir_and_file
-------------------------------------------------------------------
Module Specific Test for .../modulefiles/test_dir_and_file:
Running ModulesTest for directory existence...
Is a directory: /tmp/testuser/testdir
Running ModulesTest for directory existence...done
Running ModulesTest for directory permissions...
Was able to enter directory /tmp/testuser/testdir
Running ModulesTest for directory permissions...done
Running ModulesTest for file creation...
Was able to create file /tmp/testuser/testdir/testfile
Running ModulesTest for file creation...done
Test result: PASS
-------------------------------------------------------------------
Tips for Code Reuse in Modulefiles¶
Although Modules allow one to manage many packages and versions of packages on a system, managing the modulefiles themselves can become error prone, especially since the differences between modulefiles for different versions of the same package are often rather small. This can lead to issues with the consistency of the module definitions.
E.g., let us say you have a package foo, version 1.0 with a corresponding modulefile. A bit later, foo version 2.0 comes out, and you add a modulefile for that, likely copying the 1.0 version and editing a few lines. Then a bug is discovered in the version 1.0 modulefile, e.g. an environment variable that would be useful in some cases was omitted, or a typo in the help function. The version 1.0 modulefile is fixed, but did you remember to fix the 2.0 modulefile which, since it was created by copying the version 1.0 modulefile, likely has the same error?
This page includes some tips to reduce the amount of redundant code in your modulefiles (i.e. increase the amount of code reuse) so that they are easier to manage and more consistent.
A Simple Example¶
We return to our "foo" example. A fairly traditional set up would have a "foo" directory somewhere under your MODULEPATH with modulefiles 1.0 and 2.0 underneath it. Each of 1.0 and 2.0 will likely be largely the same, having basically the same help text, whatis, and variables set, with only some changes to some text and paths to reflect the version difference. Example code for this and other cases discussed in this document can be found in the "doc/example/tips-for-code-reuse" subdirectory of this package. The modulefiles for this simple example start in the "foo" subdirectory. For example, the version 1.0 modulefile might look something like
#%Module1.0
##
## foo
proc ModulesHelp { } {
puts stderr "
FooA: A simple example of modulefile code reuse
Version 1.0
blah, blah, blah
"
}
module-whatis "foo version 1.0"
conflict foo
prepend-path PATH /software/foo/1.0/bin
prepend-path MANPATH /software/foo/1.0/share/man
prepend-path LD_LIBRARY_PATH /software/foo/1.0/lib
Although the above is simple enough, there is still much redundancy between the version 1.0 and 2.0 files, and we do not bother showing the file for 2.0 because it is so similar (only 5 chars change between the 1.0 and 2.0 versions, basically all the "1.0" strings become "2.0"). The command "module avail foo" shows versions 1.0 and 2.0, and loading either will set the environmental variables PATH, MANPATH, and LD_LIBRARY_PATH appropriately, conflict with itself (so only one version of foo can be loaded at a time), and define the help and whatis texts.
To refactor this to increase code reuse, we copy one of the original modulefiles to "common", and change all the references to the version number to a "$version" variable. To avoid confusion with the previous version, we change the package name from "foo" to "fooA", and the new versions can be found in the "fooA" subdirectory of "doc/example/tips-for-code-reuse". After adding some comments, etc, the common module becomes
#Common modulefile for fooA
#Expects the following variables to have been set
# version: the version of fooA
proc ModulesHelp { } {
global version
puts stderr "
FooA: A simple example of modulefile code reuse
Version $version
This is a simple example of code reuse in modulefiles.
We have a couple versions of fooA, and the only differences
in what the modulefiles for the different fooA versions do
is that some paths include the version number.
"
}
module-whatis "fooA version $version"
conflict fooA
set rootdir /software/fooA/$version
prepend-path PATH $rootdir/bin
prepend-path MANPATH $rootdir/share/man
prepend-path LD_LIBRARY_PATH $rootdir/lib
We then create a pair of small stub files to replace "1.0" and "2.0". These simply just set the version variable appropriately, and then "source" the "common" file. For "1.0", the file would look like
#%Module1.0
set version 1.0
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/common
A similar file would be created for "2.0", just changing the version number in the "set version" line. The "set moduledir" line sets the Tcl variable moduledir to contain the name of the directory in which the final modulefile (i.e. "1.0") is located, so we can find the "common" file.
The common file then handles all the work of defining the PATH, MANPATH, and LD_LIBRARY_PATH environmental variables, using the value of the Tcl variable "version" passed to it by the stub file. It also handles defining the help procedure and the whatis text, and the conflict with itself.
Note that the "common" file does NOT start with the Modules magic "#%Module1.0"; this will keep "common" from showing up in "module avail fooA". The "1.0" and "2.0" files do need to start with the magic "#%Module1.0" tag so the module command will "see" them. Because of this, the "module avail fooA" command will just show the 1.0 and 2.0 versions as expected.
The files for this example are in the "doc/example/tips-for-code-reuse/fooA" directory.
A Simple Example, revisited¶
The "fooA" case above is fairly common, and we can actually improve upon what we did above. To avoid confusion, we will repeat using the package name "fooB", and the files for this example will be in the "doc/example/tips-for-code-reuse/fooB" directory.
Using introspection in the modulefiles, we can get the version number of fooB from the name of the modulefile. So we add code to the top of "common" to default the version variable from the modulename.
We then copy the "1.0" stub modulefile to ".generic", and remove the line which sets the version. Because is starts with a leading ".", the generic modulefile will not be displayed in "module avail" and such. Since this generic modulefile is now version independent, we can replace "1.0" and "2.0" with symlinks to the .generic file.
The new common file looks like
#Common modulefile for fooB
#Expects the following variables to have been set
# version: the version of fooB, defaults to last component of module tag
if [info exists version]==0 {
set version [file tail [module-info version [module-info name] ] ]
}
proc ModulesHelp { } {
global version
puts stderr "
FooB: A simple example of modulefile code reuse, revisited
Version $version
This our second visit to simple example of code reuse in modulefiles.
Because the all of the differences between the different fooB versions
modulefiles is contained in the version number, we replace the stub
modulefiles for the two versions with symlinks to a generic version
file, and infer the version from the tag given to the module command.
The generic modulefile, .generic, does not appear in 'module avail'
commands because of the leading period (.). Indeed, this generic modulefile
does is not even 'bar' specific, and typically we actually put the file
in an utilities directory outside the MODULEPATH and symlink to it from
multiple packages.
"
}
module-whatis "fooB version $version"
conflict fooB
set rootdir /software/fooB/$version
prepend-path PATH $rootdir/bin
prepend-path MANPATH $rootdir/share/man
prepend-path LD_LIBRARY_PATH $rootdir/lib
The .generic stub file looks like
#%Module######################
##
## generic modulefile,
##
## This just sources the file common in the same directory
##
## Usage:
## Just symlink this file to .generic in the directory with common, and
## then make symlink to .generic for all versions of the app
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/common
Again, the common file handles setting the environmental variables PATH, MANPATH, and LD_LIBRARY_PATH, using the Tcl variable version which was defaulted from modulename. This works even in the case where the user does not specify the full module path, and the modulecmd defaults the version (e.g. if the user types "module load fooB" without specifying the version of fooB.) The common file also handles defining the help procedure and whatis text. When the command "module avail fooB" is issued, the common file does not get listed (because it does not start with the magic "#%Module1.0" tag), nor does the .generic file get listed (because it starts with a period (".")), but the two 1.0 and 2.0 symlinks do get listed, just as one wants.
This replaces a file for each version of fooB with one common file doing all the work, one generic file, and a bunch of symlinks. And the .generic file is not even specific to fooB. Indeed, at our site, we put the generic modulefile in an "utilities" directory outside of the MODULEPATH, and just symlink it to ".generic" in each application directory, and then symlink the versions to this symlinked ".generic". So we end up with one "common" file for each application, one shared generic modulefile, and a bunch of symlinks.
A More Complicated Example¶
Although the simple cases like the "foo" example above are not uncommon, many packages are more complicated. We now consider the fictitious "bar" package (example modulefiles in "example/tips-for-code-reuse/bar" directory). This is admittedly a contrived example, but it displays some of the ways in which we can modify the above simple cases to handle the more complicated needs of some packages. Our "bar" package has the follow characteristics:
- We have two versions of "bar" built, "1.0" and "2.0"
- For each bar version, we have builds for three different threading models: nothreads, pthreads, and openmp.
- We expect users to use commands specifying both the bar version and the threading model, e.g. "module load fooB/1.0/pthreads" or "module load fooB/2.0/openmp"
- The path to the installation directories include both the version number of "bar" and the threading model
- The package requires the environmental variable BAR_LICENSE_FILE to be set appropriately
- All builds of bar version 1.0 use one license file which is different than that used by bar version2.0
- Bar 2.0 nothreads and openmp builds use the same license file, with a completely different name than that used by bar version 1.0.
- The bar 2.0 pthreads build uses its very own license file with a very different filename than those used by bar version 1.0 or the other threading models of version 2.0.
- The "nothreads" builds have a prerequisite on "fooB", with bar 1.0 wanting fooB version 1.1, and bar 2.0 wanting fooB version 3.2
Even with the above exceptions, there are still more similarities than differences between the various modulefile definitions. Like in the "fooA" case, we will have a "common" script that does almost all the work, and stub files for each of the variants, but in this case the stub files are expected to define some more variables. Our "common" file, which can be found in the "example/tips-for-code-reuse/bar" directory, looks like name "fooB", and the files for this example will be in the
#Common modulefile for bar
#Expects the following variables to have been set
# version: the version of bar,
# defaults to last component of module tag
# threadingmodel: one of 'nothreads', 'openmp' or 'pthreads'
# licensefile: or will default based on version
if [info exists version]==0 {
set version [file tail [module-info version [module-info name] ] ]
}
#Default to nothreads
if [info exists threadingmodel]==0 {
set threadingmodel nothreads
}
#Default licensefile based on version
if [info exists licensefile]==0 {
if [string equal $version 1.0] {
set licensefile /somepath/to/version1/licenseFile.lic
} else {
set licensefile /a/completely/different/licenseFile.lic
}
}
proc ModulesHelp { } {
global version threadingmodel licensefile
set threadstr $threadingmodel
if [ string equal $threadingmodel nothreads ] {
set threadstr {no threading support}
}
puts stderr "
Bar: Not so simple modulefile example
Version $version
Threading Model: $threadstr
This is a more complicated example of code reuse in modulefiles.
We have multiple versions of bar on the system, and each version
comes with multiple variants for different threading support modules.
Plus we assume that the env var BAR_LICENSE_FILE needs to be set
differently depending on the bar version.
Using license file: $licensefile
"
}
module-whatis "bar version $version with threading $threadingmodel"
conflict bar
set rootdir /software/bar/$version/$threadingmodel
prepend-path PATH $rootdir/bin
prepend-path MANPATH $rootdir/share/man
prepend-path LD_LIBRARY_PATH $rootdir/lib
setenv BAR_LICENSE_FILE $licensefile
Here we have extended the parameters which are allowed to be passed in from the build specific "stub" files; in addition to the version of "bar", the stub files are expected to have set the variables "threadingmodel" and optionally "licensefile". If "licensefile" was not set, the common script will default it based on the version of "bar". The rest of the "common" file is similar to the "fooA" case, except that we use both "version" and "threadingmodel" in setting the paths, and now define BAR_LICENSE_FILE based on "licensefile". Again, almost all the work is done in the common file, including setting the relevant environmental variables, defining the help procedure and whatis text, and preventing multiple versions of bar being loaded at the same time.
We now create stubfiles for each of the three threading models underneath directories for each bar version. These can all be found under the "example/tips-for-code-reuse/bar" directory. The one for bar 1.0 and openmp looks like
#%Module1.0
set version 1.0
set threadingmodel openmp
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/../common
The pthreads version is almost identical, just setting threadingmodel to "pthreads" instead of "openmp". The "openmp" build for bar version 2.0 is also very similar, differing only in value "version" is set to. In all three cases, these stubfiles are basically the same as those used in the "fooA" example; we set a couple of Tcl variables (version and threadingmodel), and then source the common file which does all the work. The licensefile variable is left unset so the common file will default it correctly based on the bar version.
The stub file for the pthreads build for bar version 2.0 is as below:
#%Module1.0
set version 2.0
set threadingmodel pthreads
set licensefile /special/license/file/for/bar/2.0/with/pthreads/license.lic
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/../common
This version is similar to the previous three, with the addition of explicitly setting the "licensefile" variable. This value will be used in the common file to set BAR_LICENSE_FILE, rather than the default which would have been set in the common file had no value been provided.
Finally, the two "nothreads" build also have a slightly different stub file than the other builds. The one for bar version 2.0 is shown below:
#%Module1.0
set version 2.0
set threadingmodel nothreads
prereq fooB/3.2
set moduledir [file dirname $ModulesCurrentModulefile]
source $moduledir/../common
Here we add a "prereq fooB/3.2" to require that the correct version of fooB was loaded. The bar version 1.0 stubfile is almost the same, just changing the setting of the version variable from 2.0 to 1.0, and changing the version of fooB needed as a prerequisite.
So instead of having six somewhat lengthy modulefiles (~40 lines each), one for each combination of bar version and threading model, we put almost all the work into a single, slightly longer (55 lines) common file, with six small (8 lines or less) stub files which mostly just set variables to define the behavior of the common file.
When customization is needed for a specific build, we showed two ways of accommodating such. First, for simple, more-or-less "one-off" cases, you can add some code to the appropriate "stubfiles" to handle the added complexity, like was done with the "prereq fooB" for the "nothreads" builds in the examples.
Alternatively, one can add some additional logic to the common script to accommodate the complexity, like was done with the license file differences between builds. This is the recommended way to handle complexity which is likely to recur in multiple places. Generally, this is done by:
- adding a parameter to be passed from the stub file to the common file and setting appropriately in the stub files (e.g. licensefile in bar/2.0/pthreads)
- adding logic to the common file to default it appropriately (e.g. licensefile for the other builds)
The above was only a simple example of what could be done, but it shows how modulefiles can leverage the fact that the modulefiles are evaluated in a full programming language to increase the amount of code re-use, which should reduce errors, improve consistency, and in general make things more manageable over the long run.
The tips given above should work with both 3.x and 4.x versions of the Tcl based environmental packages. They have been explicitly tested on versions 3.2.10 and 4.3.0.
Top priority environment variable values¶
Multiple modulefiles may alter the same environment variable. It may be wanted that among those modulefiles one should have the priority over the others and the value it sets should persist even if another modulefile loaded after attempts to alter the variable.
When using the setenv
modulefile command, a top priority value
should persist over later setenv tries. On append-path
modulefile
command, this top priority value should stay last position and for
prepend-path
modulefile command, value should stay first position.
Implementation¶
Top priority values are implemented by the use of a site-specific
configuration that supersedes the definition of the setenv
,
append-path
and prepend-path
commands to introduce a --top
argument. This argument enables a value set with this flag on to hold top
priority and thus cannot be altered unless by another top priority value.
For append-path
command, --top
ensure value will stay at last position
in path-like variable. Same goes for prepend-path
where --top
ensure
first position in path-like variable.
# override 'setenv' procedure to add a '--top' optional argument
rename ::setenv ::__setenv
proc setenv {args} {
set arglist [lsearch -all -inline -not -exact $args "--top"]
lassign [parseSetenvCommandArgs load set {*}$arglist] bhv var val
# top priority asked
if {[llength $arglist] != [llength $args]} {
# define an helper variable to know a top-priority value has been set
if {[currentState mode] ne "display"} {
__setenv MODULES_PRIORITY_$var $val
}
__setenv {*}$arglist
# set non-priority value only if no top priority value already set
} elseif {![info exists ::env(MODULES_PRIORITY_$var)]} {
__setenv {*}$arglist
}
}
# override 'setenv-un' procedure to interpret the '--top' optional argument
# when setenv is evaluated on an unload mode
rename ::setenv-un ::__setenv-un
proc setenv-un {args} {
set arglist [lsearch -all -inline -not -exact $args "--top"]
lassign [parseSetenvCommandArgs unload unset {*}$arglist] bhv var val
# top priority asked
if {[llength $arglist] != [llength $args]} {
# define an helper variable to know a top-priority value has been set
if {[currentState mode] ne "display"} {
__setenv-un MODULES_PRIORITY_$var $val
}
__setenv-un {*}$arglist
# set non-priority value only if no top priority value already set
} elseif {![info exists ::env(MODULES_PRIORITY_$var)]} {
__setenv-un {*}$arglist
}
}
# override 'setenv-wh' procedure to interpret the '--top' optional argument
# when setenv is evaluated on an whatis mode
rename ::setenv-wh ::__setenv-wh
proc setenv-wh {args} {
set arglist [lsearch -all -inline -not -exact $args "--top"]
__setenv-wh {*}$arglist
}
# override 'add-path' procedure to add a '--top' optional argument, which
# will benefit to the 'append-path' and 'prepend-path' modulefile commands
rename ::add-path ::__add-path
proc add-path {cmd mode dflbhv args} {
set keep_top_priority 0
set pos [expr {$cmd eq {append-path} ? {append} : {prepend}}]
set arglist [lsearch -all -inline -not -exact $args "--top"]
lassign [parsePathCommandArgs $cmd $mode $dflbhv {*}$arglist] separator\
allow_dup idx_val ign_refcount bhv var path_list
# top priority asked
if {[llength $arglist] != [llength $args]} {
# record this top priority value in an helper variable
__setenv MODULES_PRIORITY_${pos}_$var $path_list
} elseif {[info exists ::env(MODULES_PRIORITY_${pos}_$var)]} {
set keep_top_priority 1
}
# ensure top-priority value keeps first or last position by unloading it
# priority new value addition, then restoring it
if {$keep_top_priority} {
eval __unload-path $cmd load remove $var\
$::env(MODULES_PRIORITY_${pos}_$var)
}
__add-path $cmd $mode $dflbhv {*}$arglist
if {$keep_top_priority} {
eval __add-path $cmd $mode $dflbhv $var\
$::env(MODULES_PRIORITY_${pos}_$var)
}
}
rename ::unload-path ::__unload-path
proc unload-path {cmd mode dflbhv args} {
set arglist [lsearch -all -inline -not -exact $args "--top"]
lassign [parsePathCommandArgs $cmd $mode $dflbhv {*}$arglist] separator\
allow_dup idx_val ign_refcount bhv var path_list
if {[llength $arglist] != [llength $args]} {
# wipe priority helper variable when unloading top priority value
switch -- $cmd {
{append-path} { set pos append }
{prepend-path} { set pos prepend }
}
if {[info exists pos]} {
__setenv MODULES_PRIORITY_${pos}_$var $path_list
}
}
__unload-path $cmd $mode $dflbhv {*}$arglist
}
Compatible with Modules v4.2+
Installation¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/top-priority-values/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the value of the siteconfig
option on Modules
version 4.3 or above:
$ module config siteconfig
On older version of Modules, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
Usage example¶
With a bar/1
modulefile that sets environment variables in a regular way:
#%Module
# define a regular value for variable
setenv TESTVAR value
# prepend a regular value to a path-like variable
prepend-path TESTPATH prevalue
# append a regular value to a path-like variable
append-path TESTPATH postvalue
And a foo/1
modulefile that sets the same variables than bar/1
but
with the --top
priority flag:
#%Module
# define a value for variable holding top priority (not overwritten by non-top priority value)
setenv --top TESTVAR topvalue
# prepend a value to a path-like variable, value that stays first position
prepend-path --top TESTPATH topprevalue
# append a value to a path-like variable, value that stays last position
append-path --top TESTPATH toppostvalue
Enable the modulepath where the example modulefiles are located:
$ module use example/top-priority-values/modulefiles
Load foo/1
then bar/1
modulefiles and check value of the environment
variable set:
$ module load foo/1 bar/1
$ echo $TESTVAR
topvalue
$ echo $TESTPATH
topprevalue:prevalue:postvalue:toppostvalue
Unload firstly loaded module matching name¶
Since Modules v4, unloading a given module name unloads lastly loaded module matching this given name. On Modules v3 the module selected for the unload was the firstly loaded not the lastly loaded. This recipe gives a way to restore the behavior of the v3 version.
Implementation¶
Starting version v4.3, an unload_match_order
configuration option
is introduced to control whether firstly loaded module or lastly loaded module
should be selected for the unload. To select firstly loaded module:
$ module config unload_match_order returnfirst
For older v4 versions, a site-specific configuration script is proposed to select firstly loaded module matching name rather lastly loaded.
# override 'getLoadedMatchingName' procedure to set behavior argument to the
# 'returnfirst' value by default
rename ::getLoadedMatchingName ::__getLoadedMatchingName
proc getLoadedMatchingName {name {behavior returnfirst} {loading 0}} {
return [__getLoadedMatchingName $name $behavior $loading]
}
Compatible with Modules v4.2
Installation (only for version older than v4.3)¶
Create site-specific configuration directory if it does not exist yet:
$ mkdir /etc/environment-modules
Then copy there the site-specific configuration script of this recipe:
$ cp example/unload-firstly-loaded/siteconfig.tcl /etc/environment-modules/
Note
Defined location for the site-specific configuration script may vary from
one installation to another. To determine the expected location for this
file on your setup, check the modulecmd.tcl
script:
$ grep '^set g_siteconfig ' $MODULES_CMD
Usage example¶
With a bare foo/1
modulefile:
#%Module
And a bare foo/2
modulefile:
#%Module
Enable the modulepath where the example modulefiles are located:
$ module use example/unload-firstly-loaded/modulefiles
Load both foo
modulefiles then attempt to unload foo
name:
$ module load foo/1 foo/2
$ module list
Currently Loaded Modulefiles:
1) foo/1 2) foo/2
$ module unload foo
$ module list
Currently Loaded Modulefiles:
1) foo/2
ml¶
DESCRIPTION¶
ml is a user interface to the Modules package. The Modules package provides for the dynamic modification of the user's environment via modulefiles.
ml acts as a shortcut command to the module command thus it supports all the command line switches and module sub-commands that are supported by module.
ml also provides handy shortcuts to list currently loaded
modulefiles, when no argument is provided to ml; to load
modulefiles, when modulefile names are passed right after ml
command name; to unload modulefiles, when modulefile names prefixed by a minus
sign (-
) are passed right after ml command name.
Multiple modulefiles to load and to unload can be specified on a single ml command line. In this situation unloads are treated first in specified order, then loads are processed also in specified order (see EXAMPLES section below). If an error occurs among either modulefile loads or unloads, command line processing is stopped and every unloads and loads performed are rolled back.
ml command line is parsed first to match every known command line switches or module sub-commands. So to load a modulefile via the ml shortcut syntax, modulefile name should not equal a module sub-command name. Moreover to unload a modulefile via the ml shortcut syntax, modulefile name should not equal a command line switch short name.
See the DESCRIPTION section in module for the list of supported command line switches and module sub-commands.
EXAMPLES¶
Loading modulefile foo
then look at currently loaded modulefiles:
$ ml foo
$ ml
Currently Loaded Modulefiles:
1) foo
Unloading modulefile foo
then list modulefiles still loaded:
$ ml -foo
$ ml
No Modulefiles Currently Loaded.
Mixing load and unload of modulefiles in a single command. All specified unloads are processed first then loads are performed:
$ ml -v -foo bar -baz qux
Unloading foo
Unloading baz
Loading bar
Loading qux
EXIT STATUS¶
The ml command exits with 0 if its execution succeed. Elsewhere
1
is returned.
ENVIRONMENT¶
See the ENVIRONMENT section in module for the list of supported environment variables.
SEE ALSO¶
module¶
SYNOPSIS¶
module [switches] [sub-command [sub-command-args]]
DESCRIPTION¶
module is a user interface to the Modules package. The Modules package provides for the dynamic modification of the user's environment via modulefiles.
Each modulefile contains the information needed to configure the
shell for an application. Once the Modules package is initialized, the
environment can be modified on a per-module basis using the module
command which interprets modulefiles. Typically modulefiles instruct
the module command to alter or set shell environment variables such
as PATH
, MANPATH
, etc. Modulefiles may be shared by many
users on a system and users may have their own set to supplement or replace
the shared modulefiles.
The modulefiles are added to and removed from the current environment by the user. The environment changes contained in a modulefile can be summarized through the module command as well. If no arguments are given, a summary of the module usage and sub-commands are shown.
The action for the module command to take is described by the sub-command and its associated arguments.
Package Initialization¶
The Modules package and the module command are initialized when a
shell-specific initialization script is sourced into the shell. The script
executes the autoinit
sub-command of the modulecmd.tcl
program located in /usr/share/Modules/libexec
for the corresponding shell. The output
of this execution is evaluated by shell which creates the module
command as either an alias or function and creates Modules environment
variables.
During this initialization process, if the Modules environment is found
undefined (when both MODULEPATH
and LOADEDMODULES
are
found either unset or empty), the modulespath
and initrc
configuration files located in /etc/environment-modules
are evaluated if present and
following this order. modulespath
file contains the list of
modulepaths to enable during initialization. In this file, the modulepaths are
separated by newline or colon characters. initrc
is a modulefile that
defines during initialization the modulepaths to enable, the modules to load
and the module configuration to apply.
During the initialization process, if the Modules environment is found defined
a module refresh
is automatically applied to restore in the
current environment all non-persistent components set by loaded modules.
The module alias or function executes the modulecmd.tcl
program and has the shell evaluate the command's output. The first argument to
modulecmd.tcl
specifies the type of shell.
The initialization scripts are kept in /usr/share/Modules/init/<shell>
where
<shell> is the name of the sourcing shell. For example, a C Shell user
sources the /usr/share/Modules/init/csh
script. The sh, csh, tcsh, bash, ksh,
zsh, fish and cmd shells are supported by modulecmd.tcl
. In addition,
python, perl, ruby, tcl, cmake, r and lisp "shells" are supported which
writes the environment changes to stdout as python, perl, ruby, tcl, lisp,
r or cmake code.
Initialization may also be performed by directly calling the
autoinit
sub-command of the modulecmd.tcl
program.
A ml alias or function may also be defined at initialization time
if enabled (see MODULES_ML
section). ml is a handy
frontend leveraging all module command capabilities with less
character typed. See ml for detailed information.
Examples of initialization¶
C Shell initialization (and derivatives):
source /usr/share/Modules/init/csh module load modulefile modulefile ...
Bourne Shell (sh) (and derivatives):
. /usr/share/Modules/init/sh module load modulefile modulefile ...
Perl:
require "/usr/share/Modules/init/perl.pm"; &module('load', 'modulefile', 'modulefile', '...');
Python:
import os exec(open("/usr/share/Modules/init/python.py").read(), globals()) module("load", "modulefile", "modulefile", "...")
Bourne Shell (sh) (and derivatives) with autoinit
sub-command:
eval "$(/usr/share/Modules/libexec/modulecmd.tcl sh autoinit)"
Modulecmd startup¶
Upon invocation modulecmd.tcl
sources a site-specific configuration
script if it exists. Siteconfig script is a Tcl script located at
/etc/environment-modules/siteconfig.tcl
. It enables to supersede any global variable or
procedure definition of modulecmd.tcl
. See Site-specific configuration for detailed information.
Afterward, modulecmd.tcl
sources rc files which contain global,
user and modulefile specific setups. These files are interpreted as
modulefiles. See modulefile for detailed information.
Upon invocation of modulecmd.tcl
module run-command files are sourced
in the following order:
- Global RC file as specified by
MODULERCFILE
variable or/etc/environment-modules/rc
. IfMODULERCFILE
points to a directory, themodulerc
file in this directory is used as global RC file. - User specific module RC file
$HOME/.modulerc
- All
.modulerc
and.version
files found during modulefile seeking.
These module run-command files must begins like modulefiles with the
#%Module
file signature, also called the Modules magic cookie. A version
number may be placed after this string. The version number reflects the
minimum version of modulecmd.tcl
required to interpret the run-command
file. If a version number doesn't exist, then modulecmd.tcl
will
assume the run-command file is compatible. Files without the magic cookie or
with a version number greater than the current version of
modulecmd.tcl
will not be interpreted and an error is reported. Such
error does not abort the whole module evaluation. If the
mcookie_version_check
configuration is disabled the version number
set is not checked.
Note
Run-command files are intended to set parameters for modulefiles, not to configure the module command itself.
Command line switches¶
The module command accepts command line switches as its first parameter. These may be used to control output format of all information displayed and the module behavior in case of locating and interpreting modulefiles.
All switches may be entered either in short or long notation. The following switches are accepted:
-
--all
,
-a
¶
Include hidden modules in search performed with
avail
,aliases
,list
,lint
,savelist
,search
orwhatis
sub-commands. Hard-hidden modules are not affected by this option.New in version 4.6.
Changed in version 4.7: Support for
list
sub-command added
-
--auto
¶
Enable automated module handling mode on sub-commands that load or unload modulefiles. See also
MODULES_AUTO_HANDLING
section.New in version 4.2.
-
--color
=<WHEN>
¶ Colorize the output. WHEN defaults to
always
or can benever
orauto
. See alsoMODULES_COLOR
section.New in version 4.3.
-
--contains
,
-C
¶
On
avail
,list
andsavelist
sub-commands, return modules or collections whose fully qualified name contains search query string.New in version 4.3.
Changed in version 5.1: Support for
list
sub-command addedChanged in version 5.2: Support for
savelist
sub-command added
-
--debug
,
-D
,
-DD
¶
Debug mode. Causes module to print debugging messages about its progress. Multiple
-D
options increase the debug verbosity. The maximum is 2.New in version 4.0.
Changed in version 4.6: Option form
-DD
added
-
--default
,
-d
¶
On
avail
sub-command, display only the default version of each module name. Default version is the explicitly set default version or also the implicit default version if the configuration optionimplicit_default
is enabled (see Locating Modulefiles section in the modulefile man page for further details on implicit default version).New in version 4.0.
-
--force
,
-f
¶
On
load
,unload
,switch
,load-any
,try-load
,mod-to-sh
andsource
sub-commands by-pass any unsatisfied modulefile constraint corresponding to the declaredprereq
andconflict
. Which means for instance that a modulefile will be loaded even if it comes in conflict with another loaded modulefile or that a modulefile will be unloaded even if it is required as a prereq by another modulefile.On
clear
sub-command, skip the confirmation dialog and proceed.On
purge
sub-command also unload sticky modules and modulefiles that are depended by non-unloadable modules.New in version 4.3:
--force
/-f
support was dropped on version 4.0 but reintroduced starting version 4.2 with a different meaning: instead of enabling an active dependency resolution mechanism--force
command line switch now enables to by-pass dependency consistency when loading or unloading a modulefile.Changed in version 4.7: Support for
purge
sub-command addedChanged in version 4.8: Support for
try-load
sub-command addedChanged in version 5.1: Support for
load-any
sub-command addedChanged in version 5.2: Support for
mod-to-sh
sub-command added
-
--help
,
-h
¶
Give some helpful usage information, and terminates the command.
-
--icase
,
-i
¶
Match module specification arguments in a case insensitive manner.
-
--ignore-cache
¶
Ignore module cache.
New in version 5.3.
-
--ignore-user-rc
¶
Skip evaluation of user-specific module rc file (
$HOME/.modulerc
).New in version 5.3.
-
--indepth
¶
On
avail
sub-command, include in search results the matching modulefiles and directories and recursively the modulefiles and directories contained in these matching directories.New in version 4.3.
-
--json
,
-j
¶
Display
avail
,list
,savelist
,stashlist
,whatis
andsearch
output in JSON format.New in version 4.5.
-
--latest
,
-L
¶
On
avail
sub-command, display only the highest numerically sorted version of each module name (see Locating Modulefiles section in the modulefile man page).New in version 4.0.
-
--no-auto
¶
Disable automated module handling mode on sub-commands that load or unload modulefiles. See also
MODULES_AUTO_HANDLING
section.New in version 4.2.
-
--no-indepth
¶
On
avail
sub-command, limit search results to the matching modulefiles and directories found at the depth level expressed by the search query. Thus modulefiles contained in directories part of the result are excluded.New in version 4.3.
-
--no-pager
¶
Do not pipe message output into a pager.
New in version 4.1.
-
--no-redirect
¶
Do not send message output to stdout. Keep it on stderr.
New in version 5.1.
-
--output
=LIST
,
-o
LIST
¶ Define the content to report in addition to module names. This option is supported by
avail
andlist
sub-commands on their regular or terse output modes. Accepted values are a LIST of elements to report separated by colon character (:
). The order of the elements in LIST does not matter.Accepted elements in LIST for
avail
sub-command are: modulepath, alias, dirwsym, sym, tag, key, variant and variantifspec.Accepted elements in LIST for
list
sub-command are: header, idx, variant, sym, tag and key.The order of the elements in LIST does not matter. Module names are the only content reported when LIST is set to an empty value.
LIST may be prefixed by
+
or-
character to indicate respectively to append it to or subtract it from current configuration option value.See also
MODULES_AVAIL_OUTPUT
andMODULES_LIST_OUTPUT
.New in version 4.7.
Changed in version 4.8: Element variant added for
list
sub-commandChanged in version 5.3: Elements variant and variantifspec added for
avail
sub-commandChanged in version 5.3: Prefixes
+
and-
added to append and subtract elements
-
--paginate
¶
Pipe all message output into less (or if set, to the command referred in
MODULES_PAGER
variable) if error output stream is a terminal. See alsoMODULES_PAGER
section.New in version 4.1.
-
--redirect
¶
Send message output to stdout instead of stderr. Only supported on sh, bash, ksh, zsh and fish shells.
New in version 5.1.
-
--silent
,
-s
¶
Turn off error, warning and informational messages. module command output result is not affected by silent mode.
-
--starts-with
,
-S
¶
On
avail
,list
andsavelist
sub-commands, return modules or collections whose name starts with search query string.New in version 4.3.
Changed in version 5.1: Support for
list
sub-command addedChanged in version 5.2: Support for
savelist
sub-command added
-
--tag
=LIST
¶ On
load
,load-any
,switch
andtry-load
sub-commands, apply LIST of module tags to the loading modulefile. LIST corresponds to the concatenation of multiple tags separated by colon character (:
). LIST should not contain tags inherited from modulefile state or from other modulefile commands. If module is already loaded, tags from LIST are added to the list of tags already applied to this module.New in version 5.1.
-
--timer
¶
Prints at the end of the output an evaluation of the total execution time of the module command. When mixed with a single or multiple
--debug
options, replaces regular debug messages by reports of the execution time of every internal procedure calls.New in version 5.2.
-
--trace
,
-T
¶
Trace mode. Report details on module searches, resolutions, selections and evaluations in addition to printing verbose messages.
New in version 4.6.
-
--verbose
,
-v
,
-vv
¶
Enable verbose messages during module command execution. Multiple
-v
options increase the verbosity level. The maximum is 2.New in version 4.3:
--verbose
/-v
support was dropped on version 4.0 but reintroduced starting version 4.3.Changed in version 4.7: Option form
-vv
added
-
--version
,
-V
¶
Lists the current version of the module command. The command then terminates without further processing.
-
--width
=COLS
,
-w
COLS
¶ Set the width of the output to COLS columns. See also
MODULES_TERM_WIDTH
section.New in version 4.7.
Module Sub-Commands¶
-
aliases
[-a]
¶ List all available symbolic version-names and aliases in the current
MODULEPATH
. All directories in theMODULEPATH
are recursively searched in the same manner than for theavail
sub-command. Only the symbolic version-names and aliases found in the search are displayed.New in version 4.0.
-
append-path
[-d C|--delim C|--delim=C] [--duplicates] variable value...
¶ Append value to environment variable. The variable is a colon, or delimiter, separated list. See
append-path
in the modulefile man page for further explanation.When
append-path
is called as a module sub-command, the reference counter variable, which denotes the number of times value has been added to environment variable, is not updated unless if the--duplicates
option is set.New in version 4.1.
Changed in version 5.0: Reference counter environment variable is not updated anymore unless if the
--duplicates
option is set
-
avail
[-d|-L] [-t|-l|-j] [-a] [-o LIST] [-S|-C] [--indepth|--no-indepth] [pattern...]
¶ List all available modulefiles in the current
MODULEPATH
. All directories in theMODULEPATH
are recursively searched for files containing the Modules magic cookie. If a pattern argument is given, then each directory in theMODULEPATH
is searched for modulefiles whose pathname, symbolic version-name or alias match pattern in a case insensitive manner by default. pattern may contain wildcard characters. Multiple versions of an application can be supported by creating a subdirectory for the application containing modulefiles for each version.Symbolic version-names and aliases found in the search are displayed in the result of this sub-command. Symbolic version-names are displayed next to the modulefile they are assigned to within parenthesis. Aliases are listed in the
MODULEPATH
section where they have been defined. To distinguish aliases from modulefiles a@
symbol is added within parenthesis next to their name. Aliases defined through a global or user specific module RC file are listed under the global/user modulerc section.When colored output is enabled and a specific graphical rendition is defined for module default version, the
default
symbol is omitted and instead the defined graphical rendition is applied to the relative modulefile. When colored output is enabled and a specific graphical rendition is defined for module alias, the@
symbol is omitted. The defined graphical rendition applies to the module alias name. SeeMODULES_COLOR
andMODULES_COLORS
sections for details on colored output.Module tags applying to the available modulefiles returned by the
avail
sub-command are reported along the module name they are associated to (see Module tags section).Module variants and their available values may be reported along the module name they belong to (see Module variants section) if defined in avail output configuration option (see
--output
/-o
option). The Extra match search process is triggered to collect variant information.A Key section is added at the end of the output in case some elements are reported in parentheses or chevrons along module name or if some graphical rendition is made over some output elements. This Key section gives hints on the meaning of such elements.
The parameter pattern may also refer to a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If pattern contains variant specification or Extra specifier, the Extra match search process is triggered to collect command information used in modulefiles. Modules are included in results only if they match pattern variant specification and extra specifier. pattern may be a bare variant specification or extra specifier without mention of a module name.
Changed in version 4.3: Options
--starts-with
/-S
,--contains
/-C
,--indepth
,--no-indepth
addedChanged in version 4.7: Key section added at end of output
Changed in version 5.3: Module variants may be reported if defined in avail output configuration
Changed in version 5.3: pattern may include variant specification or extra specifier to filter results
-
cachebuild
[modulepath...]
¶ Build module cache file for designated modulepaths. If no argument is provided cache file is built for every modulepath currently enabled. Cache file creation is skipped for modulepaths where user cannot write in.
The name and content of every readable modulefiles and rc files are recorded into cache file. Also last modification time of modulefiles and invalid modulefile error messages are recorded. With all these information, the sole cache file is evaluated to know what is available within modulepath.
See Module cache section for more details on module cache mechanism.
New in version 5.3.
-
cacheclear
¶ Delete module cache file in every modulepath currently enabled. If user cannot write in a modulepath directory, cache file deletion is skipped for this modulepath.
See Module cache section for more details on module cache mechanism.
New in version 5.3.
-
clear
[-f]
¶ Force the Modules package to believe that no modules are currently loaded. A confirmation is requested if command-line switch
-f
(or--force
) is not passed. Typed confirmation should equal toyes
ory
in order to proceed.New in version 4.3:
clear
support was dropped on version 4.0 but reintroduced starting version 4.3.
-
config
[--dump-state|name [value]|--reset name]
¶ Gets or sets
modulecmd.tcl
options. Reports the currently set value of passed option name or all existing options if no name passed. If a name and a value are provided, the value of option name is set to value. If command-line switch--reset
is passed in addition to a name, overridden value for option name is cleared.When a reported option value differs from default value a mention is added to indicate whether the overridden value is coming from a command-line switch (
cmd-line
) or from an environment variable (env-var
). When a reported option value is locked and cannot be altered a (locked
) mention is added.If no value is currently set for an option name, the mention
<undef>
is reported.For options whose value is a colon-separated list, value may be prefixed by
+
or-
character. It indicates respectively to append it to or subtract it from current option value.When command-line switch
--dump-state
is passed, currentmodulecmd.tcl
state and Modules-related environment variables are reported in addition to currently setmodulecmd.tcl
options.Existing option names are:
-
advanced_version_spec
¶ Advanced module version specification to finely select modulefiles.
Default value is
1
. It can be changed at installation time with--disable-advanced-version-spec
option. TheMODULES_ADVANCED_VERSION_SPEC
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_ADVANCED_VERSION_SPEC
description for details.New in version 4.4.
-
auto_handling
¶ Automated module handling mode.
Default value is
1
. It can be changed at installation time with--disable-auto-handling
option. TheMODULES_AUTO_HANDLING
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--auto
and--no-auto
command line switches change the value of this configuration option. SeeMODULES_AUTO_HANDLING
description for details.
-
avail_indepth
¶ avail
sub-command in depth search mode.Default value is
1
. It can be changed at installation time with--disable-avail-indepth
option. TheMODULES_AVAIL_INDEPTH
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--indepth
and--no-indepth
command line switches change the value of this configuration option. SeeMODULES_AVAIL_INDEPTH
description for details.
-
avail_output
¶ Content to report in addition to module names on
avail
sub-command regular output mode.Default value is
modulepath:alias:dirwsym:sym:tag:key
. It can be changed at installation time with--with-avail-output
option. TheMODULES_AVAIL_OUTPUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--output
/-o
command line switches change the value of this configuration option. SeeMODULES_AVAIL_OUTPUT
description for details.New in version 4.7.
-
avail_terse_output
¶ Content to report in addition to module names on
avail
sub-command terse output mode.Default value is
modulepath:alias:dirwsym:sym:tag
. It can be changed at installation time with--with-avail-terse-output
option. TheMODULES_AVAIL_TERSE_OUTPUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--output
/-o
command line switches change the value of this configuration option. SeeMODULES_AVAIL_TERSE_OUTPUT
description for details.New in version 4.7.
-
cache_buffer_bytes
¶ Size of the buffer used when reading or writing cache files.
Default value is
32768
. Values between 4096 and 1000000 are accepted. TheMODULES_CACHE_BUFFER_BYTES
environment variable is defined byconfig
sub-command when changing this configuration option from its default value.New in version 5.3.
-
cache_expiry_secs
¶ Number of seconds a cache file is considered valid after being generated.
Default value is
0
. Values between 0 and 31536000 are accepted. TheMODULES_CACHE_EXPIRY_SECS
environment variable is defined byconfig
sub-command when changing this configuration option from its default value.New in version 5.3.
-
collection_pin_version
¶ Register exact modulefile version in collection.
Default value is
0
. TheMODULES_COLLECTION_PIN_VERSION
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_COLLECTION_PIN_VERSION
description for details.
-
collection_pin_tag
¶ Register full tag list applying to modulefiles in collection.
Default value is
0
. TheMODULES_COLLECTION_PIN_TAG
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_COLLECTION_PIN_TAG
description for details.New in version 5.1.
-
collection_target
¶ Collection target which is valid for current system.
This configuration option is unset by default. The
MODULES_COLLECTION_TARGET
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_COLLECTION_TARGET
description for details.
-
color
¶ Colored output mode.
Default value is
auto
. It can be changed at installation time with--disable-color
option. TheMODULES_COLOR
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--color
command line switches changes the value of this configuration option. SeeMODULES_COLOR
description for details.
-
colors
¶ Chosen colors to highlight output items.
Default value is
hi=1:db=2:tr=2:se=2:er=91:wa=93:me=95:in=94:mp=1;94:di=94:al=96:va=93:sy=95:de=4:cm=92:aL=100:L=90;47:H=2:F=41:nF=43:S=46:sS=44:kL=30;48;5;109
. It can be changed at installation time with--with-dark-background-colors
or--with-light-background-colors
options in conjunction with--with-terminal-background
. TheMODULES_COLORS
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_COLORS
description for details.
-
contact
¶ Modulefile contact address.
Default value is
root@localhost
. TheMODULECONTACT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULECONTACT
description for details.
-
extended_default
¶ Allow partial module version specification.
Default value is
1
. It can be changed at installation time with--disable-extended-default
option. TheMODULES_EXTENDED_DEFAULT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_EXTENDED_DEFAULT
description for details.New in version 4.4.
-
editor
¶ Text editor command to open modulefile with through
edit
sub-command.Default value is
vi
. It can be changed at installation time with--with-editor
option. TheMODULES_EDITOR
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_EDITOR
description for details.New in version 4.8.
-
extra_siteconfig
¶ Additional site-specific configuration script location. See Site-specific configuration section for details.
This configuration option is unset by default. The
MODULES_SITECONFIG
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_SITECONFIG
description for details.
-
home
¶ Location of Modules package main directory.
Default value is
/usr/share/Modules
. It can be changed at installation time with--prefix
or--with-moduleshome
options. TheMODULESHOME
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULESHOME
description for details.New in version 4.4.
-
icase
¶ Enable case insensitive match.
Default value is
search
. It can be changed at installation time with--with-icase
option. TheMODULES_ICASE
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--icase
/-i
command line switches change the value of this configuration option. SeeMODULES_ICASE
description for details.New in version 4.4.
-
ignore_cache
¶ Ignore module cache.
Default is
0
. TheMODULES_IGNORE_CACHE
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--ignore-cache
command line switch changes the value of this configuration option.New in version 5.3.
-
ignore_user_rc
¶ Skip evaluation of user-specific module rc file (
$HOME/.modulerc
).Default is
0
. TheMODULES_IGNORE_USER_RC
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--ignore-user-rc
command line switch changes the value of this configuration option.New in version 5.3.
-
ignored_dirs
¶ Directories ignored when looking for modulefiles.
Default value is
CVS RCS SCCS .svn .git .SYNC .sos
. The value of this option cannot be altered.
-
implicit_default
¶ Set an implicit default version for modules.
Default value is
1
. It can be changed at installation time with--disable-implicit-default
option. TheMODULES_IMPLICIT_DEFAULT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_IMPLICIT_DEFAULT
description for details.
-
implicit_requirement
¶ Implicitly define a requirement onto modules specified on
module
commands in modulefile.Default value is
1
. It can be changed at installation time with--disable-implicit-requirement
option. TheMODULES_IMPLICIT_REQUIREMENT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_IMPLICIT_REQUIREMENT
description for details.New in version 4.7.
-
list_output
¶ Content to report in addition to module names on
list
sub-command regular output mode.Default value is
header:idx:variant:sym:tag:key
. It can be changed at installation time with--with-list-output
option. TheMODULES_LIST_OUTPUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--output
/-o
command line switches change the value of this configuration option. SeeMODULES_LIST_OUTPUT
description for details.New in version 4.7.
-
list_terse_output
¶ Content to report in addition to module names on
list
sub-command terse output mode.Default value is
header
. It can be changed at installation time with--with-list-terse-output
option. TheMODULES_LIST_TERSE_OUTPUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--output
/-o
command line switches change the value of this configuration option. SeeMODULES_LIST_TERSE_OUTPUT
description for details.New in version 4.7.
-
locked_configs
¶ Configuration options that cannot be superseded. All options referred in
locked_configs
value are locked, thus their value cannot be altered.This configuration option is set to an empty value by default. It can be changed at installation time with
--with-locked-configs
option. The value of this option cannot be altered.
Defines if the Modules magic cookie (i.e.,
#%Module
file signature) should be checked to determine if a file is a modulefile.Default value is
always
. TheMODULES_MCOOKIE_CHECK
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_MCOOKIE_CHECK
description for details.New in version 5.1.
Defines if the version set in the Modules magic cookie used in modulefile should be checked against the version of
modulecmd.tcl
to determine if the modulefile could be evaluated or not.Default value is
1
. It can be changed at installation time with--disable-mcookie-version-check
option. TheMODULES_MCOOKIE_VERSION_CHECK
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_MCOOKIE_VERSION_CHECK
description for details.New in version 4.7.
-
ml
¶ Define ml command at initialization time.
Default value is
1
. It can be changed at installation time with--disable-ml
option. TheMODULES_ML
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_ML
description for details.New in version 4.5.
-
nearly_forbidden_days
¶ Set the number of days a module should be considered nearly forbidden prior reaching its expiry date.
Default value is
14
. It can be changed at installation time with--with-nearly-forbidden-days
option. TheMODULES_NEARLY_FORBIDDEN_DAYS
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_NEARLY_FORBIDDEN_DAYS
description for details.New in version 4.6.
-
pager
¶ Text viewer to paginate message output.
Default value is
less -eFKRX
. It can be changed at installation time with--with-pager
and--with-pager-opts
options. TheMODULES_PAGER
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_PAGER
description for details.
-
protected_envvars
¶ Prevents any modification of listed environment variables (colon : separator).
This configuration option is unset by default. The
MODULES_PROTECTED_ENVVARS
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_PROTECTED_ENVVARS
description for details.New in version 5.2.
-
quarantine_support
¶ Defines if code for quarantine mechanism support should be generated in module shell function definition.
Default value is
0
. It can be changed at installation time with--enable-quarantine-support
option. TheMODULES_QUARANTINE_SUPPORT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_QUARANTINE_SUPPORT
description for details.New in version 5.0.
-
rcfile
¶ Global run-command file location.
This configuration option is unset by default. The
MODULERCFILE
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULERCFILE
description for details.
-
redirect_output
¶ Control whether or not the output of module command should be redirected from stderr to stdout.
Default value is
1
. TheMODULES_REDIRECT_OUTPUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--redirect
and--no-redirect
command line switches change the value of this configuration option. SeeMODULES_REDIRECT_OUTPUT
description for details.New in version 5.1.
-
reset_target_state
¶ Control behavior of
reset
sub-command. Whether environment should be purged (__purge__
), initial environment (__init__
) or a named collection (any other value) should restored.Default value is
__init__
. TheMODULES_RESET_TARGET_STATE
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_RESET_TARGET_STATE
description for details.New in version 5.2.
-
run_quarantine
¶ Environment variables to indirectly pass to
modulecmd.tcl
.This configuration option is set to an empty value by default. It can be changed at installation time with
--with-quarantine-vars
option that setsMODULES_RUN_QUARANTINE
. This environment variable is also defined byconfig
sub-command when changing this configuration option. SeeMODULES_RUN_QUARANTINE
description for details.
-
search_match
¶ Module search match style.
Default value is
starts_with
. It can be changed at installation time with--with-search-match
option. TheMODULES_SEARCH_MATCH
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--contains
and--starts-with
command line switches change the value of this configuration option. SeeMODULES_SEARCH_MATCH
description for details.
-
set_shell_startup
¶ Ensure module command definition by setting shell startup file.
Default value is
0
. It can be changed at installation time with--enable-set-shell-startup
option. TheMODULES_SET_SHELL_STARTUP
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_SET_SHELL_STARTUP
description for details.
-
shells_with_ksh_fpath
¶ Ensure module command is defined in ksh when it is started as a sub-shell from the listed shells.
This configuration option is set to an empty value by default. The
MODULES_SHELLS_WITH_KSH_FPATH
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_SHELLS_WITH_KSH_FPATH
description for details.New in version 4.7.
-
silent_shell_debug
¶ Disablement of shell debugging property for the module command. Also defines if code to silence shell debugging property should be generated in module shell function definition.
Default value is
0
. It can be changed at installation time with--enable-silent-shell-debug-support
option. TheMODULES_SILENT_SHELL_DEBUG
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_SILENT_SHELL_DEBUG
description for details.
-
siteconfig
¶ Primary site-specific configuration script location. See Site-specific configuration section for details.
Default value is
/etc/environment-modules/siteconfig.tcl
. It can be changed at installation time with--prefix
or--etcdir
options. The value of this option cannot be altered.
-
tag_abbrev
¶ Abbreviations to use to report module tags.
Default value is
auto-loaded=aL:loaded=L:hidden=H:hidden-loaded=H:forbidden=F:nearly-forbidden=nF:sticky=S:super-sticky=sS:keep-loaded=kL
. It can be changed at installation time with--with-tag-abbrev
option. TheMODULES_TAG_ABBREV
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_TAG_ABBREV
description for details.New in version 4.7.
-
tag_color_name
¶ Tags whose name should be colored instead of module name.
This configuration option is set to an empty value by default. It can be changed at installation time with
--with-tag-color-name
option. TheMODULES_TAG_COLOR_NAME
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_TAG_COLOR_NAME
description for details.New in version 4.7.
-
tcl_ext_lib
¶ Modules Tcl extension library location.
Default value is
/usr/share/Modules/lib64/libtclenvmodules.so
. It can be changed at installation time with--prefix
or--libdir
options. The value of this option cannot be altered.
-
tcl_linter
¶ Command to check syntax of modulefiles with through
lint
sub-command.Default value is
nagelfar.tcl
. It can be changed at installation time with--with-tcl-linter
and--with-tcl-linter-opts
options. TheMODULES_TCL_LINTER
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_TCL_LINTER
description for details.New in version 5.2.
-
term_background
¶ Terminal background color kind.
Default value is
dark
. It can be changed at installation time with--with-terminal-background
option. TheMODULES_TERM_BACKGROUND
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_TERM_BACKGROUND
description for details.
-
term_width
¶ Set the width of the output.
Default value is
0
. TheMODULES_TERM_WIDTH
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--width
/-w
command line switches change the value of this configuration option. SeeMODULES_TERM_WIDTH
description for details.New in version 4.7.
-
unload_match_order
¶ Unload firstly loaded or lastly loaded module matching request.
Default value is
returnlast
. It can be changed at installation time with--with-unload-match-order
option. TheMODULES_UNLOAD_MATCH_ORDER
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_UNLOAD_MATCH_ORDER
description for details.
-
variant_shortcut
¶ Shortcut characters that could be used to specify or report module variants.
This configuration option is set to an empty value by default. It can be changed at installation time with
--with-variant-shortcut
option. TheMODULES_VARIANT_SHORTCUT
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_VARIANT_SHORTCUT
description for details.New in version 4.8.
-
verbosity
¶ Module command verbosity level.
Default value is
normal
. It can be changed at installation time with--with-verbosity
option. TheMODULES_VERBOSITY
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. The--debug
/-D
,--silent
/-s
,--trace
/-T
and--verbose
/-v
command line switches change the value of this configuration option. SeeMODULES_VERBOSITY
description for details.
-
wa_277
¶ Workaround for Tcsh history issue.
Default value is
0
. It can be changed at installation time with--enable-wa-277
option. TheMODULES_WA_277
environment variable is defined byconfig
sub-command when changing this configuration option from its default value. SeeMODULES_WA_277
description for details.
New in version 4.3.
Changed in version 5.3: Value prefixes
+
and-
added to append and subtract elements to list-value options-
-
display
modulefile...
¶ Display information about one or more modulefiles. The display sub-command will list the full path of the modulefile and the environment changes the modulefile will make if loaded. (Note: It will not display any environment changes found within conditional statements.)
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
-
edit
modulefile
¶ Open modulefile for edition with text editor command designated by the
editor
configuration option.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.8.
-
help
[modulefile...]
¶ Print the usage of each sub-command. If an argument is given, print the Module-specific help information for the modulefile.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
-
info-loaded
modulefile
¶ Returns the names of currently loaded modules matching passed modulefile. Returns an empty string if passed modulefile does not match any loaded modules. See
module-info loaded
in the modulefile man page for further explanation.New in version 4.1.
-
initadd
modulefile...
¶ Add modulefile to the shell's initialization file in the user's home directory. The startup files checked (in order) are:
C Shell
.modules
,.cshrc
,.csh_variables
and.login
TENEX C Shell
.modules
,.tcshrc
,.cshrc
,.csh_variables
and.login
Bourne and Korn Shells
.modules
,.profile
GNU Bourne Again Shell
.modules
,.bash_profile
,.bash_login
,.profile
and.bashrc
Z Shell
.modules
,.zshrc
,.zshenv
and.zlogin
Friendly Interactive Shell
.modules
,.config/fish/config.fish
If a
module load
line is found in any of these files, the modulefiles are appended to any existing list of modulefiles. Themodule load
line must be located in at least one of the files listed above for any of theinit
sub-commands to work properly. If themodule load
line is found in multiple shell initialization files, all of the lines are changed.
-
initclear
¶ Clear all of the modulefiles from the shell's initialization files.
-
initlist
¶ List all of the modulefiles loaded from the shell's initialization file.
-
initprepend
modulefile...
¶ Does the same as
initadd
but prepends the given modules to the beginning of the list.
-
initrm
modulefile...
¶ Remove modulefile from the shell's initialization files.
-
initswitch
modulefile1 modulefile2
¶ Switch modulefile1 with modulefile2 in the shell's initialization files.
-
is-avail
modulefile...
¶ Returns a true value if any of the listed modulefiles exists in enabled
MODULEPATH
. Returns a false value otherwise. Seeis-avail
in the modulefile man page for further explanation.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.1.
-
is-loaded
[modulefile...]
¶ Returns a true value if any of the listed modulefiles has been loaded or if any modulefile is loaded in case no argument is provided. Returns a false value otherwise. See
is-loaded
in the modulefile man page for further explanation.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.1.
-
is-saved
[collection...]
¶ Returns a true value if any of the listed collections exists or if any collection exists in case no argument is provided. Returns a false value otherwise. See
is-saved
in the modulefile man page for further explanation.New in version 4.1.
-
is-used
[directory...]
¶ Returns a true value if any of the listed directories has been enabled in
MODULEPATH
or if any directory is enabled in case no argument is provided. Returns a false value otherwise. Seeis-used
in the modulefile man page for further explanation.New in version 4.1.
-
lint
[-a] [modulefile...]
¶ Analyze syntax of one or more modulefiles with the linter command designated by the
tcl_linter
configuration option.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If no modulefile is specified, all the modulefiles and modulerc available in enabled modulepaths are analyzed as well as global and user rc files. Hidden modulefiles are also analyzed when
--all
/-a
option is set.When nagelfar.tcl is the selected linter command, a static Tcl syntax analysis is performed. In addition, syntax of modulefile commands are checked in these files based on their kind (global/user rc, modulerc or modulefile).
New in version 5.2.
-
list
[-t|-l|-j] [-a] [-o LIST] [-S|-C] [pattern...]
¶ List loaded modules. If a pattern is given, then the loaded modules are filtered to only list those whose name matches this pattern. It may contain wildcard characters. pattern is matched in a case insensitive manner by default. If multiple patterns are given, loaded module has to match at least one of them to be listed.
Module tags applying to the loaded modules are reported along the module name they are associated to (see Module tags section).
Module variants selected on the loaded modules are reported along the module name they belong to (see Module variants section).
A Key section is added at the end of the output in case some elements are reported in parentheses or chevrons along module name or if some graphical rendition is made over some output elements. This Key section gives hints on the meaning of such elements.
The parameter pattern may also refer to a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If pattern contains variant specification, loaded modules are included in results only if they match it. pattern may be a bare variant specification without mention of a module name.
Changed in version 4.7: Key section added at end of output
Changed in version 4.8: Report if enabled the variants selected on loaded modules
Changed in version 5.1: pattern search to filter loaded modules added
Changed in version 5.1: Options
--starts-with
/-S
and--contains
/-C
addedChanged in version 5.3: pattern may include variant specification to filter results
-
load
[options] modulefile...
¶ Load modulefile into the shell environment.
load
command accepts the following options:--auto|--no-auto
-f|--force
--tag=taglist
Once loaded, the
loaded
module tag is associated to the loaded module. If module has been automatically loaded by another module, theauto-loaded
tag is associated instead (see Module tags section).The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
The
--tag
option accepts a list of module tags to apply to modulefile once loaded. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.Changed in version 5.1: Option
--tag
added
-
load-any
[options] modulefile...
¶ Load into the shell environment one of the modulefile specified. Try to load each modulefile specified in list from the left to the right until one got loaded or is found already loaded. Do not complain if modulefile cannot be found but if its evaluation fails an error is reported.
load-any
command accepts the following options:--auto|--no-auto
-f|--force
--tag=taglist
Once loaded, the
loaded
module tag is associated to the loaded module. If module has been automatically loaded by another module, theauto-loaded
tag is associated instead (see Module tags section).The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
The
--tag
option accepts a list of module tags to apply to modulefile once loaded. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.New in version 5.1.
-
mod-to-sh
[options] shell modulefile...
¶ Evaluate modulefile and report resulting environment changes as code for shell.
mod-to-sh
command accepts the following options:--auto|--no-auto
-f|--force
An attempt to load modulefile is made to get its environment changes. This evaluation does not change the current shell environment. Like for
load
sub-command, no evaluation occurs if modulefile is found loaded in current environment.Changes made on environment variable intended for Modules private use (e.g.,
LOADEDMODULES
,_LMFILES_
,__MODULES_*
) are ignored.Shell could be any shell name supported by
modulecmd.tcl
.Produced shell code is returned on the message output channel by
modulecmd.tcl
. Thus it is not rendered in current environment by the module shell function.mod-to-sh
automatically setverbosity
to thesilent
mode, to avoid messages to mix with the produced shell code. Verbosity is not changed if set to thetrace
mode or any higher debugging level.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 5.2.
-
path
modulefile
¶ Print path to modulefile.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.0.
-
paths
pattern
¶ Print path of available modulefiles matching pattern.
The parameter pattern may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If pattern contains variant specification or Extra specifier, the Extra match search process is triggered to collect command information used in modulefiles. Modules are included in results only if they match pattern variant specification and extra specifier. pattern may be a bare variant specification or extra specifier without mention of a module name.
New in version 4.0.
Changed in version 5.3: pattern may include variant specification or extra specifier to filter results
-
prepend-path
[-d C|--delim C|--delim=C] [--duplicates] variable value...
¶ Prepend value to environment variable. The variable is a colon, or delimiter, separated list. See
prepend-path
in the modulefile man page for further explanation.When
prepend-path
is called as a module sub-command, the reference counter variable, which denotes the number of times value has been added to environment variable, is not updated unless if the--duplicates
option is set.New in version 4.1.
Changed in version 5.0: Reference counter environment variable is not updated anymore unless if the
--duplicates
option is set
-
purge
[-f]
¶ Unload all loaded modulefiles.
When the
--force
option is set, also unload sticky modules and modulefiles that are depended by non-unloadable modules.
-
refresh
¶ Force a refresh of all non-persistent components of currently loaded modules. This should be used on derived shells where shell completions, shell aliases or shell functions need to be reinitialized but the environment variables have already been set by the currently loaded modules.
Loaded modules are evaluated in
refresh
mode following their load order. In this evaluation mode only thecomplete
,set-alias
,set-function
andputs
modulefile commands will produce environment changes. Other modulefile commands that produce environment changes (likesetenv
orappend-path
) are ignored during arefresh
evaluation as their changes should already be applied.Only the loaded modules defining non-persistent environment changes are evaluated in
refresh
mode. Such loaded modules are listed in the__MODULES_LMREFRESH
environment variable.Changed in version 4.0: Sub-command made as an alias of
reload
sub-commandChanged in version 5.0: Behavior of version 3.2
refresh
sub-command restoredChanged in version 5.2: Only evaluate modules listed in
__MODULES_LMREFRESH
-
reload
¶ Unload then load all loaded modulefiles.
No unload then load is performed and an error is returned if the loaded modulefiles have unsatisfied constraint corresponding to the
prereq
andconflict
they declare.New in version 4.0.
-
remove-path
[-d C|--delim C|--delim=C] [--index] variable value...
¶ Remove value from the colon, or delimiter, separated list in environment variable. See
remove-path
in the modulefile man page for further explanation.When
remove-path
is called as a module sub-command, the reference counter variable, which denotes the number of times value has been added to environment variable, is ignored and value is removed whatever the reference counter value set.New in version 4.1.
Changed in version 5.0: value is removed whatever its reference counter value
-
reset
¶ Restore initial environment, which corresponds to the loaded state after Modules initialization.
reset
sub-command restores the environment definition found in__MODULES_LMINIT
environment variable.reset
behavior can be changed withreset_target_state
. This configuration option is set by default to__init__
, which corresponds to the above behavior description. When set to__purge__
,reset
performs apurge
of the environment. When set to any other value,reset
performs arestore
of corresponding name collection.New in version 5.2.
-
restore
[collection]
¶ Restore the environment state as defined in collection. If collection name is not specified, then it is assumed to be the default collection if it exists,
__init__
special collection otherwise. If collection is a fully qualified path, it is restored from this location rather than from a file under the user's collection directory. IfMODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable is appended to the collection file name to restore.If collection name is
__init__
, initial environment state defined in__MODULES_LMINIT
environment variable is restored.When restoring a collection, the currently set
MODULEPATH
directory list and the currently loaded modulefiles are unused and unloaded then used and loaded to exactly match theMODULEPATH
and loaded modulefiles lists saved in this collection file. The order of the paths and modulefiles set in collection is preserved when restoring. It means that currently loaded modules are unloaded to get the sameLOADEDMODULES
root than collection and currently used module paths are unused to get the sameMODULEPATH
root. Then missing module paths are used and missing modulefiles are loaded.If a module, without a default version explicitly defined, is recorded in a collection by its bare name: loading this module when restoring the collection will fail if the configuration option
implicit_default
is disabled.New in version 4.0.
Changed in version 5.2: Restore initial environment when collection name is
__init__
or when no collection name is specified and no default collection exists
-
save
[collection]
¶ Record the currently set
MODULEPATH
directory list and the currently loaded modulefiles in a collection file under the user's collection directory$HOME/.module
. If collection name is not specified, then it is assumed to be thedefault
collection. If collection is a fully qualified path, it is saved at this location rather than under the user's collection directory.If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the collection file name.By default, if a loaded modulefile corresponds to the explicitly defined default module version, the bare module name is recorded. If the configuration option
implicit_default
is enabled, the bare module name is also recorded for the implicit default module version. IfMODULES_COLLECTION_PIN_VERSION
is set to1
, module version is always recorded even if it is the default version.By default, only the module tags specifically set with the
--tag
option or resulting from a specific module state (likeauto-loaded
andkeep-loaded
tags) are recorded in collection. IfMODULES_COLLECTION_PIN_TAG
is set to1
, all tags are recorded in collection exceptnearly-forbidden
tag.No collection is recorded and an error is returned if the loaded modulefiles have unsatisfied constraint corresponding to the
prereq
andconflict
they declare.New in version 4.0.
-
savelist
[-t|-l|-j] [-a] [-S|-C] [pattern...]
¶ List collections that are currently saved under the user's collection directory. If
MODULES_COLLECTION_TARGET
is set, only collections matching the target suffix will be displayed unless if the--all
/-a
option is set.If a pattern is given, then the collections are filtered to only list those whose name matches this pattern. It may contain wildcard characters. pattern is matched in a case insensitive manner by default. If multiple patterns are given, collection has to match at least one of them to be listed.
Stash collections are not listed unless if the
--all
/-a
option is set. Stash collections can be listed withstashlist
sub-command.New in version 4.0.
Changed in version 5.2: pattern search to filter collections added
Changed in version 5.2: Options
--starts-with
/-S
,--contains
/-C
and--all
/-a
added
-
saverm
[collection]
¶ Delete the collection file under the user's collection directory. If collection name is not specified, then it is assumed to be the default collection. If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the collection file name.New in version 4.0.
-
saveshow
[collection]
¶ Display the content of collection. If collection name is not specified, then it is assumed to be the default collection if it exists,
__init__
special collection otherwise. If collection is a fully qualified path, this location is displayed rather than a collection file under the user's collection directory. IfMODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the collection file name.If collection name is
__init__
, initial environment content defined in__MODULES_LMINIT
environment variable is displayed.New in version 4.0.
Changed in version 5.2: Display content of initial environment when collection name is
__init__
or when no collection name is specified and no default collection exists
-
search
[-a] [-j] string
¶ Seeks through the
module-whatis
information of all modulefiles for the specified string. All module-whatis information matching the string in a case insensitive manner will be displayed. string may contain wildcard characters.New in version 4.0: Prior version 4.0
module-whatis
information search was performed withapropos
orkeyword
sub-commands.
-
sh-to-mod
shell script [arg...]
¶ Evaluate with shell the designated script with defined arguments to find out the environment changes it does. Environment prior and after script evaluation are compared to determine these changes. They are translated into modulefile commands to output the modulefile content equivalent to the evaluation of shell script.
Changes on environment variables, shell aliases, shell functions, shell completions and current working directory are tracked.
Changes made on environment variable intended for Modules private use (e.g.,
LOADEDMODULES
,_LMFILES_
,__MODULES_*
) are ignored.Shell could be specified as a command name or a fully qualified pathname. The following shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.
New in version 4.6.
Changed in version 5.1: Changes on Modules private environment variable are ignored
Changed in version 5.1: Support for tracking shell completion changes on bash, tcsh and fish shells added
-
source
[options] modulefile...
¶ Execute modulefile into the shell environment. Once executed modulefile is not marked loaded in shell environment which differ from
load
sub-command.source
command accepts the following options:--auto|--no-auto
-f|--force
If modulefile corresponds to a fully qualified path, this file is executed. Otherwise modulefile is searched among the available modulefiles.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.0.
Changed in version 5.2: Accept modulefile specification as argument
-
stash
¶ Save
current environment in a stash collection thenreset
to initial environment.A collection is created only if current environment state differs from initial environment. Stash collection is named stash-<unix_millis_timestamp> where <unix_millis_timestamp> is the number of milliseconds between Unix Epoch and when this command is run.
If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the stash collection file name.New in version 5.2.
-
stashclear
¶ Remove all stash collection files of current
collection_target
. If no collection target is currently set, remove stash collection files without a target suffix.New in version 5.2.
-
stashlist
[-t|-l|-j]
¶ List all stash collection files of current
collection_target
. If no collection target is currently set, list stash collection files without a target suffix.New in version 5.2.
-
stashpop
[stash]
¶ Restore
stash collection then delete corresponding collection file.stash is either a full stash collection name (i.e., stash-<unix_millis_timestamp>) or a stash index. Most recent stash collection has index 0, 1 is the one before it. When no stash is given the latest stash collection is assumed (that is stash index 0).
If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the stash collection file name to restore.New in version 5.2.
-
stashrm
[stash]
¶ Remove
stash collection file.stash is either a full stash collection name (i.e., stash-<unix_millis_timestamp>) or a stash index. Most recent stash collection has index 0, 1 is the one before it. When no stash is given the latest stash collection is assumed (that is stash index 0).
If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the stash collection file name to delete.New in version 5.2.
-
stashshow
[stash]
¶ Display
the content of stash collection file.stash is either a full stash collection name (i.e., stash-<unix_millis_timestamp>) or a stash index. Most recent stash collection has index 0, 1 is the one before it. When no stash is given the latest stash collection is assumed (that is stash index 0).
If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable will be appended to the stash collection file name to display.New in version 5.2.
-
state
[name]
¶ Gets
modulecmd.tcl
states. Reports the currently set value of passed state name or all existing states if no name passed.New in version 5.1.
-
switch
[options] [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.
switch
command accepts the following options:--auto|--no-auto
-f|--force
--tag=taglist
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
The
--tag
option accepts a list of module tags to apply to modulefile once loaded. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.Changed in version 5.1: Option
--tag
added
-
test
modulefile...
¶ Execute and display results of the Module-specific tests for the modulefile.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.0.
-
try-load
[options] modulefile...
¶ Like
load
sub-command, load modulefile into the shell environment, but do not complain if modulefile cannot be found. If modulefile is found but its evaluation fails, error is still reported.try-load
command accepts the following options:--auto|--no-auto
-f|--force
--tag=taglist
Once loaded, the
loaded
module tag is associated to the loaded module. If module has been automatically loaded by another module, theauto-loaded
tag is associated instead (see Module tags section).The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
The
--tag
option accepts a list of module tags to apply to modulefile once loaded. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.New in version 4.8.
Changed in version 5.1: Option
--tag
added
-
unload
[--auto|--no-auto] [-f] modulefile...
¶ Remove modulefile from the shell environment.
The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
-
unuse
directory...
¶ Remove one or more directories from the
MODULEPATH
environment variable.If
module unuse
is called during a modulefile evaluation, the reference counter environment variable__MODULES_SHARE_MODULEPATH
, which denotes the number of times directory has been enabled, is checked and directory is removed only if its relative counter is equal to 1 or not defined. Otherwise directory is kept and reference counter is decreased by 1. Whenmodule unuse
is called from the command-line or within an initialization modulefile script directory is removed whatever the reference counter value set.If directory corresponds to the concatenation of multiple paths separated by colon character, each path is treated separately.
Changed in version 5.0: directory is removed whatever its reference counter value if
module unuse
is called from the command-line or within an initialization modulefile scriptChanged in version 5.0: Accept several modulepaths passed as a single string
-
use
[-a|--append] directory...
¶ Prepend one or more directories to the
MODULEPATH
environment variable. The--append
flag will append the directory toMODULEPATH
.When directory is already defined in
MODULEPATH
, it is not added again or moved at the end or at the beginning of the environment variable.If
module use
is called during a modulefile evaluation, the reference counter environment variable__MODULES_SHARE_MODULEPATH
is also set to increase the number of times directory has been added toMODULEPATH
. Reference counter is not updated whenmodule use
is called from the command-line or within an initialization modulefile script.A directory that does not exist yet can be specified as argument and then be added to
MODULEPATH
.Changed in version 5.0: Accept non-existent modulepath
Changed in version 5.0: Reference counter value of directory is not anymore increased if
module use
is called from the command-line or within an initialization modulefile script
-
whatis
[-a] [-j] [pattern...]
¶ Display the information set up by the
module-whatis
commands inside modulefiles matching pattern. pattern may contain wildcard characters. If no pattern is specified, allmodule-whatis
lines will be shown.The parameter pattern may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
If pattern contains variant specification or Extra specifier, the Extra match search process is triggered to collect command information used in modulefiles. Modules are included in results only if they match pattern variant specification and extra specifier. pattern may be a bare variant specification or extra specifier without mention of a module name.
Changed in version 5.3: pattern may include variant specification or extra specifier to filter results
Modulefiles¶
modulefiles are written in the Tool Command Language (Tcl) and are
interpreted by modulecmd.tcl
. modulefiles can use conditional
statements. Thus the effect a modulefile will have on the environment
may change depending upon the current state of the environment.
Environment variables are unset when unloading a modulefile. Thus, it is
possible to load
a modulefile and then unload
it without
having the environment variables return to their prior state.
Advanced module version specifiers¶
When the advanced module version specifiers mechanism is enabled (see
MODULES_ADVANCED_VERSION_SPEC
), the specification of modulefile
passed on Modules sub-commands changes. After the module name a version
constraint and variants may be added.
Version specifiers¶
After the module name a version constraint prefixed by the @
character may
be added. It could be directly appended to the module name or separated from
it with a space character.
Constraints can be expressed to refine the selection of module version to:
- a single version with the
@version
syntax, for instancefoo@1.2.3
syntax will select modulefoo/1.2.3
- a list of versions with the
@version1,version2,...
syntax, for instancefoo@1.2.3,1.10
will match modulesfoo/1.2.3
andfoo/1.10
- a range of versions with the
@version1:
,@:version2
and@version1:version2
syntaxes, for instancefoo@1.2:
will select all versions of modulefoo
greater than or equal to1.2
,foo@:1.3
will select all versions less than or equal to1.3
andfoo@1.2:1.3
matches all versions between1.2
and1.3
including1.2
and1.3
versions
Advanced specification of single version or list of versions may benefit from
the activation of the extended default mechanism (see
MODULES_EXTENDED_DEFAULT
) to use an abbreviated notation like @1
to refer to more precise version numbers like 1.2.3
. Range of versions on
its side natively handles abbreviated versions.
In order to be specified in a range of versions or compared to a range of
versions, the version major element should corresponds to a number. For
instance 10a
, 1.2.3
, 1.foo
are versions valid for range
comparison whereas default
or foo.2
versions are invalid for range
comparison.
Range of versions can be specified in version list, for instance
foo@:1.2,1.4:1.6,1.8:
. Such specification helps to exclude specific
versions, like versions 1.3
and 1.7
in previous example.
If the implicit default mechanism is also enabled (see
MODULES_IMPLICIT_DEFAULT
), a default
and latest
symbolic
versions are automatically defined for each module name (also at each
directory level for deep modulefiles). These automatic version symbols are
defined unless a symbolic version, alias, or regular module version already
exists for these default
or latest
version names. Using the
mod@latest
(or mod/latest
) syntax ensures highest available version
will be selected.
The symbolic version loaded
may be used over loaded module name to
designate the loaded version of the module with associated selected variants.
This version symbol should be specified using the @
prefix notation (e.g.,
foo@loaded
). An error is returned if no version of designated module is
currently loaded.
Variants¶
After the module name, variants can be specified. Module variants are
alternative evaluation of the same modulefile. A variant is specified by
associating a value to its name. This specification is then transmitted to the
evaluating modulefile which instantiates the variant in the
ModuleVariant
array variable when reaching the variant
modulefile command declaring this variant.
Variant can be specified with the name=value
syntax where name is the
declared variant name and value, the value this variant is set to when
evaluating the modulefile.
Boolean variants can be specified with the +name
syntax to set this
variant on and with the -name
or ~name
syntaxes to set this variant
off. The -name
syntax is not supported on ml command as the
minus sign already means to unload designated module. The ~name
and
+name
syntaxes could also be defined appended to another specification
word (e.g., the module name, version or another variant specification),
whereas -name
syntax must be the start of a new specification word.
Boolean variants may also be specified with the name=value
syntax. value
should be set to 1
, true
, t
, yes
, y
or on
to enable
the variant or it should be set to 0
, false
, f
, no
, n
or
off
to disable the variant.
Shortcuts may be used to abbreviate variant specification. The
variant_shortcut
configuration option associates shortcut character
to variant name. With a shortcut defined, variant could be specified with the
<shortcut>value
syntax. For instance if character %
is set as a
shortcut for variant foo
, the %value
syntax is equivalent to the
foo=value
syntax.
Specific characters used in variant specification syntax cannot be used as
part of the name of a module. These specific characters are +
, ~
,
=
and all characters set as variant shortcut. Exception is made for +
character which could be set one or several consecutive times at the end of
module name (e.g., name+ or name++).
New in version 4.4.
Changed in version 4.8: Use of version range is allowed in version list
Changed in version 4.8: Support for module variant added
Extra specifier¶
After the module name, extra specifiers can be defined in module search context. Extra specifiers are an extra query to list available modulefiles based on their content definition. They rely on the Extra match search mechanism that collects content of available modulefiles.
Extra specifier can be set with the element:name
syntax where element is
a Tcl modulefile command and name an item defined by this command.
Depending on the kind of Tcl modulefile command, name can refer to an
environment variable, a shell alias, a module specification, etc.
Supported extra specifier elements are:
variant
,complete
,uncomplete
,set-alias
,unset-alias
,set-function
,unset-function
,chdir
,family
setenv
,unsetenv
,append-path
,prepend-path
,remove-path
andpushenv
: these elements related to environment variable handling may also be aliasedenvvar
prereq
,prereq-any
,prereq-all
,depends-on
,always-load
,load
,load-any
,try-load
,switch
andswitch-on
: these elements related to module requirement definition accept a module specification as value name and may be aliasedrequire
conflict
,unload
,switch
andswitch-off
: these elements related to module incompatibility definition accept a module specification as value name and may be aliasedincompat
Each of the above supported elements corresponds to a Tcl modulefile
command. load
, load-any
, try-load
, switch
and unload
match
corresponding module sub-commands. prereq-any
is an alias on prereq
and vice versa as both Tcl modulefile commands are the same. Following the
same trend prereq-all
is an alias on depends-on
and vice versa.
Regarding switch-off
and switch-on
elements they correspond
respectively to the module to unload (if specified) and the module to load on
a module switch
command. switch
is an alias that matches both
switch-off
and switch-on
elements.
When several extra specifiers are set on a module search query, they act as an AND operation. Which means modules listed in result are those matching all extra specifiers defined.
Module specification used as name value for some extra specifier elements may leverage Advanced module version specifiers syntax. However if a module version range or list is implied, it is currently resolved to existing modules. Thus it may not match modulefile definitions targeting modules that do not exist. In addition, module aliases and symbolic versions are not resolved to their target either if set in extra specifier query or in modulefile definition.
Extra specifier can only be set in a module search context (avail
,
whatis
and paths
sub-commands). An error is raised if used
on a module specification query in another context. An error is also raised
if an unknown extra specifier element is defined in search query.
New in version 5.3.
Module tags¶
Module tags are piece of information that can be associated to individual modulefiles. Tags could be purely informational or may lead to specific behaviors.
Module tags may be inherited from the module state set by a modulefile command or consequence of a module action. The inherited tags are:
auto-loaded
: module has been automatically loaded by another moduleforbidden
: module has been set forbidden through the use of themodule-forbid
command and thus this module cannot be loaded.hidden
: module has been set hidden through the use of themodule-hide
command and thus it is not reported by default among the result of anavail
sub-command.hidden-loaded
: module has been set hidden once loaded through the use of themodule-hide --hidden-loaded
command thus it is not reported bu default among the result of alist
sub-command.loaded
: module is currently loadednearly-forbidden
: module will soon be forbidden, which has been set through the use of themodule-forbid
command. Thus this module will soon not be able to load anymore.
Tags may also be associated to modules by using the module-tag
modulefile command. Among tags that could be set this way, some have a special
meaning:
keep-loaded
: auto-loaded module cannot be automatically unloaded. This tag is also set through the use of thealways-load
command.sticky
: module once loaded cannot be unloaded unless forced or reloaded (see Sticky modules section)super-sticky
: module once loaded cannot be unloaded unless reloaded, module cannot be unloaded even if forced (see Sticky modules section)
The --tag
option helps to apply additional tags to modules. It is
available on load
, load-any
, switch
and
try-load
sub-commands and on always-load
,
depends-on
, module
, prereq
, prereq-all
and
prereq-any
modulefile commands. In case the designated module is
already loaded, the additional tags are added to the list of tags already
applied to this module.
Module tags are reported along the module they are associated to on
avail
and list
sub-command results and also when module's
loading, unloading, refreshing or tagging evaluation is mentioned. Tags could
be reported either:
- along the module name, all tags set within angle brackets, each tag
separated from the others with a colon character (e.g.,
foo/1.2 <tag1:tag2>
). - graphically rendered over the module name for each tag associated to a
Select Graphic Rendition (SGR) code in the color palette (see
MODULES_COLORS
)
When an abbreviated string is associated to a tag name (see
MODULES_TAG_ABBREV
), this abbreviation is used to report tag along
the module name or the tag is graphically rendered over the module name if a
SGR code is associated with tag abbreviation in the color palette. With an
abbreviation set, the SGR code associated to the tag full name is ignored thus
an SGR code should be associated to the abbreviation to get a graphical
rendering of tag. If the abbreviation associated to a tag corresponds to the
empty string, tag is not reported.
Graphical rendering is made over the tag name or abbreviation instead of over
the module name for each tag name or abbreviation set in the
MODULES_TAG_COLOR_NAME
environment variable.
When several tags have to be rendered graphically over the same module name, each tag is rendered over a sub-part of the module name. In case more tags need to be rendered than the total number of characters in the module name, the remaining tags are graphically rendered over the tag name instead of over the module name.
When the JSON output mode is enabled (with --json
), tags are
reported by their name under the tags
attribute. Tag abbreviation and
color rendering do not apply on JSON output.
Module tags cannot be used in search query to designate a modulefile.
New in version 4.7.
Changed in version 5.1: Tag keep-loaded
added
Sticky modules¶
Modules are said sticky when they cannot be unloaded (they stick to the loaded environment). Two kind of stickiness can be distinguished:
sticky
module: cannot be unloaded unless if the unload is forced or if the module is reloaded after being unloaded or if restoring a collection.super-sticky
module: cannot be unloaded unless if the module is reloaded after being unloaded; super-sticky modules cannot be unloaded even if the unload is forced.
Modules are designated sticky by associating them the sticky
or the
super-sticky
module tag with the module-tag
modulefile command.
When stickiness is defined over the generic module name (and not over a
specific module version, a version list or a version range), sticky or
super-sticky module can be swapped by another version of module. For instance
if the sticky
tag is defined over foo module, loaded module foo/1.2
can be swapped by foo/2.0. Such stickiness definition means one version of
module should stay loaded whatever version it is.
When restoring a collection or resetting to the initial
environment, sticky modules are unloaded to ensure restore
or
reset
sub-commands fully set the environment in target collection or
initial state. Super-sticky modules still cannot be unloaded with
restore
and reset
sub-commands.
Changed in version 5.2: Unload sticky modules when restoring a collection or resetting to the initial environment
Module variants¶
Module variants are alternative evaluation of the same modulefile. A variant is specified by associating a value to its name when designating module. Variant specification relies on the Advanced module version specifiers mechanism.
Once specified, variant's value is transmitted to the evaluating modulefile
which instantiates the variant in the ModuleVariant
array variable
when reaching the variant
modulefile command declaring this variant.
For instance the module load foo/1.2 bar=value1
command leads to the
evaluation of foo/1.2 modulefile with bar=value1 variant specification.
When reaching the variant bar value1 value2 value3
command in modulefile
during its evaluation, the ModuleVariant(bar)
array element is set to
the value1
string.
Once variants are instantiated, modulefile's code could check the variant values to adapt the evaluation and define for instance different module requirements or produce different environment variable setup.
Variants are interpreted in contexts where modulefiles are evaluated.
Variants specified on module designation are ignored by the
is-avail
or path
sub-commands. On search sub-commands
(avail
, whatis
and paths
), variants are
interpreted and trigger the Extra match search process to filter
results.
When modulefile is evaluated a value should be specified for each variant this
modulefile declares. When reaching the variant
modulefile command
declaring a variant, an error is raised if no value is specified for this
variant and if no default value is declared. Specified variant value should
match a value from the declared accepted value list if such list is defined
otherwise an error is raised. Additionally if a variant is specified but does
not correspond to a variant declared in modulefile, an error is raised.
When searching for modules with variants specified in search query, the Extra match search process triggers a specific scan modulefile evaluation. Variants defined in modulefile are collected during this evaluation then compared to the variants specified in search query. If there is a match, module is included in search results otherwise it is withdrawn.
Module variants are reported along the module they are associated to on
list
sub-command results. They are also reported on avail
sub-command if specified in search query or added to the element to report in
sub-command output (see --output
/-o
option).
Variants are reported within curly braces next to module name, each variant
definition separated from the others with a colon character (e.g.,
foo/1.2{variant1=value:+variant2}
). Boolean variants are reported with the
+name
or -name
syntaxes on list
sub-command or with the
name=on,off
syntax on avail
sub-command. When a shortcut
character is defined for a variant (see MODULES_VARIANT_SHORTCUT
) it
is reported with the <shortcut>value
syntax. For instance if %
character is defined as a shortcut for variant1:
foo/1.2{%value:+variant2}
.
When the JSON output mode is enabled (with --json
), variants are
reported under the variants
JSON object as name/value pairs. Values of
Boolean variant are set as JSON Boolean. Other values are set as JSON strings.
Variant shortcut and color rendering do not apply on JSON output.
New in version 4.8.
Extra match search¶
Extra match search is a mechanism that evaluates available modulefiles during a module search to find those matching an extra query or to report additional information. After selecting modulefiles that match the module name and version specified in search query, these remaining modulefiles are evaluated to collect their content.
Extra match search is available on the following module search sub-commands:
avail
, whatis
and paths
.
Extra match search is triggered when:
- Module variants and their available values have to be reported in
avail output (see
--output
/-o
option): extra match search is triggered to collect variant information - Module variant is specified in search query: extra match search is triggered to collect variant information then match them against variant specified in query
- Extra specifier is specified in search query: extra match search is triggered to collect commands used in modulefiles then match them against extra specifier query
If search query does not contain an extra query and if variant information should not be reported, no extra match search is performed. If search query does not contain any module name and version but contains an extra query or if variant information should be reported, extra match search is applied to all available modulefiles.
During this specific evaluation, modulefiles are interpreted in scan mode. This mode aims to collect the different Tcl modulefile commands used. Special care should be given when writing modulefiles to ensure they cope with such evaluation mode.
Modulefiles tagged forbidden are excluded from extra match search evaluation. Thus they are excluded from result when this mechanism is triggered.
As extra match search implies additional modulefile evaluations, it is advised to build and use Module cache to improve search speed.
New in version 5.3.
Collections¶
Collections describe a sequence of module use
then
module load
commands that are interpreted by
modulecmd.tcl
to set the user environment as described by this
sequence.
Collections are generated by the save
sub-command that dumps the
current user environment state in terms of module paths and loaded modules. By
default collections are saved under the $HOME/.module
directory.
$ module list Currently Loaded Modulefiles: 1) foo/1.2 2) bar/2.0 3) qux/3.5 $ module save foo $ cat $HOME/.module/foo module use --append /path/to/modulefiles module load foo module load bar/2.0 module load qux/3.5
The content of a collection can also be displayed with the saveshow
sub-command. Note that in the above example, bare module name is recorded for
foo
modulefile as loaded version is the implicit default. Loaded version
recording can be enforced by enabling collection_pin_version
configuration option.
$ module config collection_pin_version 1 $ module save foo $ module saveshow foo ------------------------------------------------------------------- /home/user/.module/foo: module use --append /path/to/modulefiles module load foo/1.2 module load bar/2.0 module load qux/3.5 -------------------------------------------------------------------
When a collection is activated, with the restore
sub-command, module paths and loaded modules are unused or unloaded if they
are not part or if they are not ordered the same way as in the collection.
$ module list Currently Loaded Modulefiles: 1) foo/1.2 2) bar/2.1 3) qux/3.5 $ module restore foo Unloading qux/3.5 Unloading bar/2.1 Loading bar/2.0 Loading qux/3.5 $ module list Currently Loaded Modulefiles: 1) foo/1.2 2) bar/2.0 3) qux/3.5
In the above example, second and third module loaded are changed. First loaded module is not changed or reloaded as it is the same module between current environment and collection. As second loaded module was different, this module and all those loaded afterward are unloaded to then load the sequence described by collection. As a result, third loaded module is reloaded, even if is was the same module between current environment and collection.
Existing collections can be listed with savelist
sub-command. They
can be deleted with saverm
sub-command.
$ module savelist Named collection list: 1) default 2) foo $ module saverm default $ module savelist Named collection list: 1) foo
When no argument is provided to save
, restore
,
saveshow
or saverm
sub-commands, the default
collection is assumed.
Collection can also be specified as a full pathname:
$ module save /path/to/collections/bar $ module saveshow /path/to/collections/bar ------------------------------------------------------------------- /path/to/collections/bar: module use --append /path/to/modulefiles module load foo/1.2 module load bar/2.0 module load qux/3.5 -------------------------------------------------------------------
Initial environment¶
Initial environment state, which corresponds to modulepaths enabled and
modules loaded during Modules initialization,
is referred as the __init__
collection. This collection is virtual as
its content is stored in the __MODULES_LMINIT
and not in a file. It
can be displayed with saveshow
and restored with restore
sub-command.
$ module saveshow __init__ ------------------------------------------------------------------- initial environment: module use --append /path/to/modulefiles module load foo/1.2 -------------------------------------------------------------------
If the default
collection does not exist, saveshow
and
restore
sub-commands assume __init__
collection when no argument
provided to them.
$ module list Currently Loaded Modulefiles: 1) foo/1.2 2) bar/2.1 3) qux/3.5 $ module savelist Named collection list: 1) foo $ module restore Unloading qux/3.5 Unloading bar/2.1
Initial environment state can also be restored with the reset
sub-command. This sub-command behavior can be changed with
reset_target_state
configuration option to choose to just purge
loaded modules or to restore a specific collection.
Collection targets¶
A collection target can be defined for current environment session with the
collection_target
configuration option. When set, available
collections are reduced to those suffixed with target name. Which means
restore
, saveshow
, savelist
and saverm
only find collections matching currently set target.
$ module savelist Named collection list: 1) foo $ module config collection_target mytarget $ module savelist No named collection (for target "mytarget"). $ module restore foo ERROR: Collection foo (for target "mytarget") cannot be found
When saving a new collection, generated file is suffixed with currently set target name.
$ module save bar $ module savelist Named collection list (for target "mytarget"): 1) bar $ ls $HOME/.module bar.mytarget foo
Collection targets help to distinguish contexts and make collection reachable
only from the context they have been made for. For instance the same user
account may be used to access different OSes or machine architectures. With a
target set, users are ensured to only access collections built for the context
they are currently connected to. See also MODULES_COLLECTION_TARGET
section.
Stash collections¶
Current user environment can be stashed with stash
sub-command. When
this sub-command is called, current module environment is saved in a stash
collection then initial environment is restored.
$ module list Currently Loaded Modulefiles: 1) foo/1.2 2) qux/4.2 $ module stash Unloading qux/4.2
Specific sub-commands are available to handle stash collections:
stashpop
, stashlist
, stashshow
,
stashrm
and stashclear
. A stash collection is restored
with stashpop
which also deletes the collection once restored.
$ module stashlist Stash collection list (for target "mytarget"): 0) stash-1667669750191 $ module stashpop Loading qux/4.2 $ module stashlist No stash collection (for target "mytarget").
Stash collections have same format and are saved in the same location than other collections. Collection target also applies to stash collection. Creation timestamp is saved in stash collection name.
Stash collection can be designated by their full collection name (i.e., stash-<creation_timestamp>) or a stash index. Most recent stash collection has index 0, 1 is the one before it. When no argument is provided on stash sub-commands, the latest stash collection is assumed (that is stash index 0).
$ module stashlist Stash collection list (for target "mytarget"): 0) stash-1667669750783 1) stash-1667669750253 $ module stashshow 1 ------------------------------------------------------------------- /home/user/.module/stash-1667669750253.mytarget: module use --append /path/to/modulefiles module load foo/1.2 module load bar/2.0 -------------------------------------------------------------------
New in version 4.0.
Changed in version 5.2: Initial environment state introduced
Changed in version 5.2: Stash collection introduced
Site-specific configuration¶
Siteconfig, the site-specific configuration script, is a way to extend
modulecmd.tcl
. Siteconfig is a Tcl script. Its location is
/etc/environment-modules/siteconfig.tcl
.
When modulecmd.tcl
is invoked it sources siteconfig script if it
exists. Any global variable or procedure of modulecmd.tcl
can be
redefined in siteconfig.
An additional siteconfig script may be specified through the
extra_siteconfig
configuration option. The
MODULES_SITECONFIG
environment variable is defined by
config
sub-command when setting extra_siteconfig
. If it
exists the extra siteconfig is sourced by modulecmd.tcl
right after
main siteconfig script.
Hooks¶
Siteconfig relies on the ability of the Tcl language to overwrite previously
defined variables and procedures. Sites may deploy their own Tcl code in
siteconfig to adapt modulecmd.tcl
to their specific needs. The
trace
Tcl command may especially be used to define hooks that are run when
entering or leaving a given procedure, or when a variable is read or written.
See trace(n) man page for detailed information. The following
example setup a procedure that is executed before each modulefile evaluation:
proc beforeEval {cmdstring code result op} {
# code to run right before each modulefile evaluation
}
trace add execution execute-modulefile enter beforeEval
Another possibility is to override the definition of an existing procedure by
first renaming its original version then creating a new procedure that will add
specific code and rely on the renamed original procedure for the rest. See
rename(n) man page for details. As an example, the following code
adds a new query option to the module-info
modulefile command:
rename module-info __module-info
proc module-info {what {more {}}} {
switch -- $what {
platform { return myhost-$::tcl_platform(machine) }
default { return [__module-info $what $more] }
}
}
Siteconfig hook variables¶
Some Tcl variables can be defined in siteconfig script with special hook meaning. The following variables are recognized:
-
modulefile_extra_vars
¶ List of variable names and associated values to setup in modulefile evaluation context. These variables can be accessed when modulefile is executed. In case code in a modulefile changes the value of such variable, its value is reset to the one defined in
modulefile_extra_vars
prior the evaluation of the next modulefile.set modulefile_extra_vars {myvar 1 othervar {some text}}
In the above siteconfig example,
modulefile_extra_vars
sets themyvar
andothervar
variables in the modulefile evaluation context with respectively1
andsome text
as value.New in version 5.2.
-
modulefile_extra_cmds
¶ List of command and associated local procedure to setup in modulefile evaluation context. These commands can be called from the modulefile to execute associated procedure. In case a modulefile changes the definition of such command, its definition is bound again on the procedure defined in
modulefile_extra_cmds
prior the evaluation of the next modulefile.proc mycmd {} { # Tcl code } proc anotherproc {args} { # Tcl code } set modulefile_extra_cmds {mycmd mycmd othercmd anotherproc}
In the above siteconfig example,
modulefile_extra_cmds
sets themycmd
andothercmd
commands in the modulefile evaluation context and bind them respectively to themycmd
andanotherproc
procedures defined in siteconfig script.New in version 5.2.
-
modulerc_extra_vars
¶ List of variable names and associated values to setup in modulerc evaluation context. These variables can be accessed when modulerc is executed. In case code in a modulerc changes the value of such variable, its value is reset to the one defined in
modulerc_extra_vars
prior the evaluation of the next modulerc.set modulerc_extra_vars {myvar 1 othervar {some text}}
In the above siteconfig example,
modulerc_extra_vars
sets themyvar
andothervar
variables in the modulerc evaluation context with respectively1
andsome text
as value.New in version 5.2.
-
modulerc_extra_cmds
¶ List of command and associated local procedure to setup in modulerc evaluation context. These commands can be called from the modulerc to execute associated procedure. In case a modulerc changes the definition of such command, its definition is bound again on the procedure defined in
modulerc_extra_cmds
prior the evaluation of the next modulerc.proc mycmd {} { # Tcl code } proc anotherproc {args} { # Tcl code } set modulerc_extra_cmds {mycmd mycmd othercmd anotherproc}
In the above siteconfig example,
modulerc_extra_cmds
sets themycmd
andothercmd
commands in the modulerc evaluation context and bind them respectively to themycmd
andanotherproc
procedures defined in siteconfig script.New in version 5.2.
New in version 4.1.
Changed in version 4.3: Additional site-specific configuration script introduced
Module cache¶
To improve module search efficiency, a module cache can be setup in each
modulepath. A module cache is represented by a .modulecache
file
stored at the root of modulepath directory. This file aggregates contents of
all valid modulercs and modulefiles and issue description of all
non-modulefiles stored in modulepath directory.
When cache file is available, a module search analyzes this file rather walking through the content of modulepath directory to check if files are modulefiles or not. Cache file reduces module search processing time especially when hundreds of modulefiles are available and if these files are located on busy storage systems. Having one file to read per modulepath rather walking through a whole directory content extremely reduces the number of required I/O operations.
When modulefiles or directories in the modulepath are not accessible for everyone, a limited access indication is recorded in cache file rather content of these modulefiles and content of these directories. When cache file containing such indication is processed, the limited access modulefiles are tested to check if they are available to the current running user. Limited access directories are walked down to find all available modulefiles and modulercs.
Cache files are generated with cachebuild
sub-command. This command
has to be run by someone who owns write access in modulepath directory to
create cache file.
Cache files are used any time a module search occurs in modulepaths. They are
analyzed for instance during avail
, load
,
display
or whatis
sub-commands.
Cache files are removed with cacheclear
sub-command. This command
has to be run by someone who own write access in modulepath directory to
effectively delete cache file.
EXIT STATUS¶
The module command exits with 0
if its execution succeed.
Otherwise 1
is returned.
ENVIRONMENT¶
-
__MODULES_AUTOINIT_INPROGRESS
¶ If set to
1
, theautoinit
sub-command process is skipped.This environment variable is set to
1
by theautoinit
sub-command after checking it is not set. It ensures no nested initialization of Modules occur. At the end of the processing of theautoinit
sub-command,__MODULES_AUTOINIT_INPROGRESS
is unset.New in version 5.0.
-
__MODULES_LMALTNAME
¶ A colon separated list of the alternative names set through
module-version
andmodule-alias
statements corresponding to all loaded modulefiles. Each element in this list starts by the name of the loaded modulefile followed by all alternative names resolving to it. The loaded modulefile and its alternative names are separated by the ampersand character.Each alternative name stored in
__MODULES_LMALTNAME
is prefixed by theal|
string if it corresponds to a module alias or prefixed by theas|
string if it corresponds to an automatic version symbol. These prefixes help to distinguish the different kind of alternative name.This environment variable is intended for module command internal use to get knowledge of the alternative names matching loaded modulefiles in order to keep environment consistent when conflicts or pre-requirements are set over these alternative designations. It also helps to find a match after modulefiles being loaded when
unload
,is-loaded
orinfo-loaded
actions are run over these names.Starting version 4.7 of Modules,
__MODULES_LMALTNAME
is also used onlist
sub-command to report the symbolic versions associated with the loaded modules.New in version 4.2.
Changed in version 5.0: Variable renamed from
MODULES_LMALTNAME
to__MODULES_LMALTNAME
-
__MODULES_LMCONFLICT
¶ A colon separated list of the
conflict
statements defined by all loaded modulefiles. Each element in this list starts by the name of the loaded modulefile declaring the conflict followed by the name of all modulefiles it declares a conflict with. These loaded modulefiles and conflicting modulefile names are separated by the ampersand character.This environment variable is intended for module command internal use to get knowledge of the conflicts declared by the loaded modulefiles in order to keep environment consistent when a conflicting module is asked for load afterward.
New in version 4.2.
Changed in version 5.0: Variable renamed from
MODULES_LMCONFLICT
to__MODULES_LMCONFLICT
-
__MODULES_LMINIT
¶ A colon separated list describing the modulepaths that have been enabled and the modulefiles that have been loaded with their tags during Modules initialization. Each element in this list corresponds to a collection definition line.
This environment variable is intended for module command internal use to get knowledge of the initial loaded state after initialization.
This initial environment state can then be restored with
reset
sub-command. It can also be restored withrestore
sub-command when__init__
collection name is specified or when no collection name is specified and no default collection exists.The content of the initial environment can be displayed with
saveshow
sub-command when__init__
collection name is specified or when no collection name is specified and no default collection exists.New in version 5.2.
-
__MODULES_LMPREREQ
¶ A colon separated list of the
prereq
statements defined by all loaded modulefiles. Each element in this list starts by the name of the loaded modulefile declaring the pre-requirement followed by the name of all modulefiles it declares aprereq
with. These loaded modulefiles and pre-required modulefile names are separated by the ampersand character. When aprereq
statement is composed of multiple modulefiles, these modulefile names are separated by the pipe character.This environment variable is intended for module command internal use to get knowledge of the pre-requirement declared by the loaded modulefiles in order to keep environment consistent when a pre-required module is asked for unload afterward.
New in version 4.2.
Changed in version 5.0: Variable renamed from
MODULES_LMPREREQ
to__MODULES_LMPREREQ
-
__MODULES_LMREFRESH
¶ A colon separated list of the loaded modules that are qualified for refresh evaluation. Loaded modules listed in this variable are those defining volatile environment changes like shell completion, alias and function.
New in version 5.2.
-
__MODULES_LMSOURCESH
¶ A colon separated list of the
source-sh
statements defined by all loaded modulefiles. Each element in this list starts by the name of the loaded modulefile declaring the environment changes made by the evaluation ofsource-sh
scripts. This name is followed by eachsource-sh
statement call and corresponding result achieved in modulefile. The loaded modulefile name and eachsource-sh
statement description are separated by the ampersand character. Thesource-sh
statement call and each resulting modulefile command (corresponding to the environment changes done by sourced script) are separated by the pipe character.This environment variable is intended for module command internal use to get knowledge of the modulefile commands applied for each
source-sh
command when loading the modulefile. In order to reverse these modulefile commands when modulefile is unloaded to undo the environment changes.New in version 4.6.
Changed in version 5.0: Variable renamed from
MODULES_LMSOURCESH
to__MODULES_LMSOURCESH
-
__MODULES_LMEXTRATAG
¶ A colon separated list of the tags corresponding to all loaded modulefiles that have been set through the
--tag
option. Each element in this list starts by the name of the loaded modulefile followed by all explicitly set tags applying to it. The loaded modulefile and its tags are separated by the ampersand character.This environment variable is intended for module command internal use to distinguish from all tags those that have been specifically set with
--tag
option.New in version 5.1.
-
__MODULES_LMTAG
¶ A colon separated list of the tags corresponding to all loaded modulefiles that have been set through
module-tag
statements or from other modulefile statements likemodule-forbid
(that may apply the nearly-forbidden tag in specific situation) (see Module tags section). Each element in this list starts by the name of the loaded modulefile followed by all tags applying to it. The loaded modulefile and its tags are separated by the ampersand character.This environment variable is intended for module command internal use to get knowledge of the tags applying to loaded modulefiles in order to report these tags on
list
sub-command output or to apply specific behavior when unloading modulefile.New in version 4.7.
Changed in version 5.0: Variable renamed from
MODULES_LMTAG
to__MODULES_LMTAG
-
__MODULES_LMVARIANT
¶ A colon separated list of the variant instantiated through
variant
statements by all loaded modulefiles (see Module variants section). Each element in this list starts by the name of the loaded modulefile followed by all the variant definitions set during the load of this module. The loaded modulefile and each of its variant definition are separated by the ampersand character. Each variant definition starts with the variant name, followed by the variant value set, then a flag to know if variant is of the Boolean type and last element in this definition is a flag to know if the chosen value is the default one for this variant and if it has been automatically set or not. These four elements composing the variant definition are separated by the pipe character.This environment variable is intended for module command internal use to get knowledge of the variant value defined by the loaded modulefiles in order to keep environment consistent when requirements are set over a specific variant value or just to report these variant values when listing loaded modules.
New in version 4.8.
Changed in version 5.0: Variable renamed from
MODULES_LMVARIANT
to__MODULES_LMVARIANT
-
__MODULES_PUSHENV_<VAR>
¶ Stack of saved values for
<VAR>
environment variable. A colon-separated list containing pairs of elements. A pair is formed by a loaded module name followed by the value set to<VAR>
in this module withpushenv
command. An ampersand character separates the two parts of the pair.First element in list corresponds to the lastly set value of
<VAR>
. If a value were set to<VAR>
prior the first evaluatedpushenv
command, this value is associated to an empty module name to record it as a pair element in__MODULES_PUSHENV_<VAR>
.New in version 5.1.
-
__MODULES_QUAR_<VAR>
¶ Value of environment variable
<VAR>
passed tomodulecmd.tcl
in order to restore<VAR>
to this value once started.New in version 4.1.
Changed in version 5.0: Variable renamed from
<VAR>_modquar
to__MODULES_QUAR_<VAR>
-
__MODULES_QUARANTINE_SET
¶ If set to
1
, restore the environment variables set on hold by the quarantine mechanism when startingmodulecmd.tcl
script. This variable is automatically defined by Modules shell initialization scripts or module shell function when they apply the quarantine mechanism. (seeMODULES_QUARANTINE_SUPPORT
).New in version 5.0.
-
__MODULES_SHARE_<VAR>
¶ Reference counter variable for path-like variable
<VAR>
. A colon separated list containing pairs of elements. A pair is formed by a path element followed its usage counter which represents the number of times this path has been enabled in variable<VAR>
. A colon separates the two parts of the pair.An element of a path-like variable is added to the reference counter variable as soon as it is added more than one time. When an element of a path-like variable is not found in the reference counter variable, it means this element has only be added once to the path-like variable.
When an empty string is added as an element in the path-like variable, it is added to the reference counter variable even if added only once to distinguish between an empty path-like variable and a path-like variable containing an empty string as single element.
New in version 4.0.
Changed in version 5.0: Variable renamed from
<VAR>_modshare
to__MODULES_SHARE_<VAR>
Changed in version 5.0: Elements are added to the reference counter variable only if added more than one time in the relative path-like variable
-
_LMFILES_
¶ A colon separated list of the full pathname for all loaded modulefiles.
This environment variable is generated by module command and should not be modified externally.
-
LOADEDMODULES
¶ A colon separated list of all loaded modulefiles.
This environment variable is generated by module command and should not be modified externally.
-
MODULECONTACT
¶ Email address to contact in case any issue occurs during the interpretation of modulefiles.
This environment variable value supersedes the default value set in the
contact
configuration option. It can be defined with theconfig
sub-command.New in version 4.0.
-
MODULEPATH
¶ The path that the module command searches when looking for modulefiles. Typically, it is set to the main modulefiles directory,
/usr/share/Modules/modulefiles
, by the initialization script.MODULEPATH
can be set usingmodule use
or by the module initialization script to search group or personal modulefile directories before or after the main modulefile directory.Path elements registered in the
MODULEPATH
environment variable may contain reference to environment variables which are converted to their corresponding value by module command each time it looks at theMODULEPATH
value. If an environment variable referred in a path element is not defined, its reference is converted to an empty string.
-
MODULERCFILE
¶ The location of a global run-command file containing modulefile specific setup. See Modulecmd startup section for detailed information.
This environment variable value supersedes the default value set in the
rcfile
configuration option. It can be defined with theconfig
sub-command.
-
MODULES_ADVANCED_VERSION_SPEC
¶ If set to
1
, enable advanced module version specifiers (see Advanced module version specifiers section). If set to0
, disable advanced module version specifiers.This environment variable value supersedes the default value set in the
advanced_version_spec
configuration option. It can be defined with theconfig
sub-command.New in version 4.4.
-
MODULES_AUTO_HANDLING
¶ If set to
1
, enable automated module handling mode. If set to0
disable automated module handling mode. Other values are ignored.Automated module handling mode consists in additional actions triggered when loading or unloading a modulefile to satisfy the constraints it declares. When loading a modulefile, following actions are triggered:
- Requirement Load: load of the modulefiles declared as a
prereq
of the loading modulefile. - Dependent Reload: reload of the modulefiles declaring a
prereq
onto loaded modulefile or declaring aprereq
onto a modulefile part of this reloading batch.
When unloading a modulefile, following actions are triggered:
- Dependent Unload: unload of the modulefiles declaring a non-optional
prereq
onto unloaded modulefile or declaring a non-optionalprereq
onto a modulefile part of this unloading batch. Aprereq
modulefile is considered optional if theprereq
definition order is made of multiple modulefiles and at least one alternative modulefile is loaded. - Useless Requirement Unload: unload of the
prereq
modulefiles that have been automatically loaded for either the unloaded modulefile, an unloaded dependent modulefile or a modulefile part of this useless requirement unloading batch. Modulefiles are added to this unloading batch only if they are not required by any other loaded modulefiles and if they are not taggedkeep-loaded
. - Dependent Reload: reload of the modulefiles declaring a
conflict
or an optionalprereq
onto either the unloaded modulefile, an unloaded dependent or an unloaded useless requirement or declaring aprereq
onto a modulefile part of this reloading batch.
In case a loaded modulefile has some of its declared constraints unsatisfied (pre-required modulefile not loaded or conflicting modulefile loaded for instance), this loaded modulefile is excluded from the automatic reload actions described above.
For the specific case of the
switch
sub-command, where a modulefile is unloaded to then load another modulefile. Dependent modulefiles to Unload are merged into the Dependent modulefiles to Reload that are reloaded after the load of the switched-to modulefile.This environment variable value supersedes the default value set on the
auto_handling
configuration option. It can be defined with theconfig
sub-command. The--auto
and--no-auto
command line switches override this environment variable.New in version 4.2.
Changed in version 5.1: Modules with keep-loaded tag set are excluded from Useless Requirement Unload mechanism
- Requirement Load: load of the modulefiles declared as a
-
MODULES_AVAIL_INDEPTH
¶ If set to
1
, enable in depth search results foravail
sub-command. If set to0
disableavail
sub-command in depth mode. Other values are ignored.When in depth mode is enabled, modulefiles and directories contained in directories matching search query are also included in search results. When disabled these modulefiles and directories contained in matching directories are excluded.
This environment variable value supersedes the default value set in the
avail_indepth
configuration option. It can be defined with theconfig
sub-command. The--indepth
and--no-indepth
command line switches override this environment variable.New in version 4.3.
-
MODULES_AVAIL_OUTPUT
¶ A colon separated list of the elements to report in addition to module names on
avail
sub-command regular output mode.Accepted elements that can be set in value list are:
alias
: module aliases.dirwsym
: directories associated with symbolic versions.key
: legend appended at the end of the output to explain it.modulepath
: modulepath names set as header prior the list of available modules found in them.sym
: symbolic versions associated with available modules.tag
: tags associated with available modules.variant
: variants and their possible values associated with available modules.variantifspec
: likevariant
but only if a variant has been specified in search query.
The order of the elements in the list does not matter. Module names are the only content reported when LIST is set to an empty value.
In case the
modulepath
element is missing from value list, the available modules from global/user rc and all enabled modulepaths are reported as a single list.This environment variable value supersedes the default value set in the
avail_output
configuration option. It can be defined with theconfig
sub-command. The--output
/-o
command line switches override this environment variable.New in version 4.7.
Changed in version 5.3: Elements
variant
andvariantifspec
added
-
MODULES_AVAIL_TERSE_OUTPUT
¶ A colon separated list of the elements to report in addition to module names on
avail
sub-command terse output mode.See
MODULES_AVAIL_OUTPUT
to get the accepted elements that can be set in value list.The order of the elements in the list does not matter. Module names are the only content reported when LIST is set to an empty value.
This environment variable value supersedes the default value set in the
avail_terse_output
configuration option. It can be defined with theconfig
sub-command. The--output
/-o
command line switches override this environment variable.New in version 4.7.
Changed in version 5.3: Elements
variant
andvariantifspec
added
-
MODULES_CACHE_BUFFER_BYTES
¶ Size of the buffer used when reading or writing cache files. Accepted values are integers comprised between 4096 and 1000000.
New in version 5.3.
-
MODULES_CACHE_EXPIRY_SECS
¶ Number of seconds a cache file is considered valid after being generated. For example, if set to
3600
it means a cache file expires one hour after being generated and is then ignored.When set to
0
cache file never expires. Accepted values are integers comprised between 0 (cache files never expire) and 31536000 (equivalent to one year duration).New in version 5.3.
-
MODULES_CMD
¶ The location of the active module command script.
This environment variable is generated by module command and should not be modified externally.
New in version 4.1.
-
MODULES_COLLECTION_PIN_VERSION
¶ If set to
1
, register exact version number of modulefiles when saving a collection. Otherwise modulefile version number is omitted if it corresponds to the explicitly set default version and also to the implicit default when the configuration optionimplicit_default
is enabled.This environment variable value supersedes the default value set in the
collection_pin_version
configuration option. It can be defined with theconfig
sub-command.New in version 4.1.
-
MODULES_COLLECTION_PIN_TAG
¶ If set to
1
, register all tags applying to modulefiles when saving a collection. Otherwise only the extra tags set through the--tag
option and tags resulting from specific module states (likeauto-loaded
andkeep-loaded
tags) are recorded in collection. Note that thenearly-forbidden
tag due to its temporal meaning is not saved in collection even when this configuration option is enabled.This environment variable value supersedes the default value set in the
collection_pin_tag
configuration option. It can be defined with theconfig
sub-command.New in version 5.1.
-
MODULES_COLLECTION_TARGET
¶ The collection target that determines what collections are valid thus reachable on the current system.
Collection directory may sometimes be shared on multiple machines which may use different modules setup. For instance modules users may access with the same
HOME
directory multiple systems using different OS versions. When it happens a collection made on machine 1 may be erroneous on machine 2.When a target is set, only the collections made for that target are available to the
restore
,savelist
,saveshow
,saverm
,stash
,stashpop
,stashlist
,stashshow
, andstashrm
sub-commands. Saving a collection registers the target footprint by suffixing the collection filename with.$MODULES_COLLECTION_TARGET
. The collection target is not involved when collection is specified as file path on thesaveshow
,restore
andsave
sub-commands.For example, the
MODULES_COLLECTION_TARGET
variable may be set with results from commands like lsb_release, hostname, dnsdomainname, etc.This environment variable value supersedes the default value set in the
collection_target
configuration option. It can be defined with theconfig
sub-command.New in version 4.0.
-
MODULES_COLOR
¶ Defines if output should be colored or not. Accepted values are
never
,auto
andalways
.When color mode is set to
auto
, output is colored only if the standard error output channel is attached to a terminal.This environment variable value supersedes the default value set in the
color
configuration option. It can be defined with theconfig
sub-command. The--color
command line switch overrides this environment variable.NO_COLOR
,CLICOLOR
andCLICOLOR_FORCE
environment variables are also honored to define color mode. Thenever
mode is set ifNO_COLOR
is defined (regardless of its value) or ifCLICOLOR
equals to0
. IfCLICOLOR
is set to another value, it corresponds to theauto
mode. Thealways
mode is set ifCLICOLOR_FORCE
is set to a value different than0
.NO_COLOR
variable prevails overCLICOLOR
andCLICOLOR_FORCE
. Color mode set with these three variables is superseded by mode set withMODULES_COLOR
environment variable or with--color
command line switch..New in version 4.3.
-
MODULES_COLORS
¶ Specifies the colors and other attributes used to highlight various parts of the output. Its value is a colon-separated list of output items associated to a Select Graphic Rendition (SGR) code. It follows the same syntax than
LS_COLORS
.Output items are designated by keys. Items able to be colorized are: highlighted element (
hi
), debug information (db
), trace information (tr
), tag separator (se
); Error (er
), warning (wa
), module error (me
) and info (in
) message prefixes; Modulepath (mp
), directory (di
), module alias (al
), module variant (va
), module symbolic version (sy
), moduledefault
version (de
) and modulefile command (cm
).Module tags can also be colorized. The key to set in the color palette to get a graphical rendering of a tag is the tag name or the tag abbreviation if one is defined for tag. The SGR code applied to a tag name is ignored if an abbreviation is set for this tag thus the SGR code should be defined for this abbreviation to get a graphical rendering. Each basic tag has by default a key set in the color palette, based on its abbreviated string: auto-loaded (
aL
), forbidden (F
), hidden and hidden-loaded (H
), loaded (L
), nearly-forbidden (nF
), sticky (S
), super-sticky (sS
) and keep-loaded (kL
).See the Select Graphic Rendition (SGR) section in the documentation of the text terminal that is used for permitted values and their meaning as character attributes. These substring values are integers in decimal representation and can be concatenated with semicolons. Modules takes care of assembling the result into a complete SGR sequence (
\33[...m
). Common values to concatenate include1
for bold,4
for underline,30
to37
for foreground colors and90
to97
for 16-color mode foreground colors. See also https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters for a complete SGR code reference.No graphical rendition will be applied to an output item that could normally be colored but which is not defined in the color set. Thus if
MODULES_COLORS
is defined empty, no output will be colored at all.This environment variable value supersedes the default value set in the
colors
configuration option. It can be defined with theconfig
sub-command.New in version 4.3.
Changed in version 4.6: Output item for trace information (
tr
) addedChanged in version 4.7: Output items for module tags auto-loaded (
aL
), forbidden (F
), hidden and hidden-loaded (H
), loaded (L
), nearly-forbidden (nF
), sticky (S
) and super-sticky (sS
) addedChanged in version 4.8: Output item for module variant (
va
) addedChanged in version 5.1: Output item for keep-loaded module tag (
kL
) added
-
MODULES_EDITOR
¶ Text editor command name or path for use to open modulefile through the
edit
sub-command.This environment variable value supersedes the default value set in the
editor
configuration option. It can be defined with theconfig
sub-command.Text editor could also be defined through the
VISUAL
orEDITOR
environment variables. These environment variables are overridden byMODULES_EDITOR
.New in version 4.8.
-
MODULES_EXTENDED_DEFAULT
¶ If set to
1
, a specified module version is matched against starting portion of existing module versions, where portion is a substring separated from the rest of the version string by a.
character. For example specified modulesmod/1
andmod/1.2
will match existing modulefilemod/1.2.3
.In case multiple modulefiles match the specified module version and a single module has to be selected, the explicitly set default version is returned if it is part of matching modulefiles. Otherwise the implicit default among matching modulefiles is returned if defined (see
MODULES_IMPLICIT_DEFAULT
section)This environment variable value supersedes the default value set in the
extended_default
configuration option. It can be defined with theconfig
sub-command.New in version 4.4.
-
MODULES_FAMILY_<NAME>
¶ Module name minus version that provides for the name family in currently loaded environment. This environment variable is defined through the use of the
family
modulefile command.For instance if loading modulefile
foo/1.0
defines being member of thebar
family, theMODULES_FAMILY_BAR
will be set to thefoo
value.This environment variable is generated by module command and should not be modified externally.
New in version 5.1.
-
MODULES_ICASE
¶ When module specification are passed as argument to module sub-commands or modulefile Tcl commands, defines the case sensitiveness to apply to match them. When
MODULES_ICASE
is set tonever
, a case sensitive match is applied in any cases. When set tosearch
, a case insensitive match is applied to theavail
,list
,whatis
,paths
andsavelist
sub-commands. When set toalways
, a case insensitive match is also applied to the other module sub-commands and modulefile Tcl commands for the module specification they receive as argument.This environment variable value supersedes the default value set in the
icase
configuration option. It can be defined with theconfig
sub-command. The--icase
/-i
command line switches, which correspond to thealways
mode, override this environment variable.New in version 4.4.
Changed in version 5.1: Search mode applied to
list
sub-commandChanged in version 5.2: Search mode applied to
savelist
sub-command
-
MODULES_IGNORE_CACHE
¶ Ignore (if set to
1
) or not (if set to0
) module cache.This environment variable value supersedes the default value set in the
ignore_cache
configuration option. It can be defined with theconfig
sub-command. The--ignore-cache
command line switch overrides this environment variable.New in version 5.3.
-
MODULES_IGNORE_USER_RC
¶ Skip evaluation (if set to
1
) or not (if set to0
) of user-specific module rc file ($HOME/.modulerc
).This environment variable value supersedes the default value set in the
ignore_user_rc
configuration option. It can be defined with theconfig
sub-command. The--ignore-user-rc
command line switch overrides this environment variable.New in version 5.3.
-
MODULES_IMPLICIT_DEFAULT
¶ Defines (if set to
1
) or not (if set to0
) an implicit default version for modules without a default version explicitly defined (see Locating Modulefiles section in the modulefile man page).Without either an explicit or implicit default version defined a module must be fully qualified (version should be specified in addition to its name) to get:
- targeted by module
load
,switch
,display
,help
,test
andpath
sub-commands. - restored from a collection, unless already loaded in collection-specified order.
- automatically loaded by automated module handling mechanisms (see
MODULES_AUTO_HANDLING
section) when declared as module requirement, withprereq
ormodule load
modulefile commands.
An error is returned in the above situations if either no explicit or implicit default version is defined.
This environment variable value supersedes the default value set in the
implicit_default
configuration option. It can be defined with theconfig
sub-command. This environment variable is ignored ifimplicit_default
has been declared locked inlocked_configs
configuration option.New in version 4.3.
- targeted by module
-
MODULES_IMPLICIT_REQUIREMENT
¶ Defines (if set to
1
) or not (if set to0
) an implicit prereq or conflict requirement onto modules specified respectively onmodule load
ormodule unload
commands in modulefile. When enabled an implicit conflict requirement onto switched-off module and a prereq requirement onto switched-on module are also defined formodule switch
commands used in modulefile.This environment variable value supersedes the default value set in the
implicit_requirement
configuration option. It can be defined with theconfig
sub-command. The--not-req
option, applied to amodule
command in a modulefile, overrides this environment variable.New in version 4.7.
-
MODULES_LIST_OUTPUT
¶ A colon separated list of the elements to report in addition to module names on
list
sub-command regular output mode.Accepted elements that can be set in value list are:
header
: sentence to introduce the list of loaded modules or to state that no modules are loaded currently.idx
: index position of each loaded module.key
: legend appended at the end of the output to explain it.variant
: variant values selected for loaded modules.sym
: symbolic versions associated with loaded modules.tag
: tags associated with loaded modules.
The order of the elements in the list does not matter. Module names are the only content reported when LIST is set to an empty value.
This environment variable value supersedes the default value set in the
list_output
configuration option. It can be defined with theconfig
sub-command. The--output
/-o
command line switches override this environment variable.New in version 4.7.
Changed in version 4.8: Element
variant
added
-
MODULES_LIST_TERSE_OUTPUT
¶ A colon separated list of the elements to report in addition to module names on
list
sub-command terse output mode.See
MODULES_LIST_OUTPUT
to get the accepted elements that can be set in value list.The order of the elements in the list does not matter. Module names are the only content reported when LIST is set to an empty value.
This environment variable value supersedes the default value set in the
list_terse_output
configuration option. It can be defined with theconfig
sub-command. The--output
/-o
command line switches override this environment variable.New in version 4.7.
Changed in version 4.8: Element
variant
added
-
MODULES_MCOOKIE_CHECK
¶ If set to
eval
, the Modules magic cookie (i.e.,#%Module
file signature) is only checked to determine if a file is a modulefile when evaluating these files. If set toalways
, the Modules magic cookie is also checked when searching for modules.The
eval
mode is made to significantly reduce file checks when walking through modulepaths to search for modulefiles. Special care should be given to the content of modulepaths when thiseval
mode is set as the following kind of files are included in search results:- modulefiles with a magic cookie requiring a higher version of
modulecmd.tcl
- files not beginning with the magic cookie
#%Module
- read-protected files
When a module cache file is available for a given modulepath,
eval
mode is not applied as cache content is generated inalways
mode.This environment variable value supersedes the default value set in the
mcookie_check
configuration option. It can be defined with theconfig
sub-command.New in version 5.1.
- modulefiles with a magic cookie requiring a higher version of
-
MODULES_MCOOKIE_VERSION_CHECK
¶ If set to
1
, the version set in the Modules magic cookie in modulefile is checked against the current version ofmodulecmd.tcl
to determine if the modulefile can be evaluated.When a module cache file is available for a given modulepath, version check is considered enabled as cache content is generated in this mode.
This environment variable value supersedes the default value set in the
mcookie_version_check
configuration option. It can be defined with theconfig
sub-command.New in version 4.7.
-
MODULES_ML
¶ If set to
1
, define ml command when initializing Modules (see Package Initialization section). If set to0
, ml command is not defined.This environment variable value supersedes the default value set in the
ml
configuration option. It can be defined with theconfig
sub-command.To enable or disable ml command,
MODULES_ML
should be set prior Modules initialization or theml
configuration option should be set in theinitrc
configuration file.New in version 4.5.
-
MODULES_NEARLY_FORBIDDEN_DAYS
¶ Number of days a module is considered nearly forbidden prior reaching its expiry date set by
module-forbid
modulefile command. When a nearly forbidden module is evaluated a warning message is issued to inform module will soon be forbidden. If set to0
, modules will never be considered nearly forbidden. Accepted values are integers comprised between 0 and 365.This environment variable value supersedes the default value set in the
nearly_forbidden_days
configuration option. It can be defined with theconfig
sub-command.New in version 4.6.
-
MODULES_PAGER
¶ Text viewer for use to paginate message output if error output stream is attached to a terminal. The value of this variable is composed of a pager command name or path eventually followed by command-line options.
This environment variable value supersedes the default value set in the
pager
configuration option. It can be defined with theconfig
sub-command.If
MODULES_PAGER
variable is set to an empty string or to the valuecat
, pager will not be launched.New in version 4.1.
-
MODULES_PROTECTED_ENVVARS
¶ A colon separated list of environment variable names that should not be modified by any modulefile command.
Prevents modifications by
append-path
,prepend-path
,remove-path
,setenv
andunsetenv
. When these modulefile commands attempt to modify a protected environment variable, a warning message is emitted and modification is ignored.This environment variable value supersedes the default value set in the
protected_envvars
configuration option. It can be defined with theconfig
sub-command.New in version 5.2.
-
MODULES_QUARANTINE_SUPPORT
¶ If set to
1
, produces the shell code for quarantine mechanism when theautoinit
sub-command generates the module shell function.The generated shell code for quarantine mechanism indirectly passes the environment variable defined in
MODULES_RUN_QUARANTINE
to themodulecmd.tcl
script to protect its run-time environment from side-effect coming from the current definition of these variables.To enable quarantine support,
MODULES_QUARANTINE_SUPPORT
should be set to1
prior Modules initialization or thequarantine_support
configuration should be set to1
in theinitrc
configuration file.Generated code for quarantine mechanism sets the
__MODULES_QUARANTINE_SET
environment variable when calling themodulecmd.tcl
script to make it restore the environment variable put in quarantine.This environment variable value supersedes the default value set in the
quarantine_support
configuration option. It can be defined with theconfig
sub-command.New in version 5.0.
-
MODULES_REDIRECT_OUTPUT
¶ If set to
0
, the output generated by module command is kept on stderr and not redirected to stdout channel.This environment variable value supersedes the default value set in the
redirect_output
configuration option. It can be defined with theconfig
sub-command. The--redirect
and--no-redirect
command line switches override this environment variable.New in version 5.1.
-
MODULES_RESET_TARGET_STATE
¶ Defines behavior of
reset
sub-command. When set to__init__
, initial environment is restored. When set to__purge__
,reset
performs apurge
sub-command. Any other value designates a name collection torestore
.This environment variable value supersedes the default value set in the
reset_target_state
configuration option. It can be defined with theconfig
sub-command.New in version 5.2.
-
MODULES_RUN_QUARANTINE
¶ A space separated list of environment variable names that should be passed indirectly to
modulecmd.tcl
to protect its run-time environment from side-effect coming from their current definition.If the quarantine mechanism has been included in module shell function (see
MODULES_QUARANTINE_SUPPORT
), each variable found inMODULES_RUN_QUARANTINE
will have its value emptied or set to the value of the correspondingMODULES_RUNENV_<VAR>
variable when definingmodulecmd.tcl
run-time environment.Original values of these environment variables set in quarantine are passed to
modulecmd.tcl
via__MODULES_QUAR_<VAR>
variables.This environment variable value supersedes the default value set in the
run_quarantine
configuration option. It can be defined with theconfig
sub-command.New in version 4.1.
-
MODULES_RUNENV_<VAR>
¶ Value to set to environment variable
<VAR>
formodulecmd.tcl
run-time execution if<VAR>
is referred inMODULES_RUN_QUARANTINE
.New in version 4.1.
-
MODULES_SEARCH_MATCH
¶ When searching for modules with
avail
sub-command, defines the way query string should match against available module names. Withstarts_with
value, returned modules are those whose name begins by search query string. When set tocontains
, any modules whose fully qualified name contains search query string are returned.This environment variable value supersedes the default value set in the
search_match
configuration option. It can be defined with theconfig
sub-command. The--starts-with
and--contains
command line switches override this environment variable.New in version 4.3.
-
MODULES_SET_SHELL_STARTUP
¶ If set to
1
, defines when module command initializes the shell startup file to ensure that the module command is still defined in sub-shells. Setting shell startup file means defining theENV
andBASH_ENV
environment variable to the Modules bourne shell initialization script. If set to0
, shell startup file is not defined.This environment variable value supersedes the default value set in the
set_shell_startup
configuration option. It can be defined with theconfig
sub-command.To enable shell startup file,
MODULES_SET_SHELL_STARTUP
should be set to1
prior Modules initialization or theset_shell_startup
configuration option should be set to1
in theinitrc
configuration file.New in version 4.3.
-
MODULES_SHELLS_WITH_KSH_FPATH
¶ A list of shell on which the
FPATH
environment variable should be defined at initialization time to point to theksh-functions
directory where the ksh initialization script for module command is located. It enables for the listed shells to get module function defined when starting ksh as sub-shell from there.Accepted values are a list of shell among sh, bash, csh, tcsh and fish separated by colon character (
:
).This environment variable value supersedes the default value set in the
shells_with_ksh_fpath
configuration option. It can be defined with theconfig
sub-command.To enable the setup of
FPATH
for some shells,MODULES_SHELLS_WITH_KSH_FPATH
should be set to the list of these shells prior Modules initialization or theshells_with_ksh_fpath
configuration option should be set to the list of these shells in theinitrc
configuration file.New in version 4.7.
-
MODULES_SILENT_SHELL_DEBUG
¶ If set to
1
, disable anyxtrace
orverbose
debugging property set on current shell session for the duration of either the module command or the module shell initialization script. Only applies to Bourne Shell (sh) and its derivatives.This environment variable value supersedes the default value set in the
silent_shell_debug
configuration option. It can be defined with theconfig
sub-command.To generate the code to silence shell debugging property in the module shell function,
MODULES_SILENT_SHELL_DEBUG
should be set to1
prior Modules initialization or thesilent_shell_debug
configuration option should be set to1
in theinitrc
configuration file.New in version 4.1.
-
MODULES_SITECONFIG
¶ Location of a site-specific configuration script to source into
modulecmd.tcl
. See Site-specific configuration section for details.This environment variable value supersedes the default value set in the
extra_siteconfig
configuration option. It can be defined with theconfig
sub-command. This environment variable is ignored ifextra_siteconfig
has been declared locked inlocked_configs
configuration option.New in version 4.3.
-
MODULES_TAG_ABBREV
¶ Specifies the abbreviation strings used to report module tags (see Module tags section). Its value is a colon-separated list of module tag names associated to an abbreviation string (e.g. tagname=abbrev).
If a tag is associated to an empty string abbreviation, this tag will not be reported. In case the whole
MODULES_TAG_ABBREV
environment variable is set to an empty string, tags are reported but not abbreviated.This environment variable value supersedes the default value set in the
tag_abbrev
configuration option. It can be defined with theconfig
sub-command.New in version 4.7.
-
MODULES_TAG_COLOR_NAME
¶ Specifies the tag names or abbreviations whose graphical rendering should be applied over themselves instead of being applied over the name of the module they are attached to. Value of
MODULES_TAG_COLOR_NAME
is a colon-separated list of module tag names or abbreviation strings (see Module tags section).When a select graphic rendition is defined for a tag name or a tag abbreviation string, it is applied over the module name associated with the tag and tag name or abbreviation is not displayed. When listed in
MODULES_TAG_COLOR_NAME
environment variable, a tag name or abbreviation is displayed and select graphic rendition is applied over it.This environment variable value supersedes the default value set in the
tag_color_name
configuration option. It can be defined with theconfig
sub-command.New in version 4.7.
-
MODULES_TCL_LINTER
¶ Command name or path for use to check syntax of modulefile through the
lint
sub-command.This environment variable value supersedes the default value set in the
tcl_linter
configuration option. It can be defined with theconfig
sub-command.New in version 5.2.
-
MODULES_TERM_BACKGROUND
¶ Inform Modules of the terminal background color to determine if the color set for dark background or the color set for light background should be used to color output in case no specific color set is defined with the
MODULES_COLORS
variable. Accepted values aredark
andlight
.This environment variable value supersedes the default value set in the
term_background
configuration option. It can be defined with theconfig
sub-command.New in version 4.3.
-
MODULES_TERM_WIDTH
¶ Specifies the number of columns of the output. If set to
0
, the output width will be the full terminal width, which is automatically detected by the module command. Accepted values are integers comprised between 0 and 1000.This environment variable value supersedes the default value set in the
term_width
configuration option. It can be defined with theconfig
sub-command. The--width
/-w
command line switches override this environment variable.New in version 4.7.
-
MODULES_UNLOAD_MATCH_ORDER
¶ When a module unload request matches multiple loaded modules, unload firstly loaded module or lastly loaded module. Accepted values are
returnfirst
andreturnlast
.This environment variable value supersedes the default value set in the
unload_match_order
configuration option. It can be defined with theconfig
sub-command.New in version 4.3.
-
MODULES_VARIANT_SHORTCUT
¶ Specifies the shortcut characters that could be used to specify and report module variants (see Module variants section). Its value is a colon-separated list of variant names associated to a shortcut character (e.g., variantname=shortcutchar).
A variant shortcut must be of one character length and must avoid characters used for other concerns or in module names (i.e., [-+~/@=a-zA-Z0-9]).
If a shortcut is associated to an empty string or an invalid character, this shortcut definition will be ignored.
This environment variable value supersedes the default value set in the
variant_shortcut
configuration option. It can be defined with theconfig
sub-command.New in version 4.8.
-
MODULES_VERBOSITY
¶ Defines the verbosity level of the module command. Available verbosity levels from the least to the most verbose are:
silent
: turn off error, warning and informational messages but does not affect module command output result.concise
: enable error and warning messages but disable informational messages.normal
: turn on informational messages, like a report of the additional module evaluations triggered by loading or unloading modules, aborted evaluation issues or a report of each module evaluation occurring during arestore
orsource
sub-commands.verbose
: add additional informational messages, like a systematic report of the loading or unloading module evaluations.verbose2
: report loading or unloading module evaluations of hidden-loaded modules, report if loading module is already loaded or if unloading module is not loaded.trace
: provide details on module searches, resolutions, selections and evaluations.debug
: print debugging messages about module command execution.debug2
: reportmodulecmd.tcl
procedure calls in addition to printing debug messages.
This environment variable value supersedes the default value set in the
verbosity
configuration option. It can be defined with theconfig
sub-command. The--silent
,--verbose
,--debug
and--trace
command line switches override this environment variable.New in version 4.3.
Changed in version 4.6: Verbosity levels
trace
anddebug2
addedChanged in version 4.7: Verbosity level
verbose2
added
-
MODULES_WA_277
¶ If set to
1
prior to Modules package initialization, enables workaround for Tcsh history issue (see https://github.com/cea-hpc/modules/issues/277). This issue leads to erroneous history entries under Tcsh shell. When workaround is enabled, an alternative module alias is defined which fixes the history mechanism issue. However the alternative definition of the module alias weakens shell evaluation of the code produced by modulefiles. Characters with a special meaning for Tcsh shell (like{
and}
) may not be used anymore in shell alias definition otherwise the evaluation of the code produced by modulefiles will return a syntax error.This environment variable value supersedes the default value set in the
wa_277
configuration option. It can be defined with theconfig
sub-command.To enable this workaround,
MODULES_WA_277
should be set to1
prior Modules initialization or thewa_277
configuration option should be set to1
in theinitrc
configuration file.New in version 4.3.
-
MODULESHOME
¶ The location of the main Modules package file directory containing module command initialization scripts, the executable program
modulecmd.tcl
, and a directory containing a collection of main modulefiles.This environment variable value supersedes the default value set in the
home
configuration option. It can be defined with theconfig
sub-command.
FILES¶
/usr/share/Modules
TheMODULESHOME
directory.
/etc/environment-modules/initrc
The configuration file evaluated by
modulecmd.tcl
when it initializes to enable the default modulepaths, load the default modules and set module command configuration.
initrc
is a modulefile so it is written as a Tcl script and defines modulepaths to enable withmodule use
, modules to load withmodule load
and configuration to apply withmodule config
. As any modulefileinitrc
must begin with the Modules magic cookie (i.e.,#%Module
file signature).
initrc
is optional. When this configuration file is present it is evaluated after themodulespath
configuration file. See the Package Initialization section for details.
/etc/environment-modules/modulespath
The configuration file evaluated by
modulecmd.tcl
when it initializes to enable the default modulepaths. This file contains the list of modulepaths separated by either newline or colon characters.
modulespath
is optional. When this configuration file is present it is evaluated before theinitrc
configuration file. See the Package Initialization section for details.
/etc/environment-modules/siteconfig.tcl
The site-specific configuration script ofmodulecmd.tcl
. An additional configuration script could be defined using theMODULES_SITECONFIG
environment variable. See Site-specific configuration for detailed information.
/etc/environment-modules/rc
The system-wide modules rc file. The location of this file can be changed using theMODULERCFILE
environment variable as described above.
$HOME/.modulerc
The user specific modules rc file.
$HOME/.module
The user specific collection directory.
/usr/share/Modules/modulefiles
The directory for system-wide modulefiles. The location of the directory can be changed using theMODULEPATH
environment variable as described above.
<modulepath>/.modulerc
Modulepath-specific module rc file.
<modulepath>/.modulecache
Modulepath-specific module cache file.
/usr/share/Modules/libexec/modulecmd.tcl
The modulefile interpreter that gets executed upon each invocation of module.
/usr/share/Modules/init/<shell>
The Modules package initialization file sourced into the user's environment.
SEE ALSO¶
modulefile¶
DESCRIPTION¶
modulefiles are written in the Tool Command Language, Tcl(n) and
are interpreted by the modulecmd.tcl
program via the module
user interface. modulefiles can be loaded, unloaded, or switched on-the-fly
while the user is working; and can be used to implement site policies
regarding the access and use of applications.
A modulefile begins with the #%Module
file signature, also called the
Modules magic cookie. A version number may be placed after this string. The
version number is useful as the modulefile format may change thus it
reflects the minimum version of modulecmd.tcl
required to interpret
the modulefile. If a version number doesn't exist, then modulecmd.tcl
will assume the modulefile is compatible. Files without the magic cookie or
with a version number greater than the current version of
modulecmd.tcl
will not be interpreted. If the
mcookie_version_check
configuration is disabled the version number
set is not checked.
Each modulefile contains the changes to a user's environment needed to access an application. Tcl is a simple programming language which permits modulefiles to be arbitrarily complex, depending upon the application's and the modulefile writer's needs. If support for extended tcl (tclX) has been configured for your installation of the Modules package, you may use all the extended commands provided by tclX, too.
A typical modulefile is a simple bit of code that set or add entries
to the PATH
, MANPATH
, or other environment variables. A
Modulefile is evaluated against current modulecmd.tcl
's mode which
leads to specific evaluation results. For instance if the modulefile sets a
value to an environment variable, this variable is set when modulefile is
loaded and unset when modulefile is unloaded.
Tcl has conditional statements that are evaluated when the modulefile is interpreted. This is very effective for managing path or environment changes due to different OS releases or architectures. The user environment information is encapsulated into a single modulefile kept in a central location. The same modulefile is used by every user on any machine. So, from the user's perspective, starting an application is exactly the same irrespective of the machine or platform they are on.
modulefiles also hide the notion of different types of shells. From the user's perspective, changing the environment for one shell looks exactly the same as changing the environment for another shell. This is useful for new or novice users and eliminates the need for statements such as "if you're using the C Shell do this ..., otherwise if you're using the Bourne shell do this ...". Announcing and accessing new software is uniform and independent of the user's shell. From the modulefile writer's perspective, this means one set of information will take care of every type of shell.
Modules Specific Tcl Commands¶
The Modules Package uses commands which are extensions to the "standard" Tool Command Language Tcl(n) package. Unless otherwise specified, the Module commands return the empty string. Some commands behave differently when a modulefile is loaded or unloaded. The command descriptions assume the modulefile is being loaded.
-
always-load
[--optional] [--tag taglist] modulefile...
¶ Load modulefile and apply the
keep-loaded
tag to it in order to avoid the automatic unload of this modulefile when modules dependent of it are unloaded.modulefile is declared as a requirement of currently loading module. This command acts as an alias of
module load
command. If more than one modulefile are specified, then this list acts as a Boolean AND operation, which means all specified modulefiles are required.When the
--optional
option is set, each specified modulefile is declared as an optional requirement. A modulefile that cannot be loaded, will not stop the evaluation.The
--tag
option accepts a list of module tags to apply to modulefile once loaded in addition to thekeep-loaded
tag. taglist corresponds to the concatenation of multiple tags separated by colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.New in version 5.1.
Changed in version 5.2: Option
--optional
added
-
append-path
[-d C|--delim C|--delim=C] [--duplicates] variable value...
¶ See
prepend-path
.
-
break
¶ This is not a Modules-specific command, it's actually part of Tcl, which has been overloaded similar to the
continue
andexit
commands to have the effect of causing the module not to be listed as loaded and not affect other modules being loaded concurrently. All non-environment commands within the module will be performed up to this point and processing will continue on to the next module on the command line. Thebreak
command will only have this effect if not used within a Tcl loop though.An example: Suppose that a full selection of modulefiles are needed for various different architectures, but some of the modulefiles are not needed and the user should be alerted. Having the unnecessary modulefile be a link to the following notavail modulefile will perform the task as required.
#%Module1.0 ## notavail modulefile ## proc ModulesHelp { } { puts stderr "This module does nothing but alert the user" puts stderr "that the [module-info name] module is not available" } module-whatis "Notifies user that module is not available." set curMod [module-info name] if { [ module-info mode load ] } { puts stderr "Note: '$curMod' is not available for [uname sysname]." } break
-
chdir
directory
¶ Set the current working directory to directory.
-
complete
shell name body
¶ Define shell completion for command name with specified body if shell is the current shell under which
modulecmd.tcl
was invoked. Body corresponds to argument options accepted by the shell command which defines completion. When a modulefile is unloaded,complete
becomesuncomplete
.The following shells are supported: bash, tcsh, bash and fish. Please refer to the documentation of these shells to learn how to define completion. The command is ignored if an unsupported shell is specified.
New in version 5.1.
-
conflict
modulefile...
¶ conflict
controls whether or not the modulefile will be loaded. Theconflict
command lists modulefiles which conflict with the current modulefile. If a list contains more than one modulefile, then each member of the list acts as a Boolean OR operation. Multipleconflict
commands may be used to create a Boolean AND operation. If one of the requirements have not been satisfied, an error is reported and the current modulefile makes no changes to the user's environment.If an argument for
conflict
is a directory and any other modulefile from that directory has been loaded, then a conflict will occur. For example, specifying X11 as aconflict
will stop X11/R4 and X11/R5 from being loaded at the same time.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
-
continue
¶ This is not a modules specific command but another overloaded Tcl command and is similar to the
break
orexit
commands except the module will be listed as loaded as well as performing any environment or Tcl commands up to this point and then continuing on to the next module on the command line. Thecontinue
command will only have this effect if not used within a Tcl loop though.
-
depends-on
[--optional] [--tag taglist] modulefile...
¶ Alias of
prereq-all
command.New in version 5.1.
Changed in version 5.2: Option
--optional
added
-
exit
[N]
¶ This is not a modules specific command but another overloaded Tcl command and is similar to the
break
orcontinue
commands. However, this command will cause the immediate cessation of this module and any additional ones on the command line. This module and the subsequent modules will not be listed as loaded. No environment commands will be performed in the current module.
-
family
name
¶ Defines loading modulefile as a member of family name. Only one member of a family could be loaded. Error is raised when attempting to load another member of the same family name.
family
corresponds to the definition of aconflict
on name and the definition of amodule-alias
name targeting currently loading module.In addition, the
MODULES_FAMILY_<NAME>
environment variable is defined and set to the currently loading module name minus version. This variable helps to know what module provides for the family name in the currently loaded environment. For instance if loading modulefilefoo/1.0
defines being member of thebar
family, theMODULES_FAMILY_BAR
will be set to thefoo
value. For compatibility, theLMOD_FAMILY_<NAME>
environment variable is also defined and set to the same value thanMODULES_FAMILY_<NAME>
.name should be a non-empty string only containing characters that could be part of an environment variable name (i.e., [a-zA-Z0-9_]).
New in version 5.1.
-
getenv
[--return-value] variable [value]
¶ Returns value of environment variable. If variable is not defined, value is returned if set, an empty string is returned otherwise. The
getenv
command should be preferred over the Tcl global variableenv
to query environment variables.When modulefile is evaluated in display mode,
getenv
returns variable name prefixed with dollar sign (e.g.,$variable
) unless if the--return-value
option is set. When this option is set the value of environment variable or defined fallback value is returned in display mode.New in version 4.0.
Changed in version 5.0: An empty string is returned instead of
_UNDEFINED_
when variable is not defined and no value is setChanged in version 5.1: Option
--return-value
added.
-
getvariant
[--return-value] variant [value]
¶ Returns value of designated variant. If variant is not defined, value is returned if set, an empty string is returned otherwise. The
getvariant
command should be preferred over theModuleVariant
Tcl array to query a variant value.When modulefile is evaluated in display mode,
getvariant
returns variant name enclosed in curly braces (e.g.,{variant}
) unless if the--return-value
option is set. When this option is set the value of variant or defined fallback value is returned in display mode.New in version 4.8.
Changed in version 5.1: Option
--return-value
added.
-
is-avail
modulefile...
¶ The
is-avail
command returns a true value if any of the listed modulefiles exists in enabledMODULEPATH
. If a list contains more than one modulefile, then each member acts as a boolean OR operation. If an argument foris-avail
is a directory and a modulefile exists in the directoryis-avail
would return a true value.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.1.
-
is-loaded
[modulefile...]
¶ The
is-loaded
command returns a true value if any of the listed modulefiles has been loaded or if any modulefile is loaded in case no argument is provided. If a list contains more than one modulefile, then each member acts as a boolean OR operation. If an argument foris-loaded
is a directory and any modulefile from the directory has been loadedis-loaded
would return a true value.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
-
is-saved
[collection...]
¶ The
is-saved
command returns a true value if any of the listed collections exists or if any collection exists in case no argument is provided. If a list contains more than one collection, then each member acts as a boolean OR operation.If
MODULES_COLLECTION_TARGET
is set, a suffix equivalent to the value of this variable is appended to the passed collection name. In case no collection argument is provided, a true value will only be returned if a collection matching currently set target exists.New in version 4.1.
-
is-used
[directory...]
¶ The
is-used
command returns a true value if any of the listed directories has been enabled inMODULEPATH
or if any directory is enabled in case no argument is provided. If a list contains more than one directory, then each member acts as a boolean OR operation.New in version 4.1.
-
module
[sub-command] [sub-command-options] [sub-command-args]
¶ This command permits a modulefile to
load
orunload
other modulefiles or touse
orunuse
modulepaths. No checks are made to ensure that the modulefile does not try to load itself. Often it is useful to have a single modulefile that performs a number ofmodule load
commands. For example, if every user on the system requires a basic set of applications loaded, then a core modulefile would contain the necessarymodule load
commands.The
--not-req
option may be set for theload
,try-load
,load-any
,unload
andswitch
sub-commands to inhibit the definition of an implicit prereq or conflict requirement onto specified modules.On
try-load
sub-command, if specified modulefile is not found thus loaded, no implicit prereq requirement is defined over this module.The
load-any
sub-command loads one modulefile from the specified list. An error is obtained if no modulefile from the list can be loaded. No operation is performed if a modulefile from the list is found already loaded.The
unuse
sub-command accepts the--remove-on-unload
,--noop-on-unload
,--append-on-unload
and--prepend-on-unload
options to control the behavior to apply when modulefile is unloaded. Seeremove-path
for further explanation.The
load
,try-load
,load-any
andswitch
sub-commands accept the--tag
option to apply specified tags to modulefile once loaded. Option accepts a concatenation of multiple module tags separated by colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.Command line switches
--auto
,--no-auto
and--force
are ignored when passed to amodule
command set in a modulefile.Not all the sub-commands described in the Module Sub-Commands section of the module man page are available when
module
is used as a Modules specific Tcl command. The following table summarizes the different sub-commands available for each interpretation context.Sub-commands available from modulefile interpretation Sub-commands available from initrc
configuration file and sourced script fileSub-commands available from run-command (rc) file interpretation load
,load-any
,switch
,try-load
,unload
,unuse
,use
. Also available but not recommended for use from regular modulefile:aliases
,avail
,display
,initadd
,initclear
,initlist
,initprepend
,initrm
,initswitch
,list
,purge
,reload
,restore
,save
,savelist
,saverm
,saveshow
,search
,test
,whatis
Same sub-commands available than for modulefile and config
sub-command.None Changed in version 4.7: Option
--not-req
added forload
,unload
andswitch
sub-commandsChanged in version 5.0:
source
sub-command is not allowed anymore andsource
Tcl command should be used insteadChanged in version 5.1: Options
--remove-on-unload
,--noop-on-unload
,--append-on-unload
and--prepend-on-unload
added foruse
sub-commandChanged in version 5.1: Option
--tag
added forload
,try-load
,load-any
andswitch
sub-commandsChanged in version 5.1: Option
--not-req
added fortry-load
andload-any
sub-commands
-
module-alias
name modulefile
¶ Assigns the modulefile to the alias name. This command should be placed in one of the
modulecmd.tcl
rc files in order to provide shorthand invocations of frequently used modulefile names.The parameter modulefile may be either
- a fully qualified modulefile with name and version
- a symbolic modulefile name
- another modulefile alias
-
module-forbid
[options] modulefile...
¶ Forbid use of modulefile. An error is obtained when trying to evaluate a forbidden module. This command should be placed in one of the
modulecmd.tcl
rc files.module-forbid
command accepts the following options:--after datetime
--before datetime
--not-user {user...}
--not-group {group...}
--message {text message}
--nearly-message {text message}
If
--after
option is set, forbidding is only effective after specified date time. Following the same principle, if--before
option is set, forbidding is only effective before specified date time. Accepted date time format isYYYY-MM-DD[THH:MM]
. If no time (HH:MM
) is specified,00:00
is assumed.--after
and--before
options are not supported on Tcl versions prior to 8.5.If
--not-user
option is set, forbidding is not applied if the username of the user currently runningmodulecmd.tcl
is part of the list of username specified. Following the same approach, if--not-group
option is set, forbidding is not applied if current user is member of one the group specified. When both options are set, forbidding is not applied if a match is found for--not-user
or--not-group
.Error message returned when trying to evaluate a forbidden module can be supplemented with the text message set through
--message
option.If
--after
option is set, modules are considered nearly forbidden during a number of days defined by thenearly_forbidden_days
modulecmd.tcl
configuration option (seeMODULES_NEARLY_FORBIDDEN_DAYS
), prior reaching the expiry date fixed by--after
option. When a nearly forbidden module is evaluated a warning message is issued to inform module will soon be forbidden. This warning message can be supplemented with the text message set through--nearly-message
option.If a
module-forbid
command applies to a modulefile also targeted by amodule-hide --hard
command, this module is unveiled when precisely named to return an access error.Forbidden modules included in the result of an
avail
sub-command are reported with aforbidden
tag applied to them. Nearly forbidden modules included in the result of anavail
or alist
sub-command are reported with anearly-forbidden
tag applied to them. See Module tags section in module.The parameter modulefile may leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.6.
-
module-hide
[options] modulefile...
¶ Hide modulefile to exclude it from available module search or module selection unless query refers to modulefile by its exact name. This command should be placed in one of the
modulecmd.tcl
rc files.module-hide
command accepts the following options:--soft|--hard
--hidden-loaded
--after datetime
--before datetime
--not-user {user...}
--not-group {group...}
When
--soft
option is set, modulefile is also set hidden, but hiding is disabled when search or selection query's root name matches module's root name. This soft hiding mode enables to hide modulefiles from bare module availability listing yet keeping the ability to select such module for load with the regular resolution mechanism (i.e., no need to use module exact name to select it)When
--hard
option is set, modulefile is also set hidden and stays hidden even if search or selection query refers to modulefile by its exact name.When
--hidden-loaded
option is set, hidden state also applies to the modulefile when it is loaded. Hidden loaded modules do not appear onlist
sub-command output, unless--all
option is set. Their loading or unloading informational messages are not reported unless theverbosity of Modules
is set to a level higher thanverbose
. Hidden loaded modules are detected in any cases by state query commands likeis-loaded
.If
--after
option is set, hiding is only effective after specified date time. Following the same principle, if--before
option is set, hiding is only effective before specified date time. Accepted date time format isYYYY-MM-DD[THH:MM]
. If no time (HH:MM
) is specified,00:00
is assumed.--after
and--before
options are not supported on Tcl versions prior to 8.5.If
--not-user
option is set, hiding is not applied if the username of the user currently runningmodulecmd.tcl
is part of the list of username specified. Following the same approach, if--not-group
option is set, hiding is not applied if current user is member of one the group specified. When both options are set, hiding is not applied if a match is found for--not-user
or--not-group
.If the
--all
option is set onavail
,aliases
,whatis
orsearch
sub-commands, hiding is disabled thus hidden modulefiles are included in module search. Hard-hidden modules (i.e., declared hidden with--hard
option) are not affected by--all
and stay hidden even if option is set.--all
option does not apply to module selection sub-commands likeload
. Thus in such context a hidden module should always be referred by its exact full name (e.g.,foo/1.2.3
notfoo
) unless if it has been hidden in--soft
mode. A hard-hidden module cannot be unveiled or selected in any case.If several
module-hide
commands target the same modulefile, the strongest hiding level is retained which means if both a regular, a--soft
hiding command match a given module, regular hiding mode is considered. If both a regular and a--hard
hiding command match a given module, hard hiding mode is retained. A set--hidden-loaded
option is retained even if themodule-hide
statement on which it is declared is superseded by a strongermodule-hide
statement with no--hidden-loaded
option set.Hidden modules included in the result of an
avail
sub-command are reported with ahidden
tag applied to them. Hidden loaded modules included in the result of alist
sub-command are reported with ahidden-loaded
tag applied to them. This tag is not reported onavail
sub-command context. See Module tags section in module.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
New in version 4.6.
Changed in version 4.7: Option
--hidden-loaded
added.
-
module-info
option [info-args]
¶ Provide information about the
modulecmd.tcl
program's state. Some of the information is specific to the internals ofmodulecmd.tcl
. option is the type of information to be provided, and info-args are any arguments needed.module-info alias name
Returns the full modulefile name to which the modulefile alias name is assignedmodule-info command [commandname]
Returns the currently running
modulecmd.tcl
's command as a string if no commandname is given.Returns
1
ifmodulecmd.tcl
's command is commandname. commandname can be:load
,unload
,refresh
,reload
,source
,switch
,display
,avail
,aliases
,list
,whatis
,search
,purge
,restore
,help
,test
,try-load
,load-any
,mod-to-sh
,reset
,stash
orstashpop
.New in version 4.0.
module-info loaded modulefile
Returns the names of currently loaded modules matching passed modulefile. The parameter modulefile might either be a fully qualified modulefile with name and version or just a directory which in case all loaded modulefiles from the directory will be returned. The parameter modulefile may also be a symbolic modulefile name or a modulefile alias.
This command only returns the name and version of designated loaded module. The defined variants of the loaded module are not included in the returned string.
New in version 4.1.
module-info mode [modetype]
Returns the current
modulecmd.tcl
's mode as a string if no modetype is given.Returns
1
ifmodulecmd.tcl
's mode is modetype. modetype can be:load
,unload
,remove
(alias ofunload
),switch
,refresh
,nonpersist
(alias ofrefresh
),display
,help
,test
,whatis
orscan
.module-info name
Return the name of the modulefile. This is not the full pathname for modulefile. See the Modules Variables section for information on the full pathname.
This command only returns the name and version of currently evaluating modulefile. The defined variants are not included in the returned string. See
getvariant
command orModuleVariant
array variable to get defined variant values for currently evaluating modulefile.module-info shell [shellname]
Return the current shell under which
modulecmd.tcl
was invoked if no shellname is given. The current shell is the first parameter ofmodulecmd.tcl
, which is normally hidden by the module alias.If a shellname is given, returns
1
ifmodulecmd.tcl
's current shell is shellname, returns0
otherwise. shellname can be:sh
,bash
,ksh
,zsh
,csh
,tcsh
,fish
,cmd
,tcl
,perl
,python
,ruby
,lisp
,cmake
,r
.module-info shelltype [shelltypename]
Return the family of the shell under which modulefile was invoked if no shelltypename is given. As of
module-info shell
this depends on the first parameter ofmodulecmd.tcl
. The output reflects a shell type determining the shell syntax of the commands produced bymodulecmd.tcl
.If a shelltypename is given, returns
1
ifmodulecmd.tcl
's current shell type is shelltypename, returns0
otherwise. shelltypename can be:sh
,csh
,fish
,cmd
,tcl
,perl
,python
,ruby
,lisp
,cmake
,r
.module-info specified
Return the module designation (name, version and variants) specified that led to current modulefile evaluation.module-info symbols modulefile
Returns a list of all symbolic versions assigned to the passed modulefile. The parameter modulefile might either be a full qualified modulefile with name and version, another symbolic modulefile name or a modulefile alias.module-info tags [tag]
Returns all tags assigned to currently evaluated modulefile as a list of strings if no tag name is given (see Module tags section in module)
When tags are assigned to specific module variants, they are returned only if this variant is the one currently evaluated.
Returns
1
if one of the tags applying to currently evaluated modulefile is tag. Returns0
otherwise.New in version 4.7.
module-info type
Returns eitherC
orTcl
to indicate which module command is being executed, either the C version or the Tcl-only version, to allow the modulefile writer to handle any differences between the two.module-info usergroups [name]
Returns all the groups the user currently running
modulecmd.tcl
is member of as a list of strings if no name is given.Returns
1
if one of the group current user runningmodulecmd.tcl
is member of is name. Returns0
otherwise.If the Modules Tcl extension library is disabled, the id(1) command is invoked to fetch groups of current user.
New in version 4.6.
module-info username [name]
Returns the username of the user currently running
modulecmd.tcl
as a string if no name is given.Returns
1
if username of current user runningmodulecmd.tcl
is name. Returns0
otherwise.If the Modules Tcl extension library is disabled, the id(1) command is invoked to fetch username of current user.
New in version 4.6.
module-info version modulefile
Returns the physical module name and version of the passed symbolic version modulefile. The parameter modulefile might either be a full qualified modulefile with name and version, another symbolic modulefile name or a modulefile alias.
-
module-tag
[options] tag modulefile...
¶ Associate tag to designated modulefile. This tag information will be reported along modulefile on
avail
andlist
sub-commands (see Module tags section in module). Tag information can be queried during modulefile evaluation with themodule-info tags
modulefile command.module-tag
commands should be placed in one of themodulecmd.tcl
rc files.module-tag
command accepts the following options:--not-user {user...}
--not-group {group...}
If
--not-user
option is set, the tag is not applied if the username of the user currently runningmodulecmd.tcl
is part of the list of username specified. Following the same approach, if--not-group
option is set, the tag is not applied if current user is member of one the group specified. When both options are set, the tag is not applied if a match is found for--not-user
or--not-group
.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
Tags inherited from other modulefile commands or module states cannot be set with
module-tag
. Otherwise an error is returned. Those special tags are:auto-loaded
,forbidden
,hidden
,hidden-loaded
,loaded
andnearly-forbidden
.When tag equals
sticky
orsuper-sticky
, designated modulefile is defined Sticky modules.When tag equals
keep-loaded
, designated modulefile is not automatically unloaded when it has been auto-loaded and its dependent modules are getting unloaded.New in version 4.7.
Changed in version 5.1: Tag
keep-loaded
added
-
module-version
modulefile version-name...
¶ Assigns the symbolic version-name to the modulefile. This command should be placed in one of the
modulecmd.tcl
rc files in order to provide shorthand invocations of frequently used modulefile names.The special version-name default specifies the default version to be used for module commands, if no specific version is given. This replaces the definitions made in the
.version
file in formermodulecmd.tcl
releases.The parameter modulefile may be either
- a fully or partially qualified modulefile with name / version. If
name is
.
(dot) then the current directory name is assumed to be the module name. (Use this for deep modulefile directories.) - a symbolic modulefile name
- another modulefile alias
- a fully or partially qualified modulefile with name / version. If
name is
-
module-virtual
name modulefile
¶ Assigns the modulefile to the virtual module name. This command should be placed in rc files in order to define virtual modules.
A virtual module stands for a module name associated to a modulefile. The modulefile is the script interpreted when loading or unloading the virtual module which appears or can be found with its virtual name.
The parameter modulefile corresponds to the relative or absolute file location of a modulefile.
New in version 4.1.
-
module-whatis
string
¶ Defines a string which is displayed in case of the invocation of the
module whatis
command. There may be more than onemodule-whatis
line in a modulefile. This command takes no actions in case ofload
,display
, etc. invocations ofmodulecmd.tcl
.The string parameter has to be enclosed in double-quotes if there's more than one word specified. Words are defined to be separated by whitespace characters (space, tab, cr).
-
prepend-path
[-d C|--delim C|--delim=C] [--duplicates] variable value...
¶ Append or prepend value to environment variable. The variable is a colon, or delimiter, separated list such as
PATH=directory:directory:directory
. The default delimiter is a colon:
, but an arbitrary one can be given by the--delim
option. For example a space can be used instead (which will need to be handled in the Tcl specially by enclosing it in" "
or{ }
). A space, however, can not be specified by the--delim=C
form.A reference counter environment variable is also set to know the number of times value has been added to environment variable when it is added more than one time. This reference counter environment variable is named by prefixing variable by
__MODULES_SHARE_
.When value is already defined in environment variable, it is not added again or moved at the end or at the beginning of variable. Exception is made when the
--duplicates
option is set in which case value is added again to variable.If the variable is not set, it is created. When a modulefile is unloaded,
append-path
andprepend-path
becomeremove-path
.If value corresponds to the concatenation of multiple elements separated by colon, or delimiter, character, each element is treated separately.
Changed in version 4.1: Option
--duplicates
added
-
prereq
[--optional] [--tag taglist] modulefile...
¶ prereq
controls whether or not the modulefile will be loaded. Theprereq
command lists modulefiles which must have been previously loaded before the current modulefile will be loaded. If a list contains more than one modulefile, then each member of the list acts as a Boolean OR operation. Multipleprereq
commands may be used to create a Boolean AND operation. If one of the requirements have not been satisfied, an error is reported and the current modulefile makes no changes to the user's environment.If an argument for
prereq
is a directory and any modulefile from the directory has been loaded, then the prerequisite is met. For example, specifying X11 as aprereq
means that any version of X11, X11/R4 or X11/R5, must be loaded before proceeding.The parameter modulefile may also be a symbolic modulefile name or a modulefile alias. It may also leverage a specific syntax to finely select module version (see Advanced module version specifiers section below).
When the
--optional
option is set, the whole list of specified modulefiles is declared as an optional requirement list. Evaluation is not stopped if no modulefile from the list is loaded.If the
auto_handling
configuration option is enabledprereq
will attempt to load specified modulefile if not found loaded yet (seeMODULES_AUTO_HANDLING
in module).The
--tag
option accepts a list of module tags to apply to modulefile once loaded. taglist corresponds to the concatenation of multiple tags separated by colon character. taglist should not contain tags inherited from modulefile state or from other modulefile commands. If module is already loaded, tags from taglist are added to the list of tags already applied to this module.Changed in version 4.2: An attempt to load modulefile is made if
auto_handling
configuration option is enabledChanged in version 5.1: Option
--tag
addedChanged in version 5.2: Option
--optional
added
-
prereq-all
[--optional] [--tag taglist] modulefile...
¶ Declare modulefile as a requirement of currently loading module. This command acts as an alias of
prereq
command. If more than one modulefile are specified, then this list acts as a Boolean AND operation, which means all specified modulefiles are required.When the
--optional
option is set, each specified modulefile is declared as an optional requirement. A modulefile that cannot be loaded, will not stop the evaluation.New in version 5.1.
Changed in version 5.2: Option
--optional
added
-
prereq-any
[--optional] [--tag taglist] modulefile...
¶ Alias of
prereq
command.New in version 5.1.
Changed in version 5.2: Option
--optional
added
-
pushenv
variable value
¶ Set environment variable to value and save previous value of variable to restore it when modulefile is unloaded. Like for
setenv
modulefile command, changes made to variable withpushenv
are applied to variable in Tcl'senv
array to update environment variable value in current evaluation context.When modulefile is unloaded, the value saved from the
pushenv
command of this modulefile is removed from saved value stack list. variable is then set to the remaining value on top of the stack or it is unset if stack becomes empty.Saved value stack list for variable is stored in an environment variable which is named by prefixing variable by
__MODULES_PUSHENV_
.New in version 5.1.
-
puts
[-nonewline] [channelId] string
¶ Writes the characters given by string to the channel given by channelId. This command is not a Modules-specific command, it is actually part of Tcl. See the puts(n) Tcl man page for a complete description of this command.
Content written to the
stderr
channel is rendered as output message produced by modulefile. Content written to thestdout
channel is rendered as shell command evaluated in the user current shell environment. Content sent tostdout
is spooled to be rendered after the environment changes made by modulefile.When channelId equals
prestdout
, content is rendered as shell command evaluated in current shell environment. This content is spooled and rendered prior any other environment changes.Changed in version 4.1: Content sent to
stdout
is spooled to apply it after the rendering of the environment changes made by modulefileChanged in version 5.1: Channel
prestdout
added to render content prior any other environment changes
-
remove-path
[options] variable value... [--append-on-unload|--prepend-on-unload value...]
¶ Remove value from the colon, or delimiter, separated list in variable.
remove-path
command accepts the following options:-d C|--delim C|--delim=C
--index
--remove-on-unload|--noop-on-unload|--append-on-unload|--prepend-on-unload
See
prepend-path
orappend-path
for further explanation of using an arbitrary delimiter. Every string between colons, or delimiters, in variable is compared to value. If the two match, value is removed from variable if its reference counter is equal to 1 or unknown.When
--index
option is set, value refers to an index in variable list. The string element pointed by this index is set for removal.When modulefile is unloaded, no operation is performed by default or if the
--noop-on-unload
option is set. If the--remove-on-unload
option is set, value is removed. If the--append-on-unload
option is set, append back value removed at load time or specific value if any set. If the--prepend-on-unload
option is set, prepend back value removed at load time or specific value if any set. These options cannot be set if--index
option is also set.Reference counter of value in variable denotes the number of times value has been added to variable. This information is stored in environment
__MODULES_SHARE_variable
. When attempting to remove value from variable, relative reference counter is checked and value is removed only if counter is equal to 1 or not defined. Otherwise value is kept in variable and reference counter is decreased by 1. If counter equals 1 after being decreased, value and its counter are removed from reference counter variable.If value corresponds to the concatenation of multiple elements separated by colon, or delimiter, character, each element is treated separately.
Changed in version 4.1: Option
--index
addedChanged in version 5.1: Options
--remove-on-unload
,--noop-on-unload
,--append-on-unload
and--prepend-on-unload
added
-
reportError
string
¶ Output string as an error message during modulefile evaluation and raise error count.
reportError
does not abort modulefile evaluation. Use the error(n) Tcl command to abort evaluation in addition to emit an error message.New in version 4.0.
-
reportWarning
string
¶ Output string as a warning message during modulefile evaluation.
New in version 4.0.
-
require-fullname
¶ Abort load evaluation of modulefile if name specified to designate it is not the fully qualified one. Module alias or a symbolic version names are considered fully qualified names, exception made for the default symbol.
New in version 5.1.
-
set-alias
alias-name alias-string
¶ Sets an alias with the name alias-name in the user's environment to the string alias-string. For some shells, aliases are not possible and the command has no effect (see Shell support section). When a modulefile is unloaded,
set-alias
becomesunset-alias
.
-
set-function
function-name function-string
¶ Creates a function with the name function-name in the user's environment with the function body function-string. For some shells, functions are not possible and the command has no effect (see Shell support section). When a modulefile is unloaded,
set-function
becomesunset-function
.New in version 4.2.
-
setenv
[--set-if-undef] variable value
¶ Set environment variable to value. The
setenv
command will also change the process' environment. A reference using Tcl's env associative array will reference changes made with thesetenv
command. Changes made using Tcl'senv
associative array will NOT change the user's environment variable like thesetenv
command. An environment change made this way will only affect the module parsing process. Thesetenv
command is also useful for changing the environment prior to theexec
orsystem
command. When a modulefile is unloaded,setenv
becomesunsetenv
. If the environment variable had been defined it will be overwritten while loading the modulefile. A subsequentunload
will unset the environment variable - the previous value cannot be restored! (Unless you handle it explicitly or if you use thepushenv
modulefile command instead ofsetenv
)When the
--set-if-undef
option is set, environment variable is defined when modulefile is loaded only if not yet defined.Changed in version 5.1: Option
--set-if-undef
added
-
source-sh
shell script [arg...]
¶ Evaluate with shell the designated script with defined arguments to find out the environment changes it does. Those changes obtained by comparing environment prior and after script evaluation are then translated into corresponding modulefile commands, which are then applied during modulefile evaluation as if they were directly written in it.
When modulefile is unloaded, environment changes done are reserved by evaluating in the
unload
context the resulting modulefile commands, which were recorded in the__MODULES_LMSOURCESH
environment variable atload
time.Changes on environment variables, shell aliases, shell functions, shell completions and current working directory are tracked.
Changes made on environment variable intended for Modules private use (e.g.,
LOADEDMODULES
,_LMFILES_
,__MODULES_*
) are ignored.Shell could be specified as a command name or a fully qualified pathname. The following shells are supported: sh, dash, csh, tcsh, bash, ksh, ksh93, zsh and fish.
New in version 4.6.
Changed in version 5.1: Changes on Modules private environment variable are ignored
Changed in version 5.1: Support for tracking shell completion changes on bash, tcsh and fish shells added
-
system
string
¶ Run string command through shell. On Unix, command is passed to the
/bin/sh
shell whereas on Windows it is passed tocmd.exe
.modulecmd.tcl
redirects stdout to stderr since stdout would be parsed by the evaluating shell. The exit status of the executed command is returned.
-
uname
field
¶ Provide lookup of system information. Most field information are retrieved from the
tcl_platform
array (see the tclvars(n) man page). Uname will return the stringunknown
if information is unavailable for the field.uname
will invoke the uname(1) command in order to get the operating system version and domainname(1) to figure out the name of the domain.field values are:
sysname
: the operating system namenodename
: the hostnamedomain
: the name of the domainrelease
: the operating system releaseversion
: the operating system versionmachine
: a standard name that identifies the system's hardware
-
uncomplete
name
¶ Unsets completion for command name in the user's environment. When a modulefile is unloaded, no operation is performed.
The following shells are supported: bash, tcsh and fish.
New in version 5.1.
-
unset-alias
alias-name
¶ Unsets an alias with the name alias-name in the user's environment.
-
unset-function
function-name
¶ Removes a function with the name function-name from the user's environment.
New in version 4.2.
-
unsetenv
[options] variable [value]
¶ Unsets environment variable. When a modulefile is unloaded, no operation is performed unless if an optional value is defined, in which case variable is to value. The
unsetenv
command changes the process' environment likesetenv
.If the
--noop-on-unload
option is set, no operation is performed when modulefile is unloaded. If the--unset-on-unload
option is set, environment variable is also unset when modulefile is unloaded. These behaviors are applied even if an optional value is defined.Changed in version 5.0: variable is not unset when unloading modulefile and no optional value is provided
Changed in version 5.1: Options
--noop-on-unload
and--unset-on-unload
added
-
variant
[--boolean] [--default value] name [value...]
¶ Declare module variant name with list of accepted value and instantiate it in the
ModuleVariant
array variable.Variant's value is selected through the module designation that leads to the modulefile evaluation. See Advanced module version specifiers section to learn how variants could be specified.
Selected variant value is transmitted to the evaluating modulefile. A value must be specified for variant name and it must corresponds to a value in the accepted value list if such list is defined. Otherwise an error is raised. An exception is made if modulefile is evaluated in
display
mode: no error is raised if no value is specified for a given variant and variant is not instantiated in theModuleVariant
array variable. When no list of accepted value is defined, variant could be set to any value.When the
--default
option is set, variant name is set to the value associated with this option in case no value is specified for variant in module designation.If the
--boolean
option is set, variant name is defined as a Boolean variant. No list of accepted value should be defined in this case. All values recognized as Boolean value in Tcl are accepted (i.e.,1
,true
,t
,yes
,y
,on
,0
,false
,f
,no
,n
oroff
). Boolean variants are instantiated inModuleVariant
using Tcl canonical form of Boolean value (i.e.,0
or1
).A variant which is not defined as a Boolean variant cannot define Boolean values in its accepted value list, exception made for the
0
and1
integers. An error is raised otherwise.A variant cannot be named
version
. An error is raised otherwise.New in version 4.8.
Changed in version 5.0: No error raised if a defined variant is not specified when modulefile is evaluated in
display
modeChanged in version 5.1: Accepted value list is made optional
-
versioncmp
version1 version2
¶ Compare version string version1 against version string version2. Returns
-1
,0
or1
respectively if version1 is less than, equal to or greater than version2.New in version 4.7.
-
x-resource
[resource-string|filename]
¶ Merge resources into the X11 resource database. The resources are used to control look and behavior of X11 applications. The command will attempt to read resources from filename. If the argument isn't a valid file name, then string will be interpreted as a resource. Either filename or resource-string is then passed down to be xrdb(1) command.
modulefiles that use this command, should in most cases contain one or more
x-resource
lines, each defining one X11 resource. TheDISPLAY
environment variable should be properly set and the X11 server should be accessible. Ifx-resource
can't manipulate the X11 resource database, the modulefile will exit with an error message.Examples:
x-resource /u2/staff/leif/.xres/Ileaf
The content of the Ileaf file is merged into the X11 resource database.x-resource [glob ~/.xres/ileaf]
The Tcl glob function is used to have the modulefile read different resource files for different users.x-resource {Ileaf.popup.saveUnder: True}
Merge the Ileaf resource into the X11 resource database.
Modulefiles and run-command (rc) files are differently interpreted. A limited number of the Modules specific Tcl commands are available for rc files interpretation since such files are intended to set parameters for modulefiles (like defining alias, hiding, tagging, etc) and not to change user environment. The following table summarizes the different commands available for each interpretation context.
Commands available from modulefile interpretation | Commands available from run-command (rc) file interpretation |
---|---|
All the Modules specific and standard Tcl commands | is-loaded , is-used ,
module-alias , module-forbid ,
module-hide , module-info ,
module-tag , module-version ,
module-virtual , system ,
uname , versioncmp and
standard Tcl commands |
Note
Global and user run-command files are interpreted like modulefiles and benefit from all Modules specific Tcl commands. However it not advised to perform environment changes from such files.
Modules Variables¶
-
ModulesCurrentModulefile
¶ The
ModulesCurrentModulefile
variable contains the full pathname of the modulefile being interpreted.
-
ModulesVersion
¶ The
ModulesVersion
variable can be set in.version
file to designate the name of the modulefile version which should be considered as default in current directory (see Locating Modulefiles section below).
-
ModuleTool
¶ The
ModuleTool
variable contains the name of the module implementation currently in use. The value of this variable is set toModules
for this implementation.New in version 4.7.
-
ModuleToolVersion
¶ The
ModuleToolVersion
variable contains the version of the module implementation currently in use. The value of this variable is set to5.3.0
for this version of Modules.New in version 4.7.
-
ModuleVariant
¶ The
ModuleVariant
array variable contains an element entry for each defined variant associated to the value of this variant (e.g., the$ModuleVariant(foo)
syntax corresponds to the value of variantfoo
if defined). A Tcl evaluation error is obtained when accessing an undefined variant inModuleVariant
array. Use preferably thegetvariant
command to retrieve a variant value when this variant state is not known.The list of the currently defined variants can be retrieved with
[array names ModuleVariant]
Tcl code.New in version 4.8.
Locating Modulefiles¶
Every directory in MODULEPATH
is searched to find the
modulefile. A directory in MODULEPATH
can have an arbitrary number
of sub-directories. If the user names a modulefile to be loaded which
is actually a directory, the directory is opened and a search begins for
an actual modulefile. First, modulecmd.tcl
looks for a file with
the name .modulerc
in the directory. If this file exists, its contents
will be evaluated as if it was a modulefile to be loaded. You may place
module-version
, module-alias
and module-virtual
commands inside this file.
Additionally, before seeking for .modulerc
files in the module
directory, the global modulerc file and the .modulerc
file found at
the root of the modulepath directory are sourced, too. If a named version
default now exists for the modulefile to be loaded, the assigned
modulefile now will be sourced. Otherwise the file .version
is
looked up in the module directory.
If the .version
file exists, it is opened and interpreted as Tcl code
and takes precedence over a .modulerc
file in the same directory. If
the Tcl variable ModulesVersion
is set by the .version
file,
modulecmd.tcl
will use the name as if it specifies a modulefile in
this directory. This will become the default modulefile in this case.
ModulesVersion
cannot refer to a modulefile located in a different
directory.
If ModulesVersion
is a directory, the search begins anew down that
directory. If the name does not match any files located in the current
directory, the search continues through the remaining directories in
MODULEPATH
.
Every .version
and .modulerc
file found is interpreted as Tcl
code. The difference is that .version
only applies to the current
directory, and the .modulerc
applies to the current directory and all
subdirectories. Changes made in these files will affect the subsequently
interpreted modulefile.
If a .modulecache
file is found at the root of a modulepath directory,
this file is interpreted as Tcl code to learn all .modulerc
,
.version
and modulefiles available. Modulepath content is read from
module cache file. Modulepath directory is only walked
through to check if limited access modulefiles or directories are available to
current user.
If no default version may be figured out, an implicit default is selected when
this behavior is enabled (see MODULES_IMPLICIT_DEFAULT
in
module). If disabled, module names should be fully qualified when no
explicit default is defined for them, otherwise no default version is found
and an error is returned. If enabled, then the highest numerically sorted
modulefile, virtual module or module alias under the directory will be used.
The dictionary comparison method of the lsort(n) Tcl command is
used to achieve this sort. If highest numerically sorted element is an alias,
search continues on its modulefile target.
For example, it is possible for a user to have a directory named X11 which
simply contains a .version
file specifying which version of X11 is to
be loaded. Such a file would look like:
#%Module1.0
##
## The desired version of X11
##
set ModulesVersion "R4"
The equivalent .modulerc
would look like:
#%Module1.0
##
## The desired version of X11
##
module-version "./R4" default
If the extended default mechanism is enabled (see
MODULES_EXTENDED_DEFAULT
in module) the module version
specified is matched against starting portion of existing module versions,
where portion is a substring separated from the rest of version string by a
.
character.
When the implicit default mechanism and the Advanced module version
specifiers are both enabled, a default
and latest
symbolic versions
are automatically defined for each module name (also at each directory level
in case of deep modulefile). Unless a symbolic version, alias, or regular
module version already exists for these version names.
Every file in searched directories is checked to see if it begins with the
Modules magic cookie (i.e., #%Module
file signature) to determine if it is
a modulefile (see DESCRIPTION section). When the mcookie_check
configuration is set to eval
, this check is skipped and all files in
search directories are considered modulefiles.
If user names a modulefile that cannot be found in the first modulepath directory, modulefile will be searched in next modulepath directory and so on until a matching modulefile is found. If search goes through a module alias or a symbolic version, this alias or symbol is resolved by first looking at the modulefiles in the modulepath where this alias or symbol is defined. If not found, resolution looks at the other modulepaths in their definition order.
When locating modulefiles, if a .modulerc
, a .version
, a
directory or a modulefile cannot be read during the search it is simply
ignored with no error message produced. Visibility of modulefiles can thus
be adapted to the rights the user has been granted. Exception is made when
trying to directly access a directory or a modulefile. In this case,
the access issue is returned as an error message.
Depending on their name, their file permissions or the use of specific modulefile commands, modulefile, virtual module, module alias or symbolic version may be set hidden which impacts available modules search or module selection processes (see Hiding modulefiles section below).
Hiding modulefiles¶
A modulefile, virtual module, module alias or symbolic version whose name or
element in their name starts with a dot character (.
) or who are targeted
by a module-hide
command are considered hidden. Hidden modules are
not displayed or taken into account except if they are explicitly named (e.g.,
foo/1.2.3
or foo/.2.0
not foo
). If module has been hidden with the
--soft
option of the module-hide
command set, it is not
considered hidden if the root name of the query to search it matches module
root name (e.g., searching foo
will return a foo/1.2.3
modulefile
targeted by a module-hide --soft
command). If module has been hidden with
the --hard
option of the module-hide
command set, it is always
considered hidden thus it is never displayed nor taken into account even if
it is explicitly named.
A modulefile, virtual module, module alias or symbolic version who are
targeted by a module-hide --hard
command and a
module-forbid
command or whose file access permissions are restricted
are considered hard-hidden and forbidden. Such modules are not displayed or
taken into account. When explicitly named for evaluation selection, such
modules are unveiled to return an access error.
Note
When the mcookie_check
configuration is set to eval
,
file access permissions are not checked thus files with restricted
permissions are included in search results but still lead to error if
evaluated.
A symbolic version-name assigned to a hidden module is displayed or taken into account only if explicitly named and if module is not hard-hidden. Non-hidden module alias targeting a hidden modulefile appears like any other non-hidden module alias. Finally, a hidden symbolic version targeting a non-hidden module is displayed or taken into account only if not hard-hidden and explicitly named to refer to its non-hidden target.
The automatic version symbols (e.g., default
and latest
) are
unaffected by hiding. Moreover when a regular default
or latest
version is set hidden, the corresponding automatic version symbol takes the
left spot. For instance, if foo/default
which targets foo/1.2.3
is set
hard-hidden, the default
automatic version symbol will be set onto
foo/2.1.3
, the highest available version of foo
.
When loading a modulefile or a virtual module targeted by a
module-hide --hidden-loaded
command, this module
inherits the hidden-loaded
tag. Hidden loaded modules are not reported
among list
sub-command results.
If the --all
is set on avail
, aliases
,
whatis
or search
sub-commands, hidden modules are taken
into account in search. Hard-hidden modules are unaffected by this option.
If the --all
is set on list
sub-command, hidden loaded
modules are included in result output.
Advanced module version specifiers¶
When the advanced module version specifiers mechanism is enabled (see
MODULES_ADVANCED_VERSION_SPEC
in module), the
specification of modulefile passed on Modules specific Tcl commands changes.
After the module name a version constraint and variants may be added.
Version specifiers¶
After the module name a version constraint prefixed by the @
character may
be added. It could be directly appended to the module name or separated from
it with a space character.
Constraints can be expressed to refine the selection of module version to:
- a single version with the
@version
syntax, for instancefoo@1.2.3
syntax will select modulefoo/1.2.3
- a list of versions with the
@version1,version2,...
syntax, for instancefoo@1.2.3,1.10
will match modulesfoo/1.2.3
andfoo/1.10
- a range of versions with the
@version1:
,@:version2
and@version1:version2
syntaxes, for instancefoo@1.2:
will select all versions of modulefoo
greater than or equal to1.2
,foo@:1.3
will select all versions less than or equal to1.3
andfoo@1.2:1.3
matches all versions between1.2
and1.3
including1.2
and1.3
versions
Advanced specification of single version or list of versions may benefit from
the activation of the extended default mechanism (see
MODULES_EXTENDED_DEFAULT
in module) to use an abbreviated
notation like @1
to refer to more precise version numbers like 1.2.3
.
Range of versions on its side natively handles abbreviated versions.
In order to be specified in a range of versions or compared to a range of
versions, the version major element should corresponds to a number. For
instance 10a
, 1.2.3
, 1.foo
are versions valid for range
comparison whereas default
or foo.2
versions are invalid for range
comparison.
Range of versions can be specified in version list, for instance
foo@:1.2,1.4:1.6,1.8:
. Such specification helps to exclude specific
versions, like versions 1.3
and 1.7
in previous example.
If the implicit default mechanism is also enabled (see
MODULES_IMPLICIT_DEFAULT
in module), a default
and
latest
symbolic versions are automatically defined for each module name
(also at each directory level for deep modulefiles). These automatic version
symbols are defined unless a symbolic version, alias, or regular module
version already exists for these default
or latest
version names.
Using the mod@latest
(or mod/latest
) syntax ensures highest available
version will be selected.
Variants¶
After the module name, variants can be specified. Module variants are
alternative evaluation of the same modulefile. A variant is specified by
associating a value to its name. This specification is then transmitted to the
evaluating modulefile which instantiates the variant in the
ModuleVariant
array variable when reaching the variant
modulefile command declaring this variant.
Variant can be specified with the name=value
syntax where name is the
declared variant name and value, the value this variant is set to when
evaluating the modulefile.
Boolean variants can be specified with the +name
syntax to set this
variant on and with the -name
or ~name
syntaxes to set this variant
off. The -name
syntax is not supported on ml command as the
minus sign already means to unload designated module. The ~name
and
+name
syntaxes could also be defined appended to another specification
word (e.g., the module name, version or another variant specification),
whereas -name
syntax must be the start of a new specification word.
Boolean variants may also be specified with the name=value
syntax. value
should be set to 1
, true
, t
, yes
, y
or on
to enable
the variant or it should be set to 0
, false
, f
, no
, n
or
off
to disable the variant.
Shortcuts may be used to abbreviate variant specification. The
variant_shortcut
configuration option associates shortcut character
to variant name. With a shortcut defined, variant could be specified with the
<shortcut>value
syntax. For instance if character %
is set as a
shortcut for variant foo
, the %value
syntax is equivalent to the
foo=value
syntax.
Specific characters used in variant specification syntax cannot be used as
part of the name of a module. These specific characters are +
, ~
,
=
and all characters set as variant shortcut. Exception is made for +
character which could be set one or several consecutive times at the end of
module name (e.g., name+ or name++).
New in version 4.4.
Changed in version 4.8: Use of version range is allowed in version list
Changed in version 4.8: Support for module variant added
Dependencies between modulefiles¶
A modulefile may express dependencies on other modulefiles. Two kind of dependency exist: pre-requirement and conflict. The former means specified modulefiles should be loaded prior the modulefile that express the requirement. The latter means specified modulefiles should not be loaded for the modulefile that express the conflict to be loaded too.
Pre-requirement could be expressed with prereq
, prereq-any
,
prereq-all
, depends-on
, always-load
,
module load
, module switch
,
module try-load
or module load-any
modulefile commands. When the auto_handling
configuration option is
disabled, required modulefile should be manually loaded prior their dependent
modulefile when expressed with the prereq
, prereq-any
,
prereq-all
or depends-on
modulefile commands. For other
commands or when auto_handling
is enabled, pre-required modulefiles
are automatically loaded.
Conflict is expressed with conflict
or module unload
modulefile commands. A conflicting loaded modulefile should be manually
unloaded prior loading the modulefile that express such conflict when defined
with conflict
. It is automatically unloaded when expressed with
module unload
.
It is strongly advised to define dependencies prior environment changes in a
modulefile. Dependency resolution should be done before any environment change
to ensure the environment is getting set in the same order whether
pre-requirements are already loaded, or if they are automatically loaded when
loading the modulefile which depends on them, or if all loaded modules are
reloaded or refreshed. This is especially important when the modulefile
updates an environment variable also altered by other modulefiles like
PATH
. As the order of the path elements in such variable defines
priority, it is important that this order does not change depending on the way
the modulefiles are loaded.
module keeps environment consistent which means a modulefile cannot
be loaded if its requirements are not loaded or if a conflicting module is
loaded. In addition a loaded module cannot be unloaded if other loaded modules
depends on it. The automated module handling
mechanisms
attempt to solve the dependencies expressed
by loading or unloading additional modulefiles. When the --no-auto
option is set on module command when loading or unload modulefile,
automated module handling mechanisms are disabled and dependencies have to be
solved manually. When dependencies are not satisfied, modulefile fails to load
or unload.
Adding the --not-req
option when expressing dependencies in modulefile
with the module
command will attempt to load or unload the designated
modulefile but it will not mark them as pre-requirement or conflict.
Adding the --optional
option on prereq
, prereq-any
,
prereq-all
, depends-on
or always-load
modulefile
commands declares the pre-requirement as optional. If an optional
pre-requirement is not found loaded or cannot be automatically loaded, the
dependency expressed is yet considered satisfied. When an optional requirement
is loaded afterward, the dependent module will get automatically reloaded if
the auto_handling
configuration option is enabled.
By adding the --force
option to the module command when
loading or unloading modulefile, the consistency checks are by-passed. This
option cannot be used when expressing dependencies in modulefiles. If a module
has been force loaded whereas its requirements are not loaded or whereas a
conflicting module is also loaded, the user environment is said inconsistent.
Note that a pre-requirement should be found in the loaded module list prior its dependent module. User environment is considered inconsistent if pre-requirement module is found loaded after dependent module, as the environment changes may have been done in the wrong priority order.
When user environment is considered inconsistent global operations achieved by
refresh
, reload
and save
sub-commands cannot
perform. This mechanism is there to avoid the situation to worsen by
re-evaluating all loaded modules or recording this environment.
When the auto_handling
configuration option is enabled, if missing
pre-requirement modulefile gets loaded or conflicting modulefile gets unloaded
the inconsistent loaded module will be automatically reloaded to make user
environment consistent again.
Modulefile Specific Help¶
Users can request help about a specific modulefile through the
module command. The modulefile can print helpful information or
start help oriented programs by defining a ModulesHelp
subroutine. The
subroutine will be called when the module help modulefile
command is used.
Modulefile Specific Test¶
Users can request test of a specific modulefile through the module
command. The modulefile can perform some sanity checks on its
definition or on its underlying programs by defining a ModulesTest
subroutine. The subroutine will be called when the
module test modulefile
command is used. The subroutine should
return 1 in case of success. If no or any other value is returned, test is
considered failed.
Modulefile Display¶
The module display modulefile
command will detail all
changes that will be made to the environment. After displaying all of the
environment changes modulecmd.tcl
will call the ModulesDisplay
subroutine. The ModulesDisplay
subroutine is a good place to put
additional descriptive information about the modulefile.
Compatibility with Lmod Tcl modulefile¶
The modulecmd.tcl
program supports Tcl modulefile written for Lmod,
the alternative module implementation developed in Lua. Such
modulefiles can be evaluated by Modules without raising error. Differences
between the two implementations are listed below.
The add-property
, remove-property
and extensions
modulefile
commands are evaluated as a no-operation command. No error is obtained if
these commands are used in modulefiles but no change occurs.
The break
command does not accept any argument. A msg
argument
can be set on Lmod to provide a customized break error message.
Use of reportError
command aborts modulefile evaluation on Lmod. This
command only reports an error message on Modules.
The require-fullname
command only aborts load modulefile evaluation
whereas the Lmod implementation also aborts unload and display
evaluations.
When processing a family
command, the LMOD_FAMILY_<NAME>
environment variable is also defined to be compatible with modulefiles or
scripts relying on such variable.
When unloading a modulefile, the pushenv
command does not update the
value of the environment variable if this modulefile was not defining the
value currently in use.
The third optional argument of append-path
and prepend-path
commands corresponds to a priority specification on Lmod whereas these two
commands accept multiple path element arguments on Modules.
The prereq
command is equivalent to the prereq-any
command
on Modules whereas on Lmod it is equivalent to the prereq-all
command.
If the auto_handling
configuration option is disabled, the
requirements defined with the depends-on
command are not
automatically loaded and an error is raised if none of these requirements are
found loaded.
On module load-any
sub-command and modulefile command, a
modulefile evaluation error is not reported and module
load-any
continues to the next modulefile instead of aborting the
whole process. No attempt to load listed modulefiles is made if one of these
modulefiles is found already loaded.
On module try-load
modulefile command, each modulefile
specified is considered an optional pre-requirement. If it is loaded
afterward and if the auto_handling
configuration option is enabled,
the dependent module will get automatically reloaded.
Shell support¶
The modulecmd.tcl
program that evaluates modulefiles supports a
variety of shells or languages: sh family shells (sh, bash, ksh and
zsh), csh family shells (csh and tcsh), fish, cmd, python,
perl, ruby, tcl, cmake, r, and lisp.
Modulefiles produce environment changes when evaluated, like defining an
environment variable. The modulecmd.tcl
program outputs the
corresponding code for the selected "shell". Thereafter this code is evaluated
by the module alias or function to update the current environment.
Depending on the "shell" kind, not all the environment changes that can be
defined in modulefiles are supported. The following table summarizes the
changes that are supported by the shells supported by modulecmd.tcl
.
Environment variables
(setenv ,
unsetenv ,
pushenv ,
append-path ,
prepend-path ,
remove-path ) |
Shell alias
(set-alias ,
unset-alias ) |
Shell functions
(set-function ,
unset-function ) |
Command completion
(complete ,
uncomplete ) |
chdir |
x-resource |
|
sh | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | |
bash | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ |
ksh | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | |
zsh | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | |
csh | ⦁ | ⦁ | ⦁ | ⦁ | ||
tcsh | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | |
fish | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ | ⦁ |
cmd | ⦁ | ⦁ | ⦁ | |||
python | ⦁ | ⦁ | ⦁ | |||
perl | ⦁ | ⦁ | ⦁ | |||
ruby | ⦁ | ⦁ | ⦁ | |||
tcl | ⦁ | ⦁ | ⦁ | |||
cmake | ⦁ | ⦁ | ||||
r | ⦁ | ⦁ | ⦁ | |||
lisp | ⦁ | ⦁ | ⦁ |
The source-sh
command evaluates a shell script and produces the
modulefile commands corresponding to the environment changes made by this
script. source-sh
is able to evaluate sh, bash, ksh, zsh,
csh, tcsh and fish shell scripts. source-sh
produces
environment changes corresponding to the kinds listed in the above table.
Based on the evaluated script, refer to the above table to know the
environment changes that will be rendered for the shell specified to
modulecmd.tcl
program.
ENVIRONMENT¶
See the ENVIRONMENT section in the module man page.
SEE ALSO¶
module, ml, Tcl(n), TclX(n), id(1), xrdb(1), exec(n), uname(1), domainname(1), tclvars(n), lsort(n)
NOTES¶
Tcl was developed by John Ousterhout at the University of California at Berkeley.
TclX was developed by Karl Lehenbauer and Mark Diekhans.
Contributing¶
Thank you for considering contributing to Modules!
Support questions¶
Please use the modules-interest mailing list for questions. Do not use the issue tracker for this.
Asking for new features¶
Please submit your new feature wishes first to the modules-interest mailing list. Discussion will help to clarify your needs and sometimes the wanted feature may already be available.
Reporting issues¶
- Describe what you expected to happen.
- If possible, include a minimal, complete, and verifiable example to help us identify the issue.
- Describe what actually happened. Run the
module
command in--debug
mode and include all the debug output obtained in your report. - Provide the current configuration and state of your Modules installation by
running the
module config --dump-state
command. - Provide the name and content of the modulefiles you try to manipulate.
Submitting patches¶
- Whether your patch is supposed to solve a bug or add a new feature, please include tests. In case of a bug, explain clearly under which circumstances it happens and make sure the test fails without your patch.
- If you are not yet familiar with the
git
command and GitHub, please read the don't be afraid to commit tutorial.
Start coding¶
- Create a branch to identify the issue or feature you would like to work on
- Using your favorite editor, make your changes, committing as you go.
- Comply to the coding conventions of this project.
- Your Tcl code has to be compatible with Tcl version 8.5 and above (see Tcl 8.5 commands reference)
- Include tests that cover any code changes you make. Make sure the test fails without your patch.
- Run the tests and verify coverage.
- Push your commits to GitHub and create a pull request.
Design notes¶
See the Design notes for recent feature specifications. You may also find there some development howtos:
Running the tests¶
Run the basic test suite with:
make test
This only runs the tests for the current environment. GitHub Actions and Cirrus CI will run the full suite when you submit your pull request.
There are more than 17 000 test cases thus it generally takes around 12 minutes to run the full test suite. It can be executed in quick mode to just run the most essential tests in about 1 minute:
make test QUICKTEST=y
The script/mt utility is also available to just execute one or
several testfiles. If a test fails, script/mt reports the diff
comparison between expected and actual results. For instance, to only
execute testsuite/modules.50-cmds/470-variant.exp
testfile, run:
script/mt 50/470
Run script/mt with --help
option to get usage details and
syntax to select several testfiles.
Running test coverage¶
Generating a report of lines that do not have test coverage can indicate where to start contributing or what your tests should cover for the code changes you submit.
Run make test COVERAGE=y
which will automatically setup the Nagelfar
Tcl code coverage tool in your modules
development directory and
instrument the source Tcl scripts. Then the full testsuite will be run in
coverage mode and an annotated script will be produced for each Tcl script in
tcl
source directory (tcl/*.tcl_m
):
make test COVERAGE=y
# then open tcl/*.tcl_m files and look for ';# Not covered' lines
The script/mt utility may also be used to run the test suite in coverage mode on full testsuite or on a few testfiles:
script/mt cov 70/{280,290}
Running linter tests¶
Linter tools check code syntax and report issues and good practices to follow. Modules uses Nagelfar to check syntax of Tcl scripts and ShellCheck to lint sh, bash and ksh scripts.
Run make testlint
to lint all sh, bash, ksh and Tcl scripts in your local
Modules repository.
The script/mt utility may also be used to run the full lint test suite or just specific testfiles. For instance to only lint Tcl scripts:
script/mt lint 00/030
Check performances¶
The script/mb utility checks from your local repository the performances of major releases of Modules and current branch. Current ongoing modifications are first stashed, then modulecmd.tcl of the releases and current branch are built. Different tests are run against each version and the execution time of each test is reported in millisecond:
$ script/mb
| v4.1.4 | v4.3.1 | v4.5.3 | v4.7.1 | v5.1.1 | main |
----------+----------+----------+----------+----------+----------+----------+
help | 9 | 12 | 12 | 15 | 16 | 16 |
avail | 61 | 67 | 76 | 82 | 91 | 86 |
avail2 | 11 | 16 | 19 | 21 | 23 | 23 |
avail3 | - | - | - | 120 | 128 | 130 |
whatis | 208 | 155 | 233 | 216 | 221 | 224 |
whatis2 | 10 | 15 | 17 | 20 | 21 | 22 |
whatis3 | - | - | - | 287 | 307 | 314 |
apropos | 208 | 153 | 222 | 210 | 220 | 223 |
load | 66 | 87 | 134 | 162 | 120 | 126 |
list | 24 | 23 | 33 | 22 | 25 | 25 |
unload | 46 | 24 | 25 | 29 | 31 | 31 |
It helps to verify that current work committed in local repository does not
impact performances on simple test scenarios. Run script/mb with
--help
option to get its usage details.
The profile
mode may also be interesting to learn what are the internal
procedures of modulecmd.tcl taking most of the execution time for
each test:
script/mb profile
Building the docs¶
Build the docs in the doc
directory using Sphinx:
cd doc
make html
Open _build/html/index.html
in your browser to view the docs.
Read more about Sphinx.
Coding conventions¶
Maximum line length is 78 characters
Use 3 spaces to indent code (do not use tab character)
Procedure names:
lowerCameCase
Variable names:
nocaseatall
Curly brace and square bracket placement:
if {![isStateDefined already_report]} { setState already_report 1 }
Commit hooks¶
A pre-commit hook script is provided in the script
directory of the project to help you check that the contribution made is free
of misspellings and trailing spaces. It requires the codespell utility that
checks for typos in any kind of files and the Aspell utility that spell
checks documentation files. The pre-commit could be enabled in your
local repository with following command:
ln -s ../../script/pre-commit .git/hooks/pre-commit
A commit-msg hook script is also provided in the script
directory of the project to help you check that your commit messages are free
of misspellings. It requires the Aspell utility and could be enabled in
your local repository with following command:
ln -s ../../script/commit-msg .git/hooks/commit-msg
Emacs settings for coding conventions¶
This is an example Emacs configuration that adheres to the first two
coding conventions. You may wish to add this to your .emacs
or
.emacs.d/
to modify your tcl-mode:
(add-hook 'tcl-mode-hook
(lambda ()
(setq indent-tabs-mode nil)
(setq tcl-indent-level 3)
(setq tcl-continued-indent-level 3)
(font-lock-add-keywords nil '(("^[^\n]\\{79\\}\\(.*\\)$" 1
font-lock-warning-face prepend)))))
Submitting installation recipes¶
- If you want to share your installation tips and tricks, efficient ways you
have to write or organize your modulefiles or some extension you made to the
module
command please add a recipe to the cookbook section of the documentation. - Create a directory under
doc/example
and put there the extension code or example modulefiles your recipe is about. - Describe this recipe through a reStructuredText document in
doc/source/cookbook
. It is suggested to have an Implementation, an Installation and an Usage example sections in that document to get as much as possible the same document layout across recipes. - Submit a patch with all the above content.
Design notes¶
Developer notes on feature specifications and code design.
Add new configuration option¶
This document is a guide for Modules developers that wish to introduce a new configuration option for the module command.
Core code¶
Introducing new configuration option means declaring it then using it (get its
value then branch code in modulecmd.tcl
script to adapt
module command behavior.
First declare configuration option in
g_config_defs
definition array- File to edit:
tcl/init.tcl.in
- Example commit: 2199edf8
New configuration option name should be short yet understandable. If composed of multiple words, they should be joined by
_
character. Option value could be superseded by an environment variable, using same name than config, upper-cased and prefixed byMODULES_
.Entry in
g_config_defs
definition array uses option name as key then a list as value composed with:- Superseding environment variable
- Default value
- Is configuration lockable to default value (0 or 1)
- Value kind (
i
for integer,s
for string,b
for boolean,l
for colon-separated list,o
for other) - Valid value list (empty list if no validation list)
- Internal value representation (optional)
- Specific procedure to call to initialize option value (optional)
- Valid value list kind (empty string,
intbe
oreltlist
)
- File to edit:
Update the Tcl code that compose the
modulecmd.tcl
script to adapt behavior depending on the value defined (by default or superseded) for the configuration option. Use thegetConf
helper procedure to fetch configuration option value. This part highly depends on the kind of configuration option introduced.- File to edit: file(s) in
tcl/
directory - Example commit: 4baf5dc4
- File to edit: file(s) in
Installation scripts¶
If the default value of the configuration option may be selected at
installation time, an installation option should be added on the
configure
script.
Define installation option argument in
configure
script, add it to the internal help message of this shell script, define an internal<optionname>
variable that is set to the default installation option value, then updated when install option argument is set.- File to edit:
configure
- Example commit: c00ecefa
- File to edit:
Define the
<optionname>
variable inMakefile.inc.in
set to the@<optionname>@
mark, that will be replaced by chosen value for option whenconfigure
script will generateMakefile.inc
. Define theinstall_<optionname>
variable insite.exp.in
to get value set for option within testsuite. Updatetranslate-in-script
rule inMakefile
to add translation of the@<optionname>@
mark into selected value.- Files to edit:
Makefile.inc.in
Makefile
site.exp.in
- Example commit: c00ecefa
- Files to edit:
Set the
@<optionname>@
mark as the default value for configuration option ing_config_defs
definition array in Tcl core code- File to edit:
tcl/init.tcl.in
- Example commit: c00ecefa
When the make installation step is performed the
modulecmd.tcl
script file is generated with the@<optionname>@
mark replaced by selected default value.- File to edit:
Initialization scripts¶
New configuration option should be referred in the shell completion scripts as
argument for the config
sub-command.
Files that should be edited to add reference to the new option:
init/Makefile
(contains definitions to build bash and tcsh completion scriptsinit/fish_completion
init/zsh-functions/_module.in
Example commit: abfef4ed
Documentation¶
Man pages and other user documentation have to be updated to describe the introduced option.
Files that should be edited:
doc/source/module.rst
(module manpage)- add configuration option description with
mconfig
anchor underconfig
sub-command section - add environment variable description with
envvar
anchor under ENVIRONMENT section
- add configuration option description with
doc/source/changes.rst
- add configuration option under Modules configuration options section of current Modules major version
- add environment variable under Environment section of current Modules major version
INSTALL.rst
- add configuration and related environment variable and installation option in the table under Configuration options section
Example commits:
In case an installation option has been added, it should be covered by documentation
- File to edit:
INSTALL.rst
- Example commit: 3d19ab52
Testsuite¶
Non-regression testsuite must be adapted first to ensure existing tests still pass then to add specific tests to check the behavior of the added configuration option and ensure overall code coverage does not drop.
First, clear the run test environment from predefined configuration value, set over the associated environment variable.
- Files that should be edited:
testsuite/modules.00-init/010-environ.exp
testsuite/install.00-init/010-environ.exp
- Example commit: 1c9fe1bd
If default value for option could be set at installation time, it may be important to take this chosen default value into account, thanks to the
install_<optionname>
Tcl variable set insite.exp
.- Files that should be edited:
Add new configuration option to the list of options tested over the
config
sub-command.- File to edit:
testsuite/modules.70-maint/220-config.exp
- Example commit: 1c9fe1bd
- File to edit:
Craft specific tests to validate the correct behavior of the configuration when not set, set with valid or invalid values.
- File to edit: depends on what is impacted by the new configuration option, if some tests already exist for concerned behavior (existing testsuite file to update) or not (new testfile to create).
- Example commit: 122039e5
Optionally if a new installation option has been introduced, it may be interesting to adapt CI configuration to test a value different than the default one
- Files to either edit:
.cirrus.yml
.github/workflows/linux_tests.yaml
- Example commit: 8bf6fb54
- Files to either edit:
Add new module sub-command¶
This document is a guide for Modules developers that wish to introduce a new sub-command for the module command.
Core code¶
Introducing new configuration option means declaring it then using it (get its
value then branch code in modulecmd.tcl
script to adapt
module command behavior.
First update in the
reportUsage
procedure the usage message of the module command to report the new sub-command.- File to edit:
tcl/report.tcl.in
- Example commit: 697b999a
- File to edit:
Update the
module
procedure and its helper procedures to register the new sub-command. First add sub-command in the list of valid sub-commands defined inparseModuleCommandName
.If sub-command cannot be called within a modulefile context add it in
module
procedure to the list of sub-commands raising an error if found call from such context.Add test in
module
procedure to verify that the number of argument passed to sub-command is valid.Update main switch in
module
procedure to add case for new sub-command that calls thecmdModule<Subcmdname>
procedure.- File to edit:
tcl/main.tcl.in
- Example commit: 697b999a
- File to edit:
Create the
cmdModule<Subcmdname>
procedure and craft in it the Tcl code corresponding to the sub-command introduced.- File to edit:
tcl/subcmd.tcl.in
- Example commit: 697b999a
- File to edit:
Initialization scripts¶
New sub-command should be referred in the shell completion scripts.
Files that should be edited to add reference to the new sub-command:
init/Makefile
(contains definitions to build bash and tcsh completion scriptsinit/bash_completion.in
init/fish_completion
init/tcsh_completion.in
init/zsh-functions/_module.in
Example commit: 0a96ed64
Linter scripts¶
New sub-commands should be described in Nagelfar syntax databases if it can be called within a modulefile context.
Files that should be edited to add reference to the new sub-command:
contrib/nagelfar/syntaxdb_modulefile.tcl
- add sub-command name in
::subCmd(module)
list - add sub-command argument description in
::syntax
array - add sub-command option description in
::option
array - See Nagelfar syntax description
- add sub-command name in
Documentation¶
Man pages and other user documentation have to be updated to describe the introduced sub-command.
Files that should be edited:
doc/source/module.rst
(module manpage)- add sub-command description with
subcmd
anchor under Module Sub-Commands section
- add sub-command description with
doc/source/modulefile.rst
(modulefile manpage)- mention if sub-command can be called from the modulefile evaluation
context under
module
modulefile command section - if sub-command leads to modulefile evaluation, mention sub-command name
in the list of value returned by
module-info command
- mention if sub-command can be called from the modulefile evaluation
context under
doc/source/changes.rst
- add sub-command under Module Sub-Commands section of current Modules major version
Example commits:
Testsuite¶
Non-regression testsuite must be adapted first to add specific tests to check the behavior of the added sub-command and ensure overall code coverage does not drop.
Test the sub-command against an invalid number of arguments (too few and too many).
- File to edit:
testsuite/modules.00-init/071-args.exp
- Example commit: 086ac136
- File to edit:
If the new sub-command cannot be called from a modulefile evaluation, test the error obtained when tried.
- Files to edit:
testsuite/modules.50-cmds/151-module-onlytop.exp
testsuite/modulefiles.3/modbad/<subcmdname>
- Example commit: 086ac136
- Files to edit:
If the new sub-command leads to modulefile evaluation, test value returned by
module-info command
.- Files to edit:
testsuite/modules.50-cmds/282-info-command.exp
testsuite/modules.50-cmds/283-info-command-exp.exp
testsuite/modulefiles/info/commandexp
- Example commit: 5cd53523
- Files to edit:
Craft specific tests to validate the correct behavior of the sub-command against valid or invalid values and valid or invalid environment.
- File to edit: new test file to create in
testsuite/modules.50-cmds
directory, for sub-command called during a modulefile evaluation, or intestsuite/modules.70-maint
directory otherwise. - Example commit: 086ac136
- File to edit: new test file to create in
Advanced module version specifiers¶
Configuration¶
- Introduce
advanced_version_spec
option name- off by default in v4 as previously soft@1 could be a module name
- on by default in v5
- in case
extended_default
is disabled- means short-hand notation cannot be used
- for soft/1.1 query soft@1 returns nothing
- means short-hand notation cannot be used
- in case
implicit_default
is disabled- means a default should be found over version range or list in selection context
Specification¶
Following Spack spec
- see https://github.com/spack/spack/blob/develop/lib/spack/spack/spec.py
- or https://spack.readthedocs.io/en/latest/basic_usage.html#version-specifier
- this specs covers all needs to specify module versions finely
- Spack users are already familiar with it
- it copes very well with command-line typing, avoiding most problematic characters
- that are interpreted by shells (like < or >)
- specification for one module could
- be almost condensed into one word "soft@1.8:"
- or be expanded into multiple "soft @1.8:"
same grammar used whatever the context
- command-line or as argument to modulefile command (like command)
versions are specified whether
- as specific words (separated by " ")
- or as suffix to module name
change command specifications which were previously accepting list of modules
- like module1 module2/vers module3
- now these modules could express versions appended to their name with @
- like module1@1.8 module2@vers module3
- or these versions could be defined as words next to module name
- like module1@1.8 module2 @vers module3
- as a consequence, it denies use of @ in module names
- such change requires an option to be enabled to avoid breaking compat
single version could be specified with soft@vers
- which matches soft/vers modulefile
version could be specified as range
- soft@:vers or soft@vers: or soft@vers1:vers2
- Tcl-dictionarily determine what is between specified range
extended_default
is always considered on when matching range- as 2.10 is included in @1:3 whatever the configuration
- to be specified in a range or compared to a range, version major element should match an hexadecimal number
- which also means be only composed by [0-9af] characters
- for instance 10a, 1.2.3, 1.foo, 10.2.good are versions valid for range comparison
- but 10g, default, foo.2, .1.3.4 are versions invalid for range comparison
- a version range using in its definition version invalid for range comparison raises error
- for instance @bar:foo
- existing module versions invalid for range comparison are ignored
- which means versions 10g, default, .1.13.4 or new are excluded from result for a @1.10: range query
- when range is defined as @major:major.minor, version matching major version but above major.minor are excluded
- for instance @1:1.10 will matches 1.0 and 1.8 but not 1.12
version could be specified as list
- soft@vers,vers,vers
- version specified could be text, like if symbolic version names are used
- should benefit from extended default specification
- to just express version with their major release number for instance
- an empty string among list is considered as a specification error
- for instance soft@vers,vers, or soft@vers,,vers
- any version in list can be a single version or a version range
- like soft@1.2,1.4:1.6,1.8
- helps to designate all versions except a few ones
when using extended default syntax
- version selection is performed same way for @vers than for /vers
- described in extended default design
when
icase
is enabled for selection context and multiple directories match module name- for instance query is ICase@1.1,1.2,1.4 and following modules exist: ICASE/1.1, icase/1.2, iCaSe/1.3 and iCaSe/1.4
- as no ICase directory exists, and a version in highest directory icase matches query (1.2), icase/1.2 is returned
- if query is iCaSe@1.1,1.2,1.4, iCaSe/1.4 will be selected as iCaSe directory matches query module name
- if query is ICase@1.1,1.4 or icase@1.1,1.4, as no version match in highest directory iCaSe/1.4 will be selected
in case of deep modulefiles
- specified version is matched at the level directly under specified module name
- not below levels
- for instance soft@vers, will match soft/vers, not soft/deep/vers
- to specify version for deep modules:"soft/deep@vers
- to ease version comparison deep version cannot be specified after the @ character like soft@deep/vers
- such specification will raise an error
- specified version is matched at the level directly under specified module name
advanced version specifier cannot be used with full path modulefile
- when a full path modulefile is specified any advanced version set afterward is treated literally
- for instance /path/to/modulefiles/mymod@1.2 will lead to the access of file mymod@1.2 in directory /path/to/modulefiles
in case version is specified multiple times
- lastly mentioned (read from left to right) value is retained (it overwrite previous values)
- like module@1.8 @2.0 or module@1.8@2.0
- beware of version specified over a fully qualified modulefile like in soft/1.8@1.10" or "soft/1.8 @1.10
- it resolves to soft/1.8/1.10 as advanced version specified is treated as an additional directory level
in case modulefile is named module@vers in filesystem
- it is not found when option
advanced_version_spec
is enabled - as it is translated to module/vers
- it is not found when option
when special characters like ? or * are used in version name or value
they are evaluated as Tcl glob pattern on return all matching modules context
they are treated literally on single module selection and compatibility check context, no wildcard meaning is applied
like currently done when specifying module version on command-line
which leads to errors as no corresponding module is found:
$ module load loc_dv6/* ERROR: Unable to locate a modulefile for 'loc_dv6/*'
if version range or list does not contain a defined default
- in a selection context
- highest version is returned if
implicit_default
is enabled - error returned if
implicit_default
is disabled- even if version range or list specifies non-existent modules and only one existent module
- highest version is returned if
- in a compatibility expression context
- range or list is matched against loaded environment whether the
implicit_default
state - when no match found and evaluation are triggered, selection context applies
- range or list is matched against loaded environment whether the
- in a selection context
when version is specified over an alias
- should proceed like for real modulefile
- when alias equal to a bare module with no version
- foo is alias on bar modulefile, bar is a file (not a dir with version modulefiles)
- query alias@:2 should behave like query alias/2
- when alias equal to a module/version modulefile
- foo is alias on bar/3 modulefile
- query alias@:2 should behave like query alias/2
Contexts where it could be used
Note
Advanced version specifier does not apply for the moment to the Module identification to select one module context. Adding support for this context will require a significant rework on module alias and symbolic version registering and resolving code.
- impact of advanced version specifier implementation over code
- question especially over
auto_handling
code like conflict and prereq handling - it should not impact triggers and actions
- but consist in an overall change of procedures comparing queries against loaded environment
- procedures like
doesModuleConflict
- procedures like
- also adapting
getModules
to restrict version possibilities to what has been specified- for instance with query soft@1,2 should only return versions matching
- question especially over
- prereq/conflict persistency
LMPREREQ
andLMCONFLICT
content should reflect specified version constraint- it could be expressed in these variables somewhat like it is specified to the
- prereq/conflict modulefile commands
- for instance
__MODULES_LMPREREQ=soft/1.10&bar@1.8,1.10&foo@<2|foo@3<4
- delimiters characters are :, & and |
- so use of characters * , *@, , is not an issue
- but for : which express version ranges it should be substituted to <
- prereq/conflict specification
- could consolidate different version set for same module on the same prereq/conflict list
- to indicate a preferred order (if available)
- like
prereq foo@1.8 foo@1.10
- or
prereq foo @1.8 foo@1.10
- also to trigger alternative requirement resolution in case first one failed
- as each module version specification leads to one evaluation only
- even if multiple modulefiles correspond to this specification
- like
prereq soft@1.8,1.9,1.10
will lead to soft/1.10 load
- like
- best candidate is chosen from matches
- in case
implicit_default
is disabled an explicit default should be part of the list or range for the triggered evaluation to succeed
- in case
- even if multiple modulefiles correspond to this specification
- whereas
prereq soft@1.8 soft@1.9 soft@1.10
will lead to a tentative load- of soft/1.8, then soft/1.9 if it failed then soft/1.8 if it also failed
- as each module version specification leads to one evaluation only
- one module version specification may match multiple loaded modules
- like
conflict soft@1.8,1.9,1.10
matches loaded modules soft/1.8 and soft/1.10 - similar to situations where requirement or conflict is expressed over module generic name, like soft, and multiple versions of module are loaded
- like
- could consolidate different version set for same module on the same prereq/conflict list
Corner cases¶
- When
icase
is enabled on all contexts and multiple directories match same icase module name- for instance following modules exist: ICASE/1.1, icase/1.2, iCaSe/1.3 and iCaSe/1.4
- a
module avail -i icase
will sort iCaSe/1.4 as the highest entry - however a
module load -i icase@1.1,1.2,1.4
command will load icase/1.2- as icase directory matches query and version 1.2 is found in icase directory
- but a
module load -i icase@1.1,1.4
command will load iCaSe/1.4- as no version 1.1 nor 1.4 is found in icase directory
Control mode behaviors¶
- Modulefile commands that modify environment variables applies
- a behavior when modulefile is loaded
- and another behavior when modulefile is unloaded
- Depending on the situation, it seems interesting to apply a different
behavior when modulefile is unloaded:
- restore value unset at load time, either:
- append-on-unload
- prepend-on-unload
- remove value from list: remove-on-unload
- unset full variable value: unset-on-unload
- set another value, either:
- append-on-unload
- prepend-on-unload
- set-on-unload (for non-path-like variable)
- do nothing: noop-on-unload
- restore value unset at load time, either:
- Also when modulefile loads sometimes it may be interesting to apply a
slightly different behavior depending on the situation:
- set value only if variable is undefined: set-if-undef
- Concerned modulefile commands:
- Only applies when the above commands are called from a modulefile (as some of these commands can also act as module sub-commands)
Unload behavior¶
Unload behavior of concerned modulefile commands:
Command Default unload behavior Specific unload behavior Alternative behaviors to add module use remove-on-unload n/a module unuse remove-on-unload n/a append-on-unload, prepend-on-unload, noop-on-unload setenv unset-on-unload n/a unsetenv noop-on-unload set-on-unload (when 2nd argument is provided) unset-on-unload append-path remove-on-unload n/a prepend-path remove-on-unload n/a remove-path noop-on-unload n/a remove-on-unload, append-on-unload, prepend-on-unload When either restoring or setting other value for path-like modulefile commands, it is needed to know if the value should be appended or prepended.
Either restoring or setting other value result in the same behavior name
- append-on-unload and prepend-on-unload
- position of the option will determine if the values to set are:
- those unset at load time: when option is placed prior value list
- a different list of value: when option is placed after value list to unset at load time and another value list is defined after option
The set-on-unload behavior is only useful for modulefile commands which unset value on load mode, as commands that set value on load mode mainly need to unset the value set.
Default unload behavior of
module unuse
,unsetenv
andremove-path
commands can also be set as an option in their argument list. Helps to dynamically choose the behavior to apply, which could be the default behavior.
Load behavior¶
Load behavior of concerned modulefile commands:
Command Default load behavior Alternative behaviors to add module use set-on-load module unuse remove-on-load setenv set-on-load set-if-undef unsetenv unset-on-load append-path add-on-load prepend-path add-on-load remove-path remove-on-load
Modulefile command options¶
- Alternative behaviors could be specified by setting the associated option
over the modulefile command:
--remove-on-unload
--append-on-unload
--prepend-on-unload
--noop-on-unload
--unset-on-unload
--set-if-undef
- The
--append-on-unload
and--prepend-on-unload
options either:- restore the value list removed at load time if placed prior this value list
- set a different value list if a different list of value is specified after option (all the values set after the option are considered element to add to the path-like variable)
- both options also accept to be set prior or right after variable name or even right at the end of argument list to restore value list removed at load time
- The
--set-if-undef
option does not change the behavior ofsetenv
when modulefile is unloaded: environment variable will be unset whether the option is set or not. - The
--remove-on-unload
option can be set anywhere in argument list - The
--remove-on-unload
,--append-on-unload
and--prepend-on-unload
options cannot be mixed with the--index
option ofremove-path
sub-command. - The
--remove-on-unload
,--append-on-unload
,--prepend-on-unload
and--noop-on-unload
options:- can be placed at different positions in argument list to limit error cases
- if multiple options of this kind are defined in argument list, the one defined at the most right is retained
Misc¶
- FUTURE: what is applied to:
module use
may also be interesting formodule load
module unuse
may also be interesting formodule unload
Default and latest version specifiers¶
Configuration¶
- Rely on
advanced_version_spec
option- No need for an extra configuration option
- When option is on it automatically enables use of these two new version specifiers
- When
advanced_version_spec
is off,mod@latest
is considered as a modulefile name to find - in case
implicit_default
is disabled- means a
default
symbol or alatest
symbol should be found defined to respectively make use of the@default
or@latest
specifiers - a not found error is otherwise raised, as specified version does not exist
- means a
Specification¶
- When a
default
or alatest
symbol is defined@default
or respectively@latest
will resolve to the symbol target
- When no
default
orlatest
symbol is defined@default
and@latest
point to the highest existing version (also called the implicit default)- note that if a
default
symbol is defined but not alatest
symbol,@default
points to the defined default and@latest
points to the highest version that exists
default
orlatest
version specifiers can be employed:- in single version specification:
@default
or@latest
- in version list:
@vers1,default
or@latest,default,vers2
- in single version specification:
default
orlatest
version specifiers cannot be employed in version range- otherwise an error is raised
default
orlatest
version specifiers can also be specified with the traditionalmod/version
syntax- for instance
mod/default
ormod/latest
- for instance
- When a
default
orlatest
modulefile exists@default
or respectively@latest
will resolve to the existing modulefile- no automatic symbol will be recorded in this case as
default
orlatest
are regular versions
- To be included in module search result, the version specifiers should fully match search query or search query should not target a specific module version
- the automatically defined symbolic versions are included in results for queries like
mod@latest
ormod
- but not for queries like
mod@la
,mod@def
,mod@lat*
,mod@def??lt
- the automatically defined symbolic versions are included in results for queries like
- Automatically defined
default
andlatest
version specifiers are not displayed to avoid overloading output:- on
module list
output - on
module avail
output - those two sub-commands only display symbolic versions manually defined
- on
- Alternative module names deduced from the automatically defined version specifiers need to be tracked
- in loaded environment for each targeted module loaded
- to keep track loaded module is default or latest version
- thus keeping ability to answer queries like
is-loaded mod@latest
from further modulefile evaluation or module command-line - this information is kept in the
__MODULES_LMALTNAME
environment variable, along other alternative names - Auto symbols in this variable are recorded with a
as|
prefix to distinguish them from other alternative names- for instance
mod/1.2&mod/regular_symbol&as|mod/latest
- it helps to filter auto symbols from regular symbols that need to be displayed
- for instance
Extended default¶
Configuration¶
- introduce
extended_default
option name - off by default in v4 as previously soft/1 was an error
- on by default in v5, option could even disappear
- set as a separate option than advanced_version_spec
- as it affects also basic soft/vers version specification
- seem easier to understand for user if concepts are distinguished
Specification¶
- Take partial version identifier and returns matches
- for soft/10.1.2.4 soft/10.1.2.3 soft/10.1.1
- query soft/10 returns highest among 3
- query soft/10.1 returns highest among 3
- query soft/1 returns nothing
- query soft/10.1.2 returns highest among soft/10.1.2.4 soft/10.1.2.3
- In situation where soft/1.1(default) soft/1.2 soft/2.1 soft/2.2
- query soft/1 returns soft/1.1
- query soft/2 returns soft/2.2
- Character considered as version number separator:
.
- list:
.
and-
-
was also considered initially, but cannot determine in all case the highest version specified after this character (may find a hash name, strings like rc, alpha, beta, etc)- not possible with
+
as it is used by variant specification
- list:
- Does not apply to the root part of module name
- e.g. foo.2
- If
implicit_default
is disabled- it makes
extended_default
inoperative if queried version does not include a defined default - even if only one modulefile matches query
- with situation described above query soft/1 returns soft/1.1
- but query soft/2 returns an error as no default is found among version 2 modulefiles
- it makes
- Contexts where it could be used
- Module version specification to return all matching modules
- on specification that are processed as a wild search,
extended_default
has no impact- as a wildcard character
*
is appended to specification - affects
avail
sub-command
- as a wildcard character
- on specification that are processed as a wild search,
- Module version specification to select one module
- Module version specification to check compatibility
- Module version specification to return all matching modules
Extra match search¶
Traditional module lookup only performs modulefile search, module version resolution, module alias and symbolic version resolution. This is based on file lookup and evaluation of modulerc files.
Searching modules with a query exceeding traditional lookup is called extra match search. It mainly looks at modulefile content to retain those matching specified query. This content lookup requires a specific modulefile evaluation (see Modulefile evaluation mode for extra match search).
Requirements¶
An extra match search query requires Advanced module version specifiers configuration to be enabled. Otherwise query specifiers will be understood as module name and version.
When extra match search applies¶
On Module version specification to return all matching modules context. On such context, variant specification in search query was previously ignored. Extra match search adds here a feature to filter returned results.
On Module version specification to select one module context, extra match search is not enabled at the moment. As it changes obtained result. For instance when loading a module with a given variant value, extra match search will remove from available modules those not declaring this variant and its specified value. It is considered to add an option to apply extra match search to the select one module context. This option will be disabled by default on Modules v5 and enabled by default on v6.
What triggers an extra match search?¶
Extra match search process¶
Extra match search is performed from getModules
procedure. All subsequent
procedures relying on getModules
will then benefit from this extra process
without a change.
Extra match search is done right after phase 3: elaborate directory content with default element selection. At this stage:
- symbolic versions, aliases and virtual modules are known
- dynamically hidden or expired elements have been filtered
- automatically defined symbols are set
- initial directory content and their default version are set
This way the subsequent phases that filters result based on name and version search query, adjusts directory content and no-indepth mode does not need to be updated and will apply on the extra match search result.
As extra match search is performed after phase 3, search operation will only applies on result obtained from traditional lookup.
In case no-indepth mode is asked and extra match search should be performed,
traditional file lookup (by findModules
) is made to return all existing
files. Not only those matching depth level. As extra match filtering process
may eliminate some entries, all of them should be tested to obtain accurate
result.
Extra match search will only be performed if search query requires it. It will
be determined by isExtraMatchSearchRequired
procedure. See What triggers
an extra match search? for applying conditions. Current search module
specification is passed as argument. This string helps to find if:
- variant has been specified in ModuleVersSpec structure
- extra specifier has been specified in ModuleVersSpec structure
If search query is a traditional one, no extra match search is performed. It saves this way substantial processing time as no evaluation of modulefile is performed.
getModules
will call a dedicated procedure named
filterExtraMatchSearch
to handle the extra match search process. It will
obtain the name of result array as argument and will bind to this array
variable (to change it without copy). Search module specification is also set
as argument to help to know the extra match query to filter modules on.
filterExtraMatchSearch
evaluates all entries in obtained result array that
are of modulefile or virtual types. See Modulefile evaluation mode for extra
match search section. With the consolidated information gathered by these
evaluations, procedure filters entries in result array that do not match the
extra match query.
Symbolic versions¶
From filterExtraMatchSearch
, symbolic version elements are retained unless
if they target an element that is withdrawn by the filter process.
They need to be filtered if their target is filtered as it may confuse some
sub-commands like paths
if they are part of getModules
result.
During wild search (no module name specified) with variant specified, auto
symbolic versions (latest and default) are disabled. This is done
especially for sub-commands like paths
that take getModules result and try
to resolve each entry. In this situation it is important not to have any auto
symbol that indirectly targets an element withdrawn from extra match filter.
Module aliases¶
From filterExtraMatchSearch
, module alias elements are purely withdrawn by
the filter process as they are not resolved on return all matching modules
context. They are also withdrawn even if searched module name matches alias
name.
They need to be filtered when search query mentions a specific variant and value as alias does not define variant in itself.
When variants have to be reported but are not part of the search query, then no filtering process occurs, aliases are not withdrawn.
Directories overridden by aliases take precedence over these aliases when extra match search is performed.
FUTURE: it may be revised to implement extra match search on select one module context.
Module tags¶
Modulefiles tagged forbidden are excluded from evaluation mechanism. If forbidden tag only applies to some specific variant values, modulefile is evaluated.
Note that in a select one module context, if forbidden tag applies specifically to searched variant, this module is excluded from result.
If module hidden tag only applies to some specific variant values, modulefile is evaluated in scan mode.
Error entries¶
Files in error (e.g., without a module header string, not readable) are
ignored by filterExtraMatchSearch
and kept in result array. These error
entries are useful to report the message they contain if erroneous file was
specifically selected.
Extra specifier¶
Extra specifier enables to query whose modules defines a given element. With them it is possible to get all the modules defining a given environment variable or requiring a given module.
Most of the modulefile Tcl commands are associated to an extra specifier. Some aliases are also provided, to gather several command elements into the general same concept they are about. Following table list the available extra specifiers and their associated modulefile command.
Modulefile command | Extra specifier(s) |
---|---|
variant | variant |
setenv | setenv, envvar |
unsetenv | unsetenv, envvar |
pushenv | pushenv, envvar |
append-path | append-path, envvar |
prepend-path | prepend-path, envvar |
remove-path | remove-path, envvar |
complete | complete |
uncomplete | uncomplete |
set-alias | set-alias |
unset-alias | unset-alias |
set-function | set-function |
unset-function | unset-function |
chdir | chdir |
family | family |
prereq | prereq, prereq-any, require |
prereq-any | prereq-any, prereq, require |
prereq-all | prereq-all, depends-on, require |
depends-on | depends-on, prereq-all, require |
always-load | always-load, require |
conflict | conflict, incompat |
module load | load, require |
module load-any | load-any, require |
module try-load | try-load, require |
module unload | unload, incompat |
module switch | switch, switch-on, require, switch-off, incompat |
Extra specifier are only valid on return all matching modules context. An error is returned when used in query on other contexts.
Using an unknown extra specifier (not part of the above table) produces an error. Helps to distinguish between a bad specification and no modulefile declaring the associated modulefile command.
Extra specifier are not made to resolve module alias or symbolic version, as such resolution is part of the regular match search.
The module switch
command produces content in different extra specifiers.
Switched-on module can be queried via switch
, switch-on
and
require
specifiers. Switched-off module can be queried via switch
,
switch-off
and incompat
specifiers. On its one-arg form, no
switched-off module is added to relative specifiers.
Recording extra specifier specification¶
Extra specifiers defined in a search query are processed and saved in
ModuleVersSpec structure along other query elements. As the search query
string is passed along the procedures, it is possible to retrieved the
extra specifier properties from this query string (with
getExtraListFromVersSpec
procedure).
Extra specifiers are saved as a list of list. Every extra specifier defined in query is set as a list whose first element is extra specifier name, then the other element corresponds to the list of values provided to this argument.
For example, search query mod/1.0 setenv:FOO variant:bar setenv:BAR
produces internal representation {setenv FOO} {variant bar} {setenv BAR}
.
When OR operation will be supported, search query mod/1.0 setenv:FOO,BAR
will produce internal representation {setenv FOO BAR}
.
Value specified may contain a space character if it is escaped on command line
either by quotes ("prereq:mod@1.0 foo=bar"
) or backslash
(prereq:mod@1.0\ foo=bar
). This is especially useful for complex module
specification.
Filtering extra specifier results¶
Every -sc variant of modulefile Tcl command, record their properties in the
g_scanModuleElt
global dictionary. It is a nested structure that contains
at the top level the list of defined extra specifier names. Each of these
names is in turn a structure that contains all defined extra specifier values
associated to the module name and version defining this extra specifier name
and value pair.
For example, when module mod/1.0 defines setenv FOO value in its file, then the global dictionary is updated to add mod/1.0 to the setenv > FOO nested key.
When extra specifier has alias name(s), each of these aliases have their own entry in the global directory. Reusing the previous example, envvar is an alias on setenv extra specifier. When module mod/1.0 defines setenv FOO value, the global dictionary is also updated to add mod/1.0 to the envvar > FOO nested key (in addition to the setenv > FOO nested key.
Such data structure optimizes filtering work: it is done once for all
modulefiles after finishing the scan evaluation of all of them. For each
extra specifier criteria, goal is to match the corresponding nested key in
g_scanModuleElt
global directory. Modulefiles to keep in result of those
listed as value in every matched nested keys.
When there are several extra specifiers in search query, result are the modules present in the value list of every matched keys (intersection of value list obtained for every extra specifier criterion).
Specific filtering work is achieved for extra specifiers accepting a module specification. See next section.
Filtering module specification¶
Some extra specifiers accept a module specification as value. It corresponds to all extra specifiers relative to requirements and incompatibilities expressed by modulefiles (prereq, conflict, etc).
Module specification passed as extra specifier value has to be compared to the module specification set in the modulefile definition for corresponding command.
When parsing such extra specifier value, when evaluating command line
arguments, module specification is parsed with a specific available module
resolution: all matching available modules are recorded into module
specification (g_moduleVersSpec
). It enables to fetch:
- every module name and version matching a version list or range specification
- every generic or fully qualified names
Match against modulefile definitions of such extra specifiers is performed in
the same location than for other extra specifiers. It relies on a modEq
comparison that has been adapted to also compare alternative names fetched and
stored into module specification structure. Relying on modEq
procedure,
comparison leverages icase and extended_default features.
LIMITATIONS: Current module specification match does not support:
- Comparison of module alias or symbolic names when used in either extra specifier value or in modulefile definition
- Version range or list specified in extra specifier value is converted into a list of existing modulefiles, thus a version in such specification that does not correspond to an existing module will not be matched
Variant value comparison is enabled on modEq
test. modVariantCmp
internal test has been adapted to let a missing variant definition be
considered as a match.
Query grammar¶
In extra match search query, variants are expressed like in select one module context:
- multiple variants mentioned act as an AND operation
module avail mod/1.0 foo=val1 bar=val2
- means foo equals val1 and bar equals val2
- same variant mentioned multiple times: only the last mention is retained
module avail mod/1.0 foo=val1 foo=val2
- means foo equals val2
In extra match search query, extra specifiers are expressed with name:value syntax. Using : as separator helps to distinguish from variant specification. As a consequence, such character is not recommended to be part of a module name or version (which was already the case, as : character is also a separator used in environment variables like LOADEDMODULES). As extra specifiers only applies to return all matching modules context, the use of name:value specific syntax may help user to distinguish from the select one module context.
NOTE: use of a --where or --with options was also considered to be able to use a name=value syntax like variant specification. It was preferred to use a different syntax (name:value) to avoid having to type an extra option.
NOTE: if name=value syntax where used for extra specifier, all extra specifier names would have been forbidden to use as variant names.
- multiple extra specifiers mentioned act as an AND operation
module avail mod/1.0 setenv:FOO pushenv:BAR
- means module defines setenv command to set FOO environment variable and defines pushenv command to set BAR*
- same extra specifier mentioned multiple times: all mentions retained and act
as an AND operation
module avail mod/1.0 variant:foo variant:bar
- means defines variant foo and variant bar
Value of either variant or extra specifier are full name. No wildcard characters are taken into account (they are treated literally).
An error is raised when an empty extra specifier name or value is specified.
FUTURE: expressing an OR operation
- for instance by mentioning multiple values separated by
,
character module avail mod/1.0 foo=val1,val2 bar=val2
- means foo equals val1 or val2 and bar equals val2
- such syntax is equivalent to version list specification
- does not seem useful to allow ranges like for version
- FIXME: allow such syntax on any context or only for return all matching modules context?
FUTURE: expressing a NOT operation
- adding a character like
~
or!
prior value module avail mod/1.0 foo=!val1 bar=val2
- means foo equals any value expect val1 and bar equals val2
- FIXME: allow such syntax on any context or only for return all matching modules context?
- NOTE: NOT operator is not specified currently on Spack's side. Some
discussions mention use of
!
, which does not work for Tcsh shell
What triggers scan
evaluation?¶
- everything that triggers an extra match search
- except tag extra specifier, as tags are defined outside of modulefiles
Modulefile evaluation mode for extra match search¶
A specific evaluation mode is created for looking at modulefile content in
order to solve an extra match search. This mode is named scan
.
Modulefile Tcl interpreter is configured to run a specific variant of modulefile Tcl commands. These variants will gather content of modulefile in global structures that will be searched after all scan evaluations to determine what modules match the extra query. Names of scan variant of modulefile Tcl command scan variant procedures are internally suffixed with -sc.
If modulefile content queries the current evaluation mode, it will obtain the
scan
string during a scan evaluation. We expect modulefile code to cope
with this behavior, especially to still be able to get all load information
of modulefile, even if mode is not load
. A load
string cannot be
returned during a scan evaluation as modulefile may have some code to
produce log message when a load attempt is detected.
Even if extra match search only concern a specific element, like querying module variants, all modulefile commands are setup to gather all content information about modulefile. This way, it is evaluated the same way whatever the query. Scan evaluation code will also be simpler.
Environment variable definition through modulefile commands like setenv
,
append-path
, etc are handled like in whatis
evaluation mode. Variables
are set to an empty value. Some processing time is saved this way. It may have
an impact on some complex modulefiles: content scan may not be accurate. If
this is an issue on some setup, an option could be added in the future to set
variable to their expected value also on whatis
and scan
evaluation
modes.
When an error is raised from a modulefile evaluation. No error message is
reported as such message is silenced during the whole avail
process.
Rendered result is ok for all kind of errors even for break
or exit
.
No error result is rendered for these two, unlike for a whatis
evaluation,
not to disturb the whole search result for one modulefile not coping with scan
evaluation.
puts
commands in modulefile are rendered like on a whatis
evaluation
mode: output is effectively produced toward the designated channel. It is up
to modulefile writer to handle the scan
evaluation, like done for
whatis
.
source-sh
commands in modulefile are rendered like on a load
evaluation. They will produce setenv
, set-alias
, set-function
and
so on commands that will be in turn evaluated in scan mode.
Specific impact¶
- With a
contains
search match every modulefiles in modulepath are evaluated in scan mode.- FUTURE: there may have room for optimisation here
Hide or forbid modulefile¶
Configuration¶
- No specific configuration
Use cases¶
- Restrict usage of particular software to a limited set of user (RestrictUsage)
- Included in module specification result for a not granted user: no
- Visible for a not granted user on a full
avail
: no - Visible for a not granted user on a targeted
avail
: no - Visible for a not granted user once loaded on a
list
: yes - Load tentative for a not granted user: error
- Allow usage of particular software once clearance has been obtained (AllowOnceCleared)
- Included in module specification result for a not granted user: yes
- Visible for a not granted user on a full
avail
: yes - Visible for a not granted user on a targeted
avail
: yes - Visible for a not granted user once loaded on a
list
: yes - Load tentative for a not granted user: error
- Expire a software after a given date (Expire)
- Included in module specification result for a not granted user: no after expiration date
- Visible for a not granted user on a full
avail
: no after expiration date - Visible for a not granted user on a targeted
avail
: no after expiration date - Visible for a not granted user once loaded on a
list
: yes, even after expiration date - Load tentative for a not granted user: error after expiration date
- Disclose a software after a given date (Disclose)
- Included in module specification result for a not granted user: no prior disclosure date
- Visible for a not granted user on a full
avail
: no prior disclosure date - Visible for a not granted user on a targeted
avail
: no prior disclosure date - Visible for a not granted user once loaded on a
list
: yes, even prior disclosure date - Load tentative for a not granted user: error prior disclosure date
- Hide software not of interest for current user (HideNotOfInt)
- Included in module specification result for a not granted user: yes
- Visible for a not granted user on a full
avail
: no, unless specific option set - Visible for a not granted user on a targeted
avail
: yes - Visible for a not granted user once loaded on a
list
: yes - Load tentative for a not granted user: success
- Hide software only useful for other software as dependency (HideDep)
- Included in module specification result for a not granted user: yes
- Visible for a not granted user on a full
avail
: no, unless specific option set - Visible for a not granted user on a targeted
avail
: yes - Visible for a not granted user once loaded on a
list
: yes - Load tentative for a not granted user: success
- Hide dependency software once loaded (HideDepOnceLoaded)
- Included in module specification result for a not granted user: see HideDep
- Visible for a not granted user on a full
avail
: see HideDep - Visible for a not granted user on a targeted
avail
: see HideDep - Visible for a not granted user once loaded on a
list
: no, unless specific option set - Load tentative for a not granted user: see HideDep
Specification¶
- 2 new modulefile commands are introduced for the needs described above:
module-hide
andmodule-forbid
module-hide
removes visibility of specified modulesmodule-hide
acts when modules are searched (avail
,whatis
andsearch
sub-commands) or selected (load
,unload
,display
, etc sub-commands)- Visibility is however enabled if hidden module is specifically searched
- On all context hidden module mod/1.0 is included in result for instance if mod/1.0 or mod@1.0,2.0 are specified
- But hidden module mod/1.0 is excluded from result if mod@:2.0 or mod@1: are specified
- And is also excluded from result if mod or mod/* are specified when mod/1.0 is set default
- Unless if search is made to select one module since in this context a mod search query is equivalent to mod/default
- Hard-hidden modules are not disclosed even if specifically searched
- Excluded from module resolution result
- Unless precisely specified on the following selection contexts:
- For example, the hidden module mod/1.0
- is included in
module load mod/1.0
result - is excluded from
module load mod/1
result, even if default symbol targets it - is excluded from
module load mod
result, unless if default symbol targets it (as query is equivalent to mod/default) - is excluded from
module load mod@:2
result, even if default symbol targets it - is included in
module load mod@1.0,2.0
result - is included/excluded the same way for
prereq
andconflict
sub-commands thanload
sub-command - is matched by
is-loaded
andinfo-loaded
sub-commands querying it once loaded - is excluded from
module whatis
result - is included/excluded the same way for
whatis
sub-command thanavail
sub-command - is excluded from
module avail
result - is excluded from
module avail m*
result - is included in
module avail mod/1.0
result - is excluded from
module avail mod/1
result, even if default symbol targets it - is excluded from
module avail mod
result, even if default symbol targets it (as query is NOT equivalent to mod/default in this context) - is excluded from
module avail mod@:2
result, even if default symbol targets it - is included in
module avail mod@1.0,2.0
result
- is included in
- Included in module resolution result if
--all
option ofavail
,whatis
,search
andaliases
sub-commands is set--all
option does not apply tois-avail
sub-command to make it coherent withload
sub-command (e.g., ais-avail mod
returning true impliesload mod
effectively loading a module)
- Visibility of a module targeted by a
module-hide
command, with regular hiding level defined, acts similarly than for a file whose name is prefixed by a dot character on Unix platform - If
--soft
option is set onmodule-hide
command, module hiding is weakened- Module is always included in resolution result for the following contexts
- For example, the hidden module mod/1.0
- is included in
module load mod/1.0
result - is included in
module load mod/1
result - is included in
module load mod
result - is included in
module load mod@:2
result - is included in
module load mod@1.0,2.0
result - is included/excluded the same way for
prereq
andconflict
sub-commands thanload
sub-command - is matched by
is-loaded
andinfo-loaded
sub-commands querying it once loaded - is excluded from
module whatis
result - is included/excluded the same way for
whatis
sub-command thanavail
sub-command - is excluded from
module avail
result - is excluded from
module avail m*
result - is included in
module avail mod/1.0
result - is included in
module avail mod/1
result - is included in
module avail mod
result - is included in
module avail mod@:2
result - is included in
module avail mod@1.0,2.0
result
- is included in
- If
--hard
option is set onmodule-hide
command, hiding is hardened and designated modules are never unveiled- Designated modules are strictly hidden, also referred as hard-hidden
--all
option ofavail
sub-command cannot unveil them
- Excluded from module resolution result, which means it is always excluded from resolution on following context:
- For example, the hard-hidden module mod/1.0
- is excluded from
module load mod/1.0
result - is excluded from
module load mod
result, even if default symbol targets it - is excluded from
module load mod/1
result, even if default symbol targets it - is excluded from
module load mod@:2
result, even if default symbol targets it - is excluded from
module load mod@1.0,2.0
result - is included/excluded the same way for
prereq
andconflict
sub-commands thanload
sub-command - is matched by
is-loaded
andinfo-loaded
sub-commands querying it once loaded - is excluded from any
avail
query result - is included/excluded the same way for
whatis
sub-command thanavail
sub-command
- is excluded from
- Visibility of a module targeted by a
module-hide --hard
command acts like if no modulefile exists on filesystem
- Designated modules are strictly hidden, also referred as hard-hidden
- If
--hidden-loaded
option is set onmodule-hide
, hiding also applies to specified modules once they are loaded- Hidden once loaded modules do not appear on
module list
- Unless
--all
option is set onlist
sub-command
- Unless
- Hidden once loaded modules load, unload or tag is not reported
- If this evaluation has been triggered automatically
- By an automated module handling mechanism for instance
- Which means user has not explicitly asked the module load or unload
- And was automatically loaded, in case of an automatic unload
- Which means the automatic unload of an hidden loaded module will be reported if it was manually loaded
- And if
verbosity
level is lower thanverbose2
level - And if no issue occurs during hidden module evaluation
- Switch of hidden modules is not reported
- If both switched-off and switched-on modules are set hidden
- If switched-off module were automatically loaded
- And if the switch evaluation has been automatically triggered
- If this evaluation has been triggered automatically
- When those modules are loaded, a
hidden-loaded
tag is applied to them and recorded in__MODULES_LMTAG
environment variable to keep track of their hidden status - Hidden once loaded status does not affect
is-loaded
: these modules will always be reported if they matchis-loaded
queries
- Hidden once loaded modules do not appear on
module-forbid
disallow evaluation of specified modules- It does not imply hiding, but can be of course coupled with
module-hide
calls - Evaluation of targeted modules is forbidden
- Error is rendered prior evaluation when trying to load, display, help, test, path, whatis them
- Note that for whatis evaluation mode, an error is reported only if a module is referred by its exact name which is not the case on
search
sub-command as no module is specified, just a keyword to search - No error occurs when unloading a module that were set forbidden after it was loaded by user
- As it impacts module evaluation,
module-forbid
is only effective when it targets modulefiles or virtual modules- Module alias or symbolic version are not impacted by
module-forbid
directives - Even if they match some
module-forbid
statements, they are still resolved to their target and these targets do not inherit the forbidden tag set on their alias, symbol. - When a
module-forbid
command targets a directory, this directory is still resolved to its target, but the target inherits the forbidden tag as it matches the name specified onmodule-forbid
command
- Module alias or symbolic version are not impacted by
- When combined with a
module-hide --hard
command, designated modules is unveiled if referred by its exact name and set in error- Thus an error is obtained when trying to reach module instead of not finding it (which is the regular behavior for hard-hidden modules)
- It does not imply hiding, but can be of course coupled with
module-hide
accepts options that change its behavior:--hidden-loaded
: hides module from loaded module list--soft
: lightweight module hide--hard
: highest hiding level--not-user
: specify a list of users unaffected by hide mechanism--not-group
: specify a list of groups whose member are unaffected by hide mechanism--before
: enables hide mechanism until a given date--after
: enables hide mechanism after a given date
module-forbid
accepts options that change its behavior:--not-user
: specify a list of users unaffected by forbid mechanism--not-group
: specify a list of groups whose member are unaffected by forbid mechanism--before
: enables forbid mechanism until a given date--after
: enables forbid mechanism after a given date--message
: supplements error message obtained when trying to evaluate a forbidden module with given text message--nearly-message
: supplements warning message obtained when evaluating a nearly forbidden module with given text message
- Each use case expressed above are covered by following command:
- RestrictUsage:
module-hide --hard
- AllowOnceCleared:
module-forbid
- Expire:
module-forbid --after
+module-hide --hard --after
- Disclose:
module-hide --hard --before
- HideNotOfInt:
module-hide --soft
- HideDep:
module-hide --soft
- HideDepOnceLoaded:
module-hide --soft --hidden-loaded
- RestrictUsage:
module-hide
andmodule-forbid
accept the specification of several modules- For instance
module-hide mod1 mod2...
- Advanced module version specifiers are supported if relative module option is enabled
- Full path specification are not supported, as modulerc are not evaluated when reaching a modulefile specified as full path
- For instance,
/path/to/modulefiles/.modulerc
is not evaluated when loading/path/to/modulefiles/mod/1.0
- Thus
module-hide
andmodule-forbid
commands set in this modulerc files are not evaluated - If module is specified as full path, no error is returned, but it will have no effect as demonstrated above
- Unless on very specific cases, where a global rc file defines these hidden/forbidden commands for the full path modules
- For instance,
- For instance
--not-user
and--not-group
specification is only supported on Unix platform- These 2 options raise an error when used on Windows platform
- In which case relative
module-hide
ormodule-forbid
command is made ineffective as well as remaining content of the modulerc script hosting them - Error message is clearly seen when trying to load related modules and indicate where to find the erroneous command
--before
and--after
are also supported bymodule-hide
to phase-out modules prior to forbid their evaluation--before
and--after
accept a date time as value- Accepted date time format is
YYYY-MM-DD[THH:MM]
- If no time value is specified (just a date like
2020-08-01
), 00:00 is assumed- So
2020-08-01
is translated into2020-08-01T00:00
- So
- An error is raised if submitted date time value does not match accepted date time format
- if both
--before
and--after
options are set and before date is greater than after date- targeted module is always hidden/forbidden
- no error is returned
- Accepted date time format is
--before
and--after
options are not supported on Tcl version below 8.5- Prior 8.5,
clock scan
command does not have a-format
option - This option is required to support defined date time format
- An error is raised when
--before
or--after
options are used over a Tcl version below 8.5
- Prior 8.5,
--message
option adds additional text to the access denied error message- Newline set in text message are preserved, which could help to control text output format
- Message content is set along forbidden module specification
- Message recorded for matching module specification will be printed
- Message recorded on other matching specification will be ignored, only message from retained matching specification is printed
- Firstly evaluated
module-forbid
command that matches module specification is retained with its message property
- a module matching a
module-forbid
statement whose--after
limit is close is considered nearly forbiddennearly-forbidden
tag applies to such module- matched
module-forbid
statement should of course not be disabled for current user of group due to--not-user
or--not-group
option values - the near range is defined by the
nearly_forbidden_days
configuration, which equals to14
(14 days) by default - this configuration accepts an integer value which represents a number of days prior forbidding starts to be effective for module
nearly_forbidden_days
configuration can be set at configure time with--with-nearly-forbidden-days
option or afterward with theconfig
sub-command (which sets theMODULES_NEARLY_FORBIDDEN_DAYS
environment variable)- when evaluating a nearly-forbidden module, a warning message is reported to indicate that module access will soon be denied
--nearly-message
option adds additional text to the access will be denied warning message- Newline set in text message are preserved, which could help to control text output format
- Message content is set along nearly-forbidden module specification
- Message recorded for matching module specification will be printed
- Message recorded on other matching specification will be ignored, only message from retained matching specification is printed
- Firstly evaluated
module-forbid
command that matches module specification is retained with its message property
module-hide
andmodule-forbid
are intended to be used in modulerc files- as they impact modulefile resolution
- they also need to be enabled in modulefile context as global/user rc files are evaluated as modulefile, not modulerc
- several
module-hide
calls for the same module will supersede each other- definition with the highest hiding level wins
- which means the most restrictive call wins
- a
--hidden-loaded
status set is kept even if correspondingmodule-hide
call is not the highest one - the multiple definitions can come across different modulerc files (global, modulepath or modulefile rc levels)
- Module specification passed as argument to
module-hide
andmodule-forbid
are matched exactly against available modules- Exception made when extended_default or icase mechanisms are enabled
- Which means wildcard characters like * or ? are treated literally
- Auto symbols (@default and @latest) are adapted when a latest version is hidden
- Auto symbols are applied to this version if it is selected specifically (for instance loaded by its full name)
- Auto symbols are applied to another version when hidden latest is not selected specifically, even if specified with @latest auto symbol
- Auto-symbols cannot be set hidden
- When a defined
default
orlatest
symbol is set hidden, it is replaced by adefault
orlatest
auto-symbol targeting highest available module version - Targeting an auto-symbol with a
module-hide
command, will have no effect
- When a defined
- When module specification of
module-hide
targets:- A symbolic version
- This symbol only is hidden
- Modulefile targeted by hidden symbolic version stays visible
- An alias
- This alias only is hidden
- Modulefile targeted by hidden alias stays visible
- A modulefile targeted by either symbolic version or alias
- This modulefile is hidden and all symbolic versions targeting it
- Aliases targeting modulefile stays visible (thus resolving alias in load or whatis contexts make hidden modulefile target visible unless if set hard-hidden)
- A symbolic version
- Hidden alias or symbolic version should not appear in the list of alternative names of loaded modules
- Unless this alias or symbolic version is not hard-hidden and is used to designate the module to load
- When
default
symbolic version is set hidden- also remove parent module name from the list of alternative names
- if resolution query corresponds to parent module name, unhide
default
symbol unless if hard-hidden
- On
avail
sub-command- Hidden symbolic versions are not reported along module they target
- Unless for non-hard-hidden symbols specifically designated in search query
- A
--default
filtered search considers search query matchesdefault
symbol- So
default
symbolic version will appear in result unless if hard-hidden
- So
- Hidden symbolic versions are not reported along module they target
- Different hiding level are considered
- -1: module is not hidden
- 0: soft hiding (applied with
module-hide --soft
) - 1: regular hiding (applied with dot name module or default
module-hide
command) - 2: hard hiding (applied with
module-hide --hard
)
- Hiding threshold
- is 0 by default, which means module is considered hidden if its hiding level is greater or equal to 0
- is raised to 2 when
--all
option is applied, which means module is considered hidden if its hiding level is greater or equal to 2
Initial environment¶
Initial environment corresponds to the environment state at the end of Modules initialization.
- initialization performed by
autoinit
sub-command - which evaluates
modulespath
andinitrc
initialization files if they exist and ifMODULEPATH
andLOADEDMODULES
are both found unset or empty - environment state is composed of:
- enabled modulepaths
- loaded modules
- with manual and modulerc tags applied onto loaded modules
- with variant values applied onto loaded modules
Initial environment is what you get when you connect to a machine, with the
environment configuration (modulepaths, loaded modules) defined by the
system administrator of this machine. Plus your own addition if the
initrc
file set by system administrator calls module restore
to
load your default collection.
Persistency¶
Once defined after the evaluation of modulespath
and initrc
initialization files, the initial environment is stored in an environment
variable: __MODULES_LMINIT
.
- colon-separated list serializing content of a collection
- each element is a
module use
ormodule load
command describing the initial environment (modulepaths, loaded modules, their tags and variants) - variable is named following private name convention as it is not expected to be modified by user
Initial environment is stored as a collection in user environment to:
- use collection mechanisms to restore or view the initial environment
- stored in user environment to attach to the current shell session
Like for other __MODULES_LM*
persistency variables, :
character in
content (like tag list separator) is translated into <
character. Not to
be confused with element separator in such variable.
As what is stored in __MODULES_LMINIT
corresponds to the loaded
environment after Modules initialization, this environment is consistent
(i.e., no missing dependency for loaded modules).
reset sub-command¶
reset
sub-command enables to restore the initial environment. It
means to unuse enabled modulepaths and unload loaded modules then use initial
modulepaths and load initial modules.
General properties:
- Shortcut name: none
- Accepted option:
--force
,--auto
,--no-auto
- Expected number of argument: 0
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: yes (
unload
andload
modes)
reset
is equivalent to restore __init__
. It relies totally on
restore
sub-command that unsets current environment and restore
initial environment, like done for any collection.
Behavior of reset
sub-command can be changed with reset_target_state
configuration option.
As it evaluates modules, --force
, --auto
and --no-auto
options can
be set for reset
sub-command. But, as for restore
sub-command these
options should have no impact, as:
- collection fully describes dependencies to load, no automatic resolution needed
- current environment unload is processed module by module, no automatic resolution expected
- sticky modules are unloaded by default, no need to force unload
- super-sticky cannot be unloaded even if forced
reset
sub-command outputs Loading, Unloading, Tagging messages like
restore
sub-command. Which is the default output mode for a sub-command
triggering multiple module evaluations that cannot be guessed by user.
FUTURE: an init
tag could be applied onto loaded modules and used
modulepaths of initial environment to let users spot what parts of their
environment is from the initial one.
restore/saveshow sub-commands¶
restore
and saveshow
sub-commands respectively restore and
show the initial environment when called with the __init__
argument.
- instead of reading a collection file, the two sub-commands read the content
of the
__MODULES_LMINIT
variable - specific name
__init__
is used not to confuse with an existing collection
restore
sub-command is changed to restore initial environment when no
argument is provided in case no default collection exists. This is done to
align behavior with Lmod.
Same behavior change is applied on saveshow
sub-command: initial
environment is displayed when no argument provided and no default collection
exists.
reset_target_state configuration option¶
reset_target_state
defines targeted state of reset
sub-command.
What environment to restore.
- equals
__init__
by default, which corresponds to the behavior described above (initial environment is restored) - when set with
config
sub-command, defines environment variableMODULES_RESET_TARGET_STATE
for value persistency - other value accepted:
__purge__
: sub-command performs amodule purge
- any other value: sub-command restore designated collection (an error is obtained if no collection with such name exists)
The ability to reset to a given collection enables user to define what is
their initial environment state. Useful if they do not want to rely on the
initial environment setup by sysadmins. For instance when sysadmins do not set
a module restore
in initrc
to restore user's default collection
when user's session initializes.
Insensitive case¶
Configuration¶
- Introduce the
icase
option name- Which is made persistent through the
MODULES_ICASE
environment variable - Many people asked for separate options as applying an icase approach to a module loading context is not seen desired by everybody whereas it is in an module search context
- Defined levels of enablement are:
never
search
always
- icase option will be set by default to
never
in v4 not to change existing behaviorssearch
in v5 as it seems to be a general improvement for everybody
- A command-line switch
--icase
(short form-i
) is added- Was there in Modules 3 (for search sub-command only)
- When set, equals to an
always
icase mode
- Which is made persistent through the
- No immediate need for a
--no-icase
command-line switch- Combining configuration option and
--icase
command-line switch seems sufficient
- Combining configuration option and
Specification¶
- When enabled, match query string in a case insensitive manner
- query soFT returns soft, SOFT, soFT, SOft, sOft and so on
- In case multiple files correspond to the same icase word
- like soft, soFT, SoFt, SOFT filenames
- query SOFT returns SOFT (exact match is returned among possibilities)
- query SoFt returns SoFt (exact match is returned among possibilities)
- query SOft returns soft (highest lexicographically sorted match is returned among possibilities)
- query soFt returns soft (highest lexicographically sorted match is returned among possibilities)
- When icase is enabled for search context it applies to
- module specification passed as argument in following context:
- When icase is enabled for all context it applies to
- search context like described above
- module specification passed as argument in following contexts:
- module alias and symbolic version resolution triggered by
module-info alias
module-info version
getPathToModule
isModuleEvaluated
- the gathering of all module alias and symbolic version targeting a given module
- this is processed by
getAllModuleResolvedName
procedure - which is called by
doesLoadingModuleMatchesName
cmdModuleLoad
- this is processed by
- Note that whatis specification passed as argument to the
search
sub-command is always matched in a case insensitive manner
Corner cases¶
- When looking for the best match among loaded modules to select one module to unload, lastly loaded module, or firstly loaded module depending on
unload_match_order
configuration, will be returned- When insensitive case is enabled, last or first icase match will be returned even if an exact match is present among the loaded module list
- This behavior has an impact in case multiple available modules correspond to the same insensitive case string
- For instance iCaSe and IcAsE modules
- When
icase
is enabled on all contexts and multiple directories match same icase module name- for instance following modules exist: ICASE/1.1, icase/1.2, iCaSe/1.3 and iCaSe/1.4
- a
module avail -i icase
will sort iCaSe/1.4 as the highest entry - however a
module load -i icase
command will load icase/1.2- as icase directory matches query
- and also
module load -i ICase
command will load icase/1.2- as no directory ICase exists, result is returned from highest directory: icase
lint sub-command¶
Goal is to provide a lint
sub-command to check syntax of
modulefiles.
Configuration¶
tcl_linter
configuration option defines linter program to use and its optionsnagelfar.tcl
is the default--with-tcl-linter
and--with-tcl-linter-opts
installation options help to change this default at installation time- When changed with
config
sub-command,MODULES_LINTER
environment variable is set
- Tcl linter program defined is checked for existence by
configure
script- Use fully qualified path resolved if found
- Print a warning message if not found
- No error if not found as
lint
is not the central use case- Could be configured or installed after Modules installation
--enable-nagelfar-addons
installation option defines if Nagelfar-specific syntax databases and plugins to lint modulefiles have to be installed.- Specific syntax databases and plugins to lint modulefiles, modulerc and global/user rc are not enabled if this option is disabled
--nagelfardatadir
installation option defines where to install Nagelfar-specific files to lint modulefiles.
Sub-command properties¶
General properties:
- Shortcut name: none
- Accepted option:
--all
,--icase
- Expected number of argument: 0 to N
- Accept boolean variant specification: no
- Parse module version specification: yes
- Fully read modulefile when checking validity: no
- Sub-command only called from top level: yes
Sub-command acts similarly than edit
sub-command:
- Resolves each specification passed as argument to a single modulefile
- Modulefile could be specified with icase, extended_default and
advanced_version_spec features
- But no boolean specification, as we are looking for modulefiles, not a module variant
- Call an external command over the resolved modulefiles
In case no argument is provided, it means to select everything:
- Every global and user rc file
- Every .modulerc and .version files in enabled modulepaths
- Every available modulefiles in enabled modulepaths
- Include modules declared forbidden
- If
--all
option set also select all hidden modulefiles in enabled modulepaths
Arguments could also be a file path:
- need to distinguish if it is a global/user rc file, a modulerc or a modulefile to accurately lint designated file
- file is considered a global/user rc file if file path corresponds to user or global rc file location
- file is considered a modulerc if filename equals
.version
or.modulerc
- otherwise file is considered a modulefile
Processing is aborted as soon as one lint command execution fails
Nagelfar linting¶
- Analyze full content of designated files
- It does not evaluate files sourced by designated files
- If
--enable-nagelfar-addons
is enabled (default) a specific syntax database and plugin is added to the Nagelfar command line to lint specified file depending on its type (global/user rc, modulerc or modulefile)- Modulefile command, their options and syntaxes are checked based on this file type
- Since not the same command set can be used in global/user rc file, in modulerc and modulefile
Report output¶
- New message block:
Linting <modulefile>
- All messages produced by Nagelfar reported under modulefile message block
- Parse Nagelfar messages to report in a structured way:
<SEVERITY> line <line_number>: message
- Message is output as a block in case it consists of several lines
- All message prefix (prior
:
) is highlighted based on severity - Nagelfar severities mapped to Modules severities:
- W = WARNING (sgrkey: wa)
- E = ERROR (sgrkey: er)
- N = NOTICE (sgrkey: in)
- Output and verbosity levels:
- By default, do not output message block if no message to report for modulefile
- If verbose mode set, report empty block if no linting message
- If silent mode set, report nothing, exit code helps to know if linter has reported error
Lmod Tcl modulefile compatibility¶
- Goal is to be able to evaluate with modulecmd.tcl a Tcl
modulefile generated for Lmod
- No evaluation error
- Be as close as possible to the behavior of Lmod
- As of Modules v5.0, the following Tcl modulefile command of Lmod are not
supported:
add-property
remove-property
extensions
depends-on
prereq-any
always-load
module load-any
pushenv
require-fullname
family
add-property
/remove-property
¶
- Property mechanism of Lmod does not completely fit into Modules tag
mechanism:
- Property are first defined in a global RC file
- Then associated to a given modulefile with
add-property
command - Could be unset with
remove-property
- Defined as a key-value
- These commands will be first implemented as a no-operation command (
nop
)- No error raised if used
- And no warning message to avoid polluting output
- These commands are intended for use only within modulefile evaluation context (not within modulerc)
- FUTURE: it could be interesting to map some properties on tags like the
lmod:sticky
property which corresponds to thesticky
tag
extensions
¶
- Extension mechanism is an additional information added on
avail
andspider
sub-command output- Requires to evaluate modulefile on
avail
processing - Not used to load the modulefile declaring them when an extension name is
passed to
load
sub-command ordepends-on
modulefile command
- Requires to evaluate modulefile on
- This command will be first implemented as a no-operation command (
nop
)- No error raised if used
- And no warning message to avoid polluting output
- This command is intended for use only within modulefile evaluation context (not within modulerc)
- FUTURE: may be interesting to improve the concept by making the extension
names an alias on the modulefile declaring them
- Will automatically achieve dependency consistency this way
- Could resolve dependencies based on extension names if modulefile is
evaluated during an
avail
prereq-any
¶
- This command is an alias over
prereq
command- In Lmod,
prereq
acts as a prereq-all - Whereas on Modules
prereq
acts already as a prereq-any
- In Lmod,
- This command is intended for use only within modulefile evaluation context (not within modulerc)
require-fullname
¶
- Raise an error if modulefile has been designed with implicit or explicit
default name
- This error aborts modulefile evaluation
- Occurs for instance if
foo/1.0
is loaded withfoo
orfoo/default
name - Which means
require-fullname
has precedence over explicitly set default version - If an alias or a symbolic version (other than
default
) point to the modulefile, no error occurs if modulefile is designated using these alternative names.
require-fullname
is implemented to only apply on load evaluation mode- On Lmod, it applies on load, unload, and display modes
- It seems important not to apply the constraint on unload and display modes to ease user's experience
- This command is intended for use only within modulefile evaluation context (not within modulerc)
depends-on
¶
- Auto load one or more modules said as dependencies when modulefile is
evaluated in load mode
- Corresponds to the Requirement Load module auto handling mechanism.
- Semantically this command corresponds to a requirement declaration.
- Make it an alias over
prereq
but with each argument set as a prereq*all not a prereq-any. - If
auto_handling
option is disabled, requirement will not be loaded and an error is raised. This will be different than Lmod as with Modules the modulefile commands defines the semantic (this is a dependency) then the automation is defined by the module command configuration, not by the modulefile like done in Lmod.
- Auto unload the dependency modules when modulefile is unloaded if no other
loaded module depends on them
- Corresponds to the Useless Requirement Unload module auto handling mechanism
- Like for load evaluation, automation is configured at the module command level, not by individual modulefiles
- This command is intended for use only within modulefile evaluation context (not within modulerc)
always-load
¶
- Auto load on or more modules said as dependencies when modulefile is
evaluated in load mode
- Semantically this command corresponds to a requirement declaration.
- Make it an alias over
module load
- Add
keep-loaded
tag to the modules loaded this way - When several modules are specified, it acts as an AND operation, which means all specified modules are required
- When modulefile is unloaded, the always-load modules are not automatically
unloaded as they own the
keep-loaded
tag - This command is intended for use only within modulefile evaluation context (not within modulerc)
module load-any
¶
- Auto load first valid module in a list when modulefile is evaluated in
load mode
- Semantically this command corresponds to a requirement declaration.
- Acting as an OR operation
- Evaluation stops after first module in list loaded
- Whether called from a modulefile evaluation context or from top evaluation context
- Different than Lmod that apply the
load
sub-command behavior when called from top evaluation context and does not stop after first modulefile loaded
- If the evaluation of first module to load in list ends in error
- When called from a modulefile evaluation context
- Error is silenced
- Next module in list is tried
- It behaves this way like a
prereq
command with auto_handling mode enabled - Proceed this way whatever the auto_handling state
- Different than Lmod that aborts modulefile evaluation
- Otherwise when called from top evaluation context
- Error message is reported
- Next module in list is tried
- Different than Lmod that aborts processing
- When called from a modulefile evaluation context
- If first modules to load are unknown
- No message reported
load-any
continues until finding a module in the specified list
- If a module in the list is already loaded
- When called from a modulefile evaluation context
load-any
is not performed as requirement is considered already satisfied- Better cope this way with the expressed requirement
- It behaves this way like a
prereq
command - Proceed this way whatever the auto_handling state
- Different behavior than Lmod that still proceed to load the module in the list from the left to the right until loading one or finding one loaded
- Otherwise when called from top evaluation context
- An attempt to load first module in list is still issued
- And pursued from left to right until loading one module or finding one loaded
- When called from a modulefile evaluation context
load-any
acts similarly totry-load
but with an OR operation behavior instead of an AND operation- An error is obtained if none of the listed modules can be loaded if none of their load attempt generated an error message
- If no argument is provided an error is obtained, like done for
try-load
- When modulefile is unloaded, an attempt to unload all specified module is
made
- Correspond to the behavior of a
module unload
- Modules which are still depended by other loaded modules will not be unloaded
- Correspond to the behavior of a
- This command is intended for use only within modulefile evaluation context (not within modulerc)
module try-load
¶
try-load
sub-command and modulefile command has been introduced in Modules version 4.8.try-load
modulefile command acts as an individualprereq
for each modulefile specified.- Each modulefile specified are considered optional requirement, as no error
is raised if they cannot be loaded.
- An update is made on version 5.2 to record each modulefile specified on
try-load
as optional requirement even if their load attempt did not succeed. - With this change, if the optional requirement is loaded later on, the
module declaring the
try-load
command will be automatically reload (ifauto_handling
is enabled) to take the new availability of its optional requirement into account.
- An update is made on version 5.2 to record each modulefile specified on
family
¶
- Defines membership in family name and ensures that only one member of a
given family is currently loaded.
- Semantically this command corresponds to the definition of both:
- a conflict on family name
- a module alias name over currently loading module
- Semantically this command corresponds to the definition of both:
- Also defines the
MODULES_FAMILY_<NAME>
environment variable set to the currently loading module name minus its version number.- As family name is used in environment variable name, it requires that name should only use characters that are accepted there
- Accepted characters for family name are [a-zA-Z0-9_]
- An error is generated in case other kind of characters are found in specified family name
- The
LMOD_FAMILY_<NAME>
environment variable is also set in addition toMODULES_FAMILY_<NAME>
and set to the same value. This way existing scripts or modulefiles relying on this variable do not need to be changed to be compatible with Modules. - When modulefile is unloaded, the
MODULES_FAMILY_<NAME>
andLMOD_FAMILY_<NAME>
environment variables are unset - This command is intended for use only within modulefile evaluation context (not within modulerc)
pushenv
¶
- Sets an environment variable with a value specified as argument but saves the previous value set to restore it when modulefile is unloaded.
- Use a
__MODULES_PUSHENV_<VAR>
environment variable as a stack to record the previous values of environment variable<VAR>
.- Each element in this Modules-specific variable is the combination of the
currently evaluating modulename and pushed value.
- Combination joined with the ampersand character
- Each element in variable separated by colon character
- When unloading, the value set by this module is removed not the value on top of the list.
- Different than Lmod that restores the value on top of the stack even if unloading module were not the one defining the top value currently in use.
- Each element in this Modules-specific variable is the combination of the
currently evaluating modulename and pushed value.
- When saving value set before any module
- An empty module name is used to push to the stack.
- When restoring this initial value, initial entry in stack is also cleared (as no other module unload will unset it).
- It is not expected that for the same environment variable,
pushenv
is mixed with:setenv
,unsetenv
append-path
,prepend-path
,remove-path
- These other modulefile commands clear the pushenv stack environment
variable (like
setenv
/unsetenv
clear the reference counter environment variable of the*-path
commands)
- It is not expected that
pushenv
is called multiple times for the same environment variable in the same modulefile- Inconsistent results may be obtained if environment variable value is used in modulefile to set other variables.
- Especially that unload evaluation of modulefile will not process the
pushenv
commands in the reverse order but in the script order. - When checked during modulefile evaluation, lastly defined value remains
- However the operation is consistent at the end of modulefile evaluation, as all values are withdrawn from stack and a value defined somewhere else is restored.
- pushenv stack environment variable correctly handles multiple entries coming from same modulefile, even multiple identical values.
- For Lua modulefiles, Lmod handles a specific
false
value which clears environment variable- Lmod does not implement this for Tcl modulefile
- Maybe because
false
cannot be distinguished from any other value - So this specific behavior is also not supported on Modules
- This command is intended for use only within modulefile evaluation context (not within modulerc)
Module magic cookie check¶
A file should start with a specific string as header line to be considered as
a modulefile. This specific string is called the magic cookie and is equal to
#%Module
optionally followed by a version number to indicate the minimum
version of modulecmd.tcl
required to interpret this file.
Magic cookie applies to modulefiles and module RC files. More recently it also
applies to the initrc
configuration file and collections.
Magic cookie is checked in two different situations:
- When searching for a modulefile: all files located under a directory used as a modulepath are checked to determine if they are modulefiles to take them into account in the module search.
- When evaluating a modulefile: when reading file to pass it down to the modulefile or modulerc interpreter, the magic cookie is checked to ensure file can be evaluated.
The mcookie_check
configuration option is introduced to be able to
disable the magic cookie check. Option accepts the following values:
always
: This is the default value, magic cookie is checked in both situations described aboveeval
: magic cookie is only checked prior evaluating file, not when searching for modulefiles
The mcookie_check
option works like the icase
option
with value determining a level of cumulative support.
FUTURE: a third value, never
, may be interesting to disable the magic
cookie check in all situations.
Skipping check when searching modules¶
When setting mcookie_check
to eval
, module magic cookie is not
checked when analyzing the files located under an enabled modulepath. This
mode significantly diminishes the I/O load when looking at the content of a
modulepath as files are not opened and header read for the check.
This mode requires a perfect control on the files located within the hierarchy of the modulepath directories as:
- non-modulefiles will be considered modulefiles and will be reported in module search results and used to locate a module corresponding to a query
- files hidden through restrictive permissions are reported in search results and used to locate a module corresponding to a query
For these non-modulefiles or read-protected files an error is obtained when trying to evaluate them, as the magic cookie is checked at this step.
Also the files specified full path are not checked prior evaluation if
mcookie_check
is set to eval
, so if these files are not modulefile an
error will be obtained when trying to evaluate them.
The eval
mode of mcookie_check
configuration option has no impact on
the initrc
configuration file and collections as such files are not
searched like modulefiles. Their header is only checked at evaluation time.
Implementation of eval
mode¶
Modulefiles or modulercs are read through the readModuleContent
procedure
which is called by:
execute-modulerc
orexecute-modulefile
procedures when files need to get fully read to get evaluatedcheckValidModule
procedure to verify file is a readable modulefile when search for modules
The checkValidModule
procedure is the one to update when mcookie_check
configuration option is not set to always
as this procedure is called by
all module search contexts. It is called by:
findModules
to check files in directories within modulepathsgetModules
to check files pointed by mfcmd:module-virtualgetPathToModule
to check files transmitted as full path file
Note
File readability (permission check) is not verified when
mcookie_check
option is set to eval
to keep the full benefit of
this mode regarding the I/O load optimization.
mod-to-sh sub-command¶
Produce shell code of environment changes made by loading designated modulefiles and send this content to the report message channel. User views the produced shell code as output.
mod-to-sh
could be send as the opposite of sh-to-mod
. The
former transforms a modulefile into shell code whereas the latter transforms
shell code into a modulefile.
Configuration¶
None.
Sub-command properties¶
General properties:
- Shortcut name: none
- Accepted option:
--force
,--icase
,--auto
,--no-auto
- Expected number of argument: 2 to N
- Accept boolean variant specification: yes
- Parse module version specification: yes
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: yes (
load
mode)
Arguments expected:
- First argument should be a supported shell name
- like bash or fish
- An error is produced if an unsupported shell is specified
- It defines the language that sub-command will use to produce shell code
- After the first argument, comes the modulefile specification
- Multiple modulefiles can be specified
- With advanced version specifiers and variants
- It defines the modulefiles to load
mod-to-sh
loads designated modulefile(s) and instead of rendering the
corresponding environment changes to the stdout channel, the shell code is
sent to the message report channel (stderr).
Target shell is changed, from the one specified as argument to
modulecmd.tcl
script to the one specified as argument to mod-to-sh
sub-command.
Once shell code is produced and sent to the message channel (stderr), target
shell defined for modulecmd.tcl
is restored to get on the regular
code channel (stdout) the evaluation status. For instance for sh shell:
test 0
if successful, test 0 = 1
otherwise.
Shell code produced by mod-to-sh
is only sent to message channel. It is
not sent to the code channel.
modtosh_real_shell
state is introduced and set by mod-to-sh
sub-command. When defined, shell code rendering procedure knows if code should
be sent to the message channel and then cleared, not to be rendered on code
channel. This state contains the target shell of modulecmd.tcl
. So
shell rendering procedure can restore target shell then produce the final
shell code to render (evaluation status).
Modulefile evaluation is made like a regular module load
. Thus if
specified modulefile is already loaded, its corresponding environment changes
will not appear on the mod-to-sh
result.
Shell code produced for mod-to-sh
is filtered to only contain environment
changes of designated modulefiles and not the Modules-specific environment
context (like LOADEDMODULES
or _LMFILES_
environment variables).
mod-to-sh
sub-command automatically adjusts the verbosity
configuration option to the silent
mode. As produced shell code is sent
to the message channel, it should not mix with report messages. Setting
verbosity to silent
disables loading messages or reportWarning
,
reportError
and puts stderr
messages defined in
modulefiles. verbosity
is not changed if set to trace
mode or
any higher mode (debugging).
module-info command¶
As mod-to-sh
leads to modulefile evaluation, the module-info
command
modulefile command returns the mod-to-sh
string
when used in a modulefile evaluated through this sub-command. It can also be
queried against this command name string to return Boolean value depending if
mod-to-sh
is the sub-command currently running.
Module cache¶
Objective is to consolidate available module information in a few number of
files in order to process these files when doing global module queries like
done by avail
or whatis
sub-commands instead of walking
through the whole modulepath directories to compute this information.
With cache files, it is expected to have lesser IO load and more efficiently handle environments with thousands modulefiles stored in a parallel filesystem.
How to store cache¶
Module cache will be a file aggregating available module information. Module
are organized into modulepaths that are enabled in user environment. Goal is
to have one module cache file per modulepath. This file will be stored under
the modulepath root with the .modulecache
file name.
Depending on modulepath ownership, modulepath may or may not have a cache file built. It seems more efficient to save cache on a per-modulepath basis as a user may enable diverse modulepaths, some of them not maintained by the admins of the machine they are running on.
Having a central system cache may miss some user-managed modulepaths.
Having a per-user cache file does not seem a good idea. If built for the user, a lot more information may be pre-processed: dynamic information from the modulerc files for instance may be processed at cache file creation, not when using the cache file. But it cannot be expected from the user to build its cache and keep it up to date. Having the cache on the user side can lead to additional issue with users complaining to the support that they cannot find a given module, but due to an outdated cache file.
In definitive, there will be one cache file per modulepath directory.
Cache content¶
As cache files should be used instead of walking through modulepath directory
to search for valid modulercs and modulefiles. Cache file should contain
everything to be autonomous to proceed avail
or whatis
queries.
Yet module search can be very dynamic as things set for instance in modulerc files may dynamically produce new modulefiles or define properties specific to some users or groups.
So the produced cache file cannot be the static view generated for the user who has built the cache file. Thus dynamic shaping is preserved by storing scripts and commands in the cache file.
Modulerc files may be highly dynamic so their full content is purely saved into the cache file. An entry is set for each valid modulerc file. Same goes for modulefiles as some conditional structure in their code can dynamically change dependency, whatis or other definitions.
It is expected that modulefile will be evaluated on avail
or whatis
commands for complex queries. So for such use case it is important to have
modulefile content cached.
Thus by reading the cache file, in one IO the content of all the modulerc and modulefiles of the modulepath will be fetched.
Goal is to record in cache file every information obtained as a result of
findModules
procedure. Thus cache file contains modulefile modification
times, which is reported on --long
output. Modulefile validity check
result is also recorded if modulefile is not valid. Modulerc validity check
is not recorded as it is not an information produced by findModules
.
Note: modulercs and modulefiles are not tested when generating cache file to see if they are valid, if their code is correctly executed. Their bare content is recorded. Same result is obtained this way whether a cache file is used or not.
Cache format¶
Goal is to make the cache file a Tcl script, like modulefiles. It will not be exactly a modulefile as specific commands will be setup to evaluate cache file and cache file will not make use of modulefile commands. See Cache evaluation section for details on how a cache file is evaluated.
Cache file starts with a #%Module
string like modulefiles. A version
number is appended next to these first characters (for instance
%Module5.3
). See Cache validity section for details on the cache file
prefix string.
Modulefile content in modulepath is defined in cache with the
modulefile-content
command. Which takes in this order:
- relative file path
- file last modification date (as a Unix epoch time)
- file module header
- file body content.
For instance:
modulefile-content foo/1.0 1234567890 #%Module {body}
- or
modulefile-content {foo/w s} 1234567890 #%Module5.2 {body}
Similar command for modulerc: modulerc-content
which accepts following
syntax:
- relative file path
- file module header
- file body content.
For instance: modulerc-content foo/.modulerc #%Module {body}
. Modification
time is not needed for modulerc as this information is not reported on an
avail
sub-command in long mode.
Every modulercs and modulefiles file contained in modulepath are recorded
in cache with modulerc-content
or modulefile-content
command.
Modulefiles whose name start with a dot character are also recorded in cache.
Invalid modulefiles are recorded in cache file through modulefile-invalid
command rather modulefile-content
. It accepts following arguments:
- relative file path
- invalidity kind
- error message
For instance: modulefile-invalid foo/2.0 invalid {Magic cookie '#%Module'
missing}
Files or directories that have limited access are recorded with specific commands:
limited-access-file foo/1.0
limited-access-directory foo
Limited access means for a file that it cannot be read by user that builds cache or other users. For a directory it means that it cannot be either read or searched by user that builds cache or other users.
A modulefile or a modulerc is not recorded with modulefile-content
or
modulerc-content
if file or one of its parent directory has limited
access. This way only content that can be read by everyone is recorded into
cache file. Sensitive information are excluded from cache file.
Note: a cache file generated by a privileged user (which has access to every thing) and a cache file generated by a less privileged user will be the same as limited-access information will not be included in cache file.
Files or directories recorded as limited access will need to be tested (and walked down for directories) when cache file will be evaluated. It is important to distinguish files from directories to save some file stat test to determine if an element is a directory when limited access elements will be tested. No need for files to distinguish modulefile from modulerc as this difference is visible with file name.
Note: Limited access tests are skipped on Windows platform as Unix-style file permission cannot be tested there.
Recording full modulefile content or subset of elements¶
It was initially drafted that only a subset of element of modulefiles would be recorded in cache file, to reduce size of this file and reduce its evaluation time.
Recording full modulefile content is in the end preferred as:
- this solution is simpler to implement
- cache file size is not too big in the end (~ hundreds of KB for a thousand of modulefiles)
- evaluation time of large cache file is acceptable (time taken to evaluate cannot be noticed by user)
- simpler to understand and manage for sites
Producing a cache entry for a modulefile with only a subset of commands recorded (like variant or requirement) is only feasible for modulefiles not using conditionals or specific evaluation scheme. Recording full content will work in any scenario whereas recording a subset limits cache usage. Moreover it is hard to determine, depending of the modulefile set, where cache can be used or not if only a subset of elements is recorded.
Cache validity¶
Cache file header indicates a Modules version number. It corresponds to the Modules version:
- the cache file has been built with
- the cache file is compatible with
It seems reasonable to ask for a cache file update every time Modules is upgraded to a newer minor version (for instance from 5.3 to 5.4):
- it is simpler to understand for staff and user when the cache is taken into account, when it is ignored
- better to ensure cache file is accurate for the Modules version as modulerc and modulefile commands may evolve from one version to another
Cache usage¶
Any time a modulepath directory is opened to get its content, the module cache file will be used instead if available.
Modulepath content analysis is performed by findModules
procedures. So
any sub-command calling it (directly or through getModules
or
getPathToModule
) will use the cache file. It corresponds to the following
sub-commands:
- lint
- paths
- search
- whatis
- aliases
- avail
- switch
- restore
- save
- display
- path
- source
- load
- test
- edit
- help
It may also occur during other sub-commands that evaluates modulefiles using
the is-avail
command: like unload or refresh.
Cache files are ignored if ignore_cache
configuration option is
enabled. This option can also be enabled just for one execution with the
--ignore-cache
command line option.
Cache files are ignored if cache expiry mechanism is enabled through the
cache_expiry_secs
configuration option. When this option is set to
0, it means a cache file never expires. This is the default behavior. If set
to something else, cache file is expired if its last modification time is
older than the number of seconds defined in cache_expiry_secs
. Option
value is an integer between 1 and 31536000, which is the number of seconds
during 1 year.
Is there an impact at evaluating the full cache file rather making a directory walk-through to find a module? Cache file is fully read, but not all the files described in it are evaluated. Just those corresponding to the search, like it is done when walking modulepath directory and evaluating only the modulerc files corresponding to the query. So results between using cache file or not should be the same: compared to a search without cache, no extra modulefile or modulerc evaluation will be performed when a cache file is used.
As cache is recorded with both mcookie_check
and mcookie_version_check
options enabled, these two options are not honored (if disabled) when a cache
file is used. They are primarily useful to skip I/O tests when walking through
the content of a modulepath directory. As these I/O tests are done during the
cache build process, the options are useless when using cache files.
When cache file is not in sync¶
Files or directories are freely available through cache when used even if after cache being built:
- their access is limited
- they are deleted
- their content changes and is not anymore valid
When files or directories have their access limited prior building cache, but afterward these access limitations are lifted. These elements will require an access test to check if they are available. This test will always be successful as element accesses are not anymore limited.
If files or directories do not exist when cache is built, they will not be found when cache is used.
If modulefile is recorded in cache as invalid, it will stay invalid if cache is used even the modulefile is fixed. Cache need to be regenerated.
Read/write performances¶
cache_buffer_bytes
configuration option defines size of the buffer
when reading or writing cache files.
With a bigger buffer, fewer read or write system calls are needed to read or write cache file. On busy storage systems it can improve I/O performances.
Cache evaluation¶
A Tcl sub-interpreter is created to analyze cache files. This sub-interp is
setup to evaluate cache file-specific commands, like modulefile-content
.
When evaluated, modulefile-content
, modulerc-content
and
modulefile-invalid
commands populate the read cache structure of modulerc
and modulefiles. This way when the modulefile for instance need to be read,
its content is already found in memory cache structure. It corresponds to the
following global variables:
::g_modfileContent
::g_fileMtime
(only for valid modulefile)::g_modfileValid
(only for modulefile, valid or not)
In addition a ::g_cacheModpath
array is filled with an entry dedicated for
each modulepath. The content of this entry mimics the result list returned by
findModules
procedures with information for the whole content of the
modulepath.
Limited access files and directories described in cache by
limited-access-file
and limited-access-directory
commands populate
specific structures to indicate some entries in modulepath have to be tested
(and walked down for directories) to determine if they are available to
current user:
g_cacheFLimitedModpath
g_cacheDLimitedModpath
These two structures are arrays with one entry per cached modulepath. Limited
access entries are tested if they match search query. Test is done through
findModulesFromDirsAndFiles
procedure which corresponds to the walk down
code extracted from findModules
.
This specific interpreter is re-used between different cache file evaluations. As for modulefile interpreter, a consistency check is performed before each reuse to test that the cache file-specific commands have not be rewritten during previous cache file evaluation.
Cache file evaluation is tracked to avoid evaluating twice the same cache file.
Cache evaluation stops if an erroneous command or syntax is encountered. Like
for erroneous modulerc, error is not reported during avail
or whatis
commands unless if ran in debug mode. Error is reporting during a load
evaluation. Cache evaluation is considered failed if there is an error in the
cache file, thus a non-cache module search will occur instead of relying on
cache module listing. However descriptions of modulefile and modulerc
evaluated in cache prior the error occurs are retained.
cachebuild sub-command¶
cachebuild
sub-command creates a module cache file in modulepaths.
Without arguments, it attempts to create cache in every enabled modulepaths
where running user has the right to write. If arguments are provided, cache
is build in the directories pointed by these arguments.
General properties:
- Shortcut name: none
- Accepted option: none
- Expected number of argument: 0 to N
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: yes (
cachebuild
)
An error is returned for each specified directories where current user has no write access.
An error is returned if a modulefile or a modulerc cannot be read. This error ends cache content generation for current modulepath. Build continues with next modulepath after this error.
Modulepaths where current user has no write rights are skipped and reported with a warning notice.
Reports a Creating <modulepath>
block header message for each cache file
created or updated. This report is made when verbosity is set to normal
or higher mode.
mcookie_check
and mcookie_version_check
options are both
enabled when recording cache. This is produced with exact same content whether
these options are enabled or not.
cacheclear sub-command¶
cacheclear
sub-command deletes all module cache file in enabled
modulepaths.
General properties:
- Shortcut name: none
- Accepted option: none
- Expected number of argument: 0
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: no
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: no
Modulepaths where current user has no write rights on the modulepath directory are skipped and reported with a warning notice.
Reports a Deleting <modulepath>
block header message for each cache file
created or updated. This report is made when verbosity is set to normal
or higher mode.
Module selection contexts¶
Description of the different contexts where a module is expressed to get resolved to modulefiles.
Module identification to select one module¶
- specification expresses exactly one module
- must qualify version to select in case a module has multiple versions
- expression may
- be absolute like mod/version
- be relative to the modulefile currently being evaluated like ./version or /version
- refer to symbolic version or module alias
- specification used to resolve argument passed to the following commands:
module-version
module-alias
module-virtual
(cannot use symbolic version or module alias, should define an actual module)module-info symbols
module-info version
module-info loaded
- relies on
getModuleNameVersion
procedure to get absolute name
Module version specification to return all matching modules¶
- specification expresses one or multiple modules
- expression may
- be absolute like mod/version
- refer to implicit or explicitly defined default version like mod
- refer to extended default version like mod/1 (to refer to mod/1.1.1)
- refer to symbolic version or module alias
- specify multiple versions as list (mod@1,2) or range (mod@:1 or mod@1:2)
- refer to a variant specification (with or without a module name specification)
- all modules matching specification are retrieved with
getModules
- specification used to resolve argument passed to the following commands:
avail
paths
whatis
list
(matching specification retrieved from loaded modules, notgetModules
)
- used to get all alias and symbolic version of loaded modules treated by:
list
- used to get all existing aliases and symbolic version (no module specification) by:
aliases
- used to get all existing modulefiles (no module specification) by:
search
Module version specification to select one module¶
- specification expresses one or multiple modules
- relies on the module version specification to return all matching modules
- then among matching modules, one is selected with
getPathToModule
:- the one set has the default version (also called the explicit default version)
- or the highest version in case no explicit default is found among results (also called the implicit default version)
- nothing is returned in case no explicit default is found among matching modules and implicit default version mechanism is disabled
- module selection may trigger another match retrieval
- for instance in case selection leads to an alias that resolves to a bare module name
- specification used to resolve argument passed to the following commands:
load
unload
(with attempt to match against loaded modules to resolve argument)switch
help
test
display
path
is-avail
- used to resolve aliases or symbolic versions treated by following commands:
paths
search
Module version specification to check compatibility¶
- specification expresses one or multiple modules
- expression may
- be absolute like mod/version
- refer to implicit or explicitly defined default version like mod
- refer to extended default version like mod/1 (to refer to mod/1.1.1)
- refer to symbolic version or module alias
- specify multiple versions as list (mod@1,2) or range (mod@:1 or mod@1:2)
- version specification is matched against loaded or loading modules with variety of procedures:
getLoadedMatchingName
getLoadedWithClosestName
isModuleEvaluated
- specification used to resolve argument passed to the following commands:
is-loaded
info-loaded
prereq
conflict
- for prereq command when version specification does not have a match among loaded or loading modules
- version specification is used to select one module per module specification
- for instance
prereq mod@:1.8 mod@1.10
triggers load tentative of default version among mod@:1.8 then if this tentative fails load of mod@1.10 is attempted - another example with
prereq mod mod@1.10
, which triggers load tentative of mod/default then if it fails load of mod@1.10 is attempted
Module tags¶
Configuration¶
- No specific configuration
Specification¶
- Introduce one new modulefile command to set tags on modulefiles:
module-tag
- A tag is a piece of information associated to individual modulefiles
- That is reported along module name on
avail
orlist
sub-command results - This piece of information could lead to specific behaviors when handling modulefile over the different module sub-commands or modulefile evaluation modes
- For instance, a module with a
sticky
tag set on it cannot be unloaded
- For instance, a module with a
- Tag may also be set manually with the
--tag
sub-command option- Applies to
load
,try-load
,load-any
andswitch
sub-commands - When directly used from the terminal session or within modulefile
- Applies to
always-load
,depends-on
,prereq
,prereq-all
andprereq-any
modulefile commands
- Applies to
- 3 different kind of tag exist:
- Those inherited from module state, consequence of a specific modulefile command or module action
- This kind of tag cannot be defined with the
module-tag
command- An error is returned otherwise
- Specific modulefile command should be used instead as such tag may have specific properties that should also be defined along
- Easier for everybody to only have one way to define such tags and not 2 different commands
- Every tag holding specific properties should have its dedicated modulefile command to define it
- This kind of tag cannot be defined with the
- Those set with
module-tag
or--tag
option that lead to a specific behavior - Those set with
module-tag
or--tag
option that are purely informational, no specific behavior
- Those inherited from module state, consequence of a specific modulefile command or module action
- Tags inherited from module state:
hidden
: module not visible, not reported by default inavail
result (tag acquired throughmodule-hide
)hidden-loaded
: loaded module not reported by default inlist
result (tag acquired throughmodule-hide --hidden-loaded
or--tag
option)forbidden
: module that cannot be loaded (tag acquired throughmodule-forbid
)nearly-forbidden
: module that soon cannot be loaded (tag acquired throughmodule-forbid
)loaded
: loaded moduleauto-loaded
: module automatically loaded by another module
- Tags set with
module-tag
or--tag
option associated to a specific behavior:sticky
: loaded module cannot be unloaded unless forced or reloaded or when restoring a collection or initial environment (see Sticky modules)super-sticky
: loaded module cannot be unloaded even if forced, it stills can be unloaded if reloaded afterward (see Sticky modules)keep-loaded
: auto_handling mechanism does not unload auto-loaded module
- Tags inherited from module state cannot be set with
module-tag
command- An error is otherwise thrown
- Tags inherited from module state cannot be set with
--tag
option- Exception made for
hidden-loaded
tag - An error is otherwise thrown
- Exception made for
- Modules project may introduce in the future new tags inherited from new states or new specific behaviors
- These new tags will supersede tags set by users using the same naming
Defining¶
module-tag [options] tag modspec...
- Apply
tag
to all modules matchingmodspec
module specification - Advanced module version specifiers are supported if relative module option is enabled
- Full path module specification is not supported, as modulerc are not evaluated when reaching a modulefile specified as full path
- One tag could be applied to multiple module specifications with a single
module-tag
command call
- Apply
module-tag
accepts the following options:--not-user
: specify a list of users unaffected by specified tagging--not-group
: specify a list of groups whose member are unaffected by specified tagging
--not-user
and--not-group
specification is only supported on Unix platform- These 2 options raise an error when used on Windows platform
- In which case relative
module-tag
command is made ineffective as well as remaining content of the modulerc script hosting them - Error message is clearly seen when trying to load related modules and indicate where to find the erroneous command
module-tag
is intended to be used in modulerc files- to be easily fetched during
avail
sub-command processing - they also need to be enabled in modulefile context as global/user rc files are evaluated as modulefile, not modulerc
- it enables to dissociate environment changes described in the modulefile from the properties of this modulefile
- as these properties are usually site-specific
- and modulefile are automatically generated by a build tool
- but properties are not always related and set by the build tool
- to be easily fetched during
module load --tag tag modspec...
- Apply
tag
to the loading module selected throughmodspec
module specification - Available from all loading module sub-commands (
load
,try-load
,load-any
andswitch
) - Option is preferably written:
--tag=tag
when called from command-line--tag tag
when called from modulefile- but both syntaxes work from both locations
- Multiple tags can be set at once by providing a tag list separated by
:
- e.g.,
--tag foo:bar
or--tag=foo:bar
- e.g.,
- Apply
Persistency¶
- The
__MODULES_LMTAG
environment variable holds all tag information applying to loaded modules- Following the same syntax scheme than
__MODULES_LMCONFLICT
- For instance
module/vers&tag&tag:module2&tag
- Following the same syntax scheme than
- The
loaded
tag is not recorded in__MODULES_LMTAG
environment variable- As it obviously applies to all loaded modules defined in
LOADEDMODULES
environment variable
- As it obviously applies to all loaded modules defined in
- The
auto-loaded
tag is now recorded in__MODULES_LMTAG
environment variable- Before version 5.0, this tag was not recorded and auto loaded modules where listed in the
__MODULES_LMNOTUASKED
environment variable - This environment variable has been removed in Modules 5.0
- Before version 5.0, this tag was not recorded and auto loaded modules where listed in the
- Tags applied to loaded modules are saved in collection
- Saving tags in collection is introduced in Modules 5.1
- When one or more tags are set on a module to save, the
--tag=tag1:tag2
option is added- After
module load
- And before module specification
- After
- When option
--tag=
is found on a module to restore- Defined tags are transmitted to apply them to the module to load
- With this change, the
--notuasked
option used in collection previously to indicate module has been auto loaded is replaced by--tag=auto-loaded
option - No difference is made between tags set manually (through
--tag
option) or tags set in modulerc (throughmodule-tag
or loaded module states): both kind of tags are recorded in collection
- The
collection_pin_tag
configuration option determines what tags should be recorded in collection- When disabled (default), only the tags set through
--tag
option or resulting from the way the module has been loaded (auto-loaded
andkeep-loaded
tags) are recorded in collections - When enabled, all tags applying to modules are recorded
- Exception made for
nearly-forbidden
tag, as its temporal meaning is not fit for being saved - Changing default value of
collection_pin_tag
defines theMODULES_COLLECTION_PIN_TAG
variable
- When disabled (default), only the tags set through
- The
__MODULES_LMEXTRATAG
environment variable holds all tags applying to loaded modules that have been set through the--tag
option- It helps to distinguish these specifically set tags from the others
- To only record these tags and those resulting from the way the module
has been loaded (like
auto-loaded
) in collections by default - The following tags set with
--tag
option but which describe a specific state of loaded module are excluded from__MODULES_LMEXTRATAG
record:auto-loaded
keep-loaded
- When a collection saved with
collection_pin_tag
option enabled is restored all tags set are then considered extra tags (as they are found set through the--tag
option).
Reporting¶
- Defined tags are reported on
avail
andlist
sub-command results- Reported along modulefile name, within angle brackets (following the HTML tag fashion)
- Each tag separated by a colon
- For instance
module/version <tag1:tag2>
- Tags are right-aligned on each column
- One space character at least separates module name and version or list of symbolic version from tag list
- Defines tags are reported on module evaluation message block
- Applies to Loading, Unloading, Refreshing, Tagging message blocks
- Only for the module designation set in the header of the block
- Not on the error message, or list of requirement loaded/unloaded
- To avoid overloading the output
- Tags are reported the same way than on
list
sub-command - If load evaluation fails, the tags are not reported as they were not yet set
- Tags applying to module alias are reported on
avail
reports only- Where the module alias stands for itself in the report
- On
list
reports, alias is reported along its modulefile target- So the tags applying to the alias are not reported
- Also these tags of the alias are not inherited by alias' target
- Tags applying to symbolic version are never reported
- As symbols are never reported alone on
avail
orlist
reports - Always reported along their modulefile target
- Also these tags of the symbolic versions are not inherited by symbol's target
- As symbols are never reported alone on
- Some tags are not reported on
avail
output:hidden-loaded
: correspond to hiding module from loaded list, not from available list
- Some tags are not reported on
list
output:loaded
: as every modules reported onlist
are loadedforbidden
: forbidden module cannot be loaded, so it cannot be found among loaded module listhidden
: correspond to hiding module from availabilities, not from loaded list
- When reported in JSON output format
- tags are listed under the
tags
key
- tags are listed under the
- Default
--long
report does not contain tag information- Not to exceed the 80-column output limit by default
Abbreviations¶
- Tag abbreviations are used to translate tag names when reporting them on
avail
orlist
sub-command output - The
tag_abbrev
configuration defines the abbreviations to apply to each tag- Set by default at configure time to
auto-loaded=aL:loaded=L:hidden=H:hidden-loaded=H:forbidden=F:nearly-forbidden=nF:sticky=S:super-sticky=sS:keep-loaded=kL
- Note that by default, hidden and hidden-loaded tags share the same abbreviation, as they operate on separate contexts (respectively avail and list contexts)
- Configuration value consists in a
key=val
pair value, each key pair are separated by a:
character- Follow the same syntax than
colors
configuration
- Follow the same syntax than
- If an existing tag name is not part of the configuration, it means no abbreviation applies to it
- If a tag name has an empty string abbreviation defined it is not reported
- Unless if there is an SGR color configuration defined for this tag
- The
MODULES_TAG_ABBREV
environment variable is used to set a specific value fortag_abbrev
configuration- If
MODULES_TAG_ABBREV
is set to an empty string, no tag abbreviation applies
- If
- Set by default at configure time to
- In case default value or environment value of
tag_abbrev
is badly set- a warning message is returned
- value is ignored
- if nor the environment nor the default value is correct then no abbreviation applies to tag
- Tags are not translated to their defined abbreviation in JSON output format
SGR¶
- If a tag name or tag abbreviation has an SGR code defined in the color list, this SGR code is applied to the module name this tag refer to
- Tag name or abbreviation is not reported by itself in this case
- As it is now represented by the SGR applied to module name
- If an abbreviation exists for a tag, SGR code should be defined for this abbreviation in color list
- An SGR code set for tag full name does not apply on the abbreviation of this tag
- If multiple tags apply to the same modules and have an SGR code defined for them in the color list
- All these SGR codes are rendered one after the other over the module name
- For instance if 2 tags apply, the first one will be rendered over the first half of the module name, the second tag over the second half of
- Tags use by default background color change to stand out
- As module kind (alias, directory, etc) is mainly represented with foreground color change by default,
- In case if there are more tags to graphically render than character in module name
- The remaining tags are reported by there name or abbreviation and SGR applies over this name or abbreviation
- The
MODULES_TAG_COLOR_NAME
environment variable is used to define the tags whose name (or abbreviation if set) should be reported- Their name does not vanish if a SGR code is defined in the color list for them
- Their SGR code is not rendered over the module name
- Instead the SGR is applied to the reported tag name (or tag abbreviation if set)
MODULES_TAG_COLOR_NAME
is bound to thetag_color_name
configurationMODULES_TAG_COLOR_NAME
contains the list of tag name (or abbreviation), each tag separated with colon character (:
)- If an abbreviation is defined for a tag and one want it to be reported by itself not rendered over module name
- This abbreviation should be set in
MODULES_TAG_COLOR_NAME
- Not the full tag name this abbreviation refers to
- This abbreviation should be set in
Querying¶
- The
tags
sub-command ofmodule-info
modulefile command enables modulefile to know what tags apply to itselfmodule-info tags
returns a list of all the tags applying to currently evaluated module- an empty list is returned when called from a modulerc evaluation context or if no tag applies to current modulefile
- Tags cannot be queried to select modules
- Symbolic versions or variants can be used to select modules
Updating tags on already loaded modules¶
- An attempt to load an already loaded module with a
--tag
option set will update the list of extra tags set for this loaded module- Works for every sub-command and modulefile commands accepting the
--tag
option - Does not imply the reload of the loaded module
- Add tags to the tag list already set, no removal
- As tags defined with
module-tag
cannot be unset
- Works for every sub-command and modulefile commands accepting the
- A
tag
sub-command may seem useful to update tag list of already loaded modules- But it is simpler to use the loading/enabling sub-command to set these extra tags, especially to distinguish between tagging modules or modulepaths
- So no need for a dedicated sub-command, use loading or enabled sub-commands instead
- If extra tags specified are already set as non-extra tags on already loaded module, the tags are not updated (extra tag list is not updated)
- With
prereq
-like commands:- all loaded requirement in specified list get their tag list updated
- loading requirement does not get its tag list updated (no real use case foreseen for cyclic dependencies)
- When restoring collection, extra tags of modules are unset to only keep the
extra tags defined in collection.
- Extra tags are cleared either when module is unloaded or specifically if module is already loaded at the correct position
- When unloading a module, the
auto-loaded
,keep-loaded
and all extra tags are unset from in-memory knowledge, not to reapply automatically these tags if the module is loaded again: only the extra and state tags from this new load will be set.
Output configuration¶
Configuration¶
- Introduce options to define the content of the output:
avail_output
: elements to report onavail
sub-command regular modeavail_terse_output
: elements to report onavail
sub-command terse modelist_output
: elements to report onlist
sub-command regular modelist_terse_output
: elements to report onlist
sub-command terse mode
Specification¶
- Output configuration is available
- Output configuration is not available (but could be added later on)
- Output configuration defines the content of the output not its format
- These configurations are set by default with the elements reported by default
avail_output
:modulepath:alias:dirwsym:sym:tag:variantifspec:key
avail_terse_output
:modulepath:alias:dirwsym:sym:tag:variantifspec
list_output
:header:idx:variant:sym:tag:key
list_terse_output
:header
- The above default value could be superseded:
- with an environment variable, that can be set through the use of the
config
sub-commandMODULES_AVAIL_OUTPUT
to supersedeavail_output
default valueMODULES_AVAIL_TERSE_OUTPUT
to supersedeavail_terse_output
default valueMODULES_LIST_OUTPUT
to supersedelist_output
default valueMODULES_LIST_TERSE_OUTPUT
to supersedelist_terse_output
default value
- with the
-o
/--output
command-line option- which applies to the current output mode defined
-o
/--output
also supersedes environment variable definition
- with an environment variable, that can be set through the use of the
- Accepted elements in value lists are:
- For
avail
options: modulepath, alias, dirwsym, sym, tag, key, variant, variantifspec - For
list
options: header, idx, variant, sym, tag, key
- For
- If the
-o
/--output
options are wrongly specified- An error is raised and evaluation terminates
- It may happen in the following situations
- No value set after the option
- Option set on unsupported module sub-command
- Element set in option value unsupported by module sub-command
- Elements set in option value not separated by colon character (
:
) - Option set on unsupported output format (
--long
or--json
) - The above situations apply whether command is called from the terminal or within a modulefile
- For all these new configuration options
- accepted value is a list of strings separated by colon character (
:
) - order of elements in the list does not matter
- an empty string is a valid value (means only the modulefile name has to be reported)
- accepted value is a list of strings separated by colon character (
- If the
MODULES_AVAIL_OUTPUT
/MODULES_AVAIL_TERSE_OUTPUT
/MODULES_LIST_OUTPUT
/MODULES_LIST_TERSE_OUTPUT
env vars are wrongly specified- Their value is ignored
- So the default value takes precedence, unless a
-o
/--output
option is specified - Value in environment variable is wrongly specified for instance in the following situations
- Element set in option value unsupported by module sub-command
- Elements set in option value not separated by colon character (
:
)
avail_output
supersedesavail_report_dir_sym
andavail_report_mfile_sym
configurations- Enabled
avail_report_dir_sym
corresponds to addingdirsym
value toavail_output
- Enabled
avail_report_mfile_sym
corresponds to addingsym
value toavail_output
- Both
avail_report_dir_sym
andavail_report_mfile_sym
could be removed safely as:- it was not possible to define them at configure time
- or change default value with an environment variable
- Enabled
- Some output content cannot be controlled at the moment with the output options:
- Hidden modules is exclusively controlled by
--all
option to get these modules unveiled - Indepth/no-indepth output is exclusively controlled by
--no-indepth/--indepth
and related configuration option
- Hidden modules is exclusively controlled by
- When modulepath element is removed from an
avail
-related option- all the modulefiles returned from all searched modulepaths are merged and sorted as a single set
- a module appearing in several modulepaths is only reported once
- tags or symbols applying to a lower priority module with same name are still reported
Output key¶
- An output key is added to print a legend explaining the output
- Meaning of
()
,{}
or<>
is explained - Default version is colored specifically
- Every tag shortened to a defined abbreviation
- Every tag colored specifically
- Every variant type set (
variant=value
,+boolvariant
,-boolvariant
,%shortcutvariantvalue
, etc) - Legend entries only concern elements that can be found in reported output
- Legend entries are not reported on JSON output mode
- Meaning of
- Output key is enabled by default on
avail
andlist
sub-command output- Key is reported at the end of the output
- No key section is reported if no element need to be described (no color, no symbol, no tag, etc)
- Variant keys are not adapted for
avail
output- Even if all possible values are reported instead of the only one set
- Users should be able to understand
name=val1,val2,...
corresponds to thename=value
key entry - Same applies to the shortcut variant key
Shell completion¶
Goal is to provide tool to define shell completion through modulefile. Need
comes from the ability of the source-sh
modulefile command to
reproduce the shell changes made by a sourced shell
script. Completion definitions are part
of those shell changes, so there is a need to be able to define them through
modulefile command.
complete
and uncomplete
modulefile commands are introduced
to give this ability to define or unset completion for commands in shell that
provides a command to define such completion. Such shells are:
- bash
- tcsh
- fish
No shell command to setup completion has been found on other shells. For instance on zsh, completion is made through files saved in specific directories.
complete¶
complete
takes as argument:
- shell: name of the shell this completion definition should be applied to
- command: name of the command the completion targets
- completion arguments aka body: parameter to define completion on shell
Shell should correspond to one of the supported shell name. When modulefile
is evaluated, the complete
command will produce shell code as output
only if shell name corresponds to the shell the modulecmd.tcl
script
has been initialized for.
If an unsupported shell name is set, complete
command is simply
ignored. No error is produced as the shell specified may be supported on a
latter version of the modulecmd.tcl
script and the modulefile may be
provided for use by different version of this script.
Command name should be a non-empty string. Otherwise an evaluation error is returned.
Body is shell-specific. When modulefile is evaluated the body defined on a
complete
command is not checked by module. Possible options are
numerous and really different from one shell to another so it is up to the
modulefile author to ensure the body definition used is correctly supported on
targeted shell.
Body value is not escaped to fit shell evaluation. Defined syntax should be compatible with this evaluation. It is up to the modulefile writer to use the correct syntax as it cannot be guessed depending on what writer wants to achieve.
For shells like fish:
- Completion definition consist of multiple complete commands for a single command name.
- Prior applying completion definition, any previous completion is cleared for command. We ensure modulefile provides the full completion definition for command this way.
Note: when loading module on fish shell, completion is first fully removed for command. It is expected that modulefile provides the full completion definition for command and not rely on previous definition made elsewhere.
complete
is evaluated on load but also refresh mode. Important on
the later to get completion correctly redefined when initializing sub-shells.
On unload mode, complete
becomes uncomplete
.
uncomplete¶
uncomplete
is evaluated on unload mode. Like other undo command,
it is ignored when unloading a modulefile.
uncomplete
does not require a shell name as argument. Only the
command name is expected.
Command name should be a non-empty string. Otherwise an evaluation error is returned.
uncomplete
command is provided in case of a need to specifically
unset a defined completion. There should not be a lot of use case for this
command, but it does not cost much to add as it is needed to undo the
complete
command when a modulefile is unloaded.
Source shell script in modulefile¶
Configuration¶
- No specific configuration
Specification¶
- Execute a shell script and include the environment changes it performs in modulefile
- Environment changes done by shell script are gathered and evaluated in modulefile context through corresponding modulefile commands
- Goal is to get the same environment after loading a modulefile using a
source-sh
than if shell script targeted by thesource-sh
where directly sourced in shell session
- Environment changes tracked are (all environment elements
module
can handle):- Value set to variable: transformed into
setenv
modulefile command - Variable unset: transformed into
unsetenv
modulefile command - Path element added to variable: transformed into
append-path
orprepend-path
modulefile command - Path element removed from variable: transformed into
remove-path
modulefile command - Current working directory change: transformed into
cd
modulefile command - Shell alias definition: transformed into
set-alias
- Shell alias unset: transformed into
unset-alias
- Shell function definition: transformed into
set-function
- Shell function unset: transformed into
unset-function
- Shell completion definition: transformed into
complete
- Shell completion unset: transformed into
uncomplete
- Value set to variable: transformed into
- Depending on modulefile evaluation mode,
source-sh
has different behaviors:load
,refresh
andscan
: execute script to gather its environment changes, transform them in modulefile commands and evaluate themunload
: undo environment changes made on load modedisplay
: execute script to gather its environment changes and report resulting command name and arguments for displayhelp
,test
andwhatis
: no operation
- Limitation: code in modulefile cannot rely on the environment changes done in script targeted by a
source-sh
command- For instance an environment variable set in shell script cannot be used to define another variable later in modulefile
- This will work on
load
,unload
anddisplay
modes, as script is run and/or analyzed and corresponding modulefile commands are evaluated in modulefile context - But it will not work on the other modes, as script is not run and analyzed there
- To simplify processing as script need to be run and analyzed if not yet loaded, but if already loaded changes recorded in environment for tracking should be used instead
- To avoid a negative impact on performances on the
whatis
global evaluation
- Result of
source-sh
command evaluation is stored into the environment when modulefile is loaded- To keep track of environment changes made by
source-sh
script evaluation - In order to undo these changes when unloading modulefile and report corresponding modulefile commands when displaying modulefile
- Environment variable
__MODULES_LMSOURCESH
is used for this need- Using following syntax:
mod&shell script arg|cmd|cmd|...&shell script|cmd:mod&shell script arg|cmd
- Example value:
foo/1&sh /tmp/source.sh|append-path PATH /tmp|cd /tmp
- Characters used to structure information in
__MODULES_LMSOURCESH
(:
,&
and|
) are escaped- Respectively to
<EnvModEscPS>
,<EnvModEscS1>
and<EnvModEscS2>
- If found in environment changes to record
- Respectively to
- Actual bodies of shell alias, shell functions and shell completions are not recorded in
__MODULES_LMSOURCESH
, an empty body is recorded instead- Example value:
foo/1&sh /tmp/source.sh|set-alias alfoo {}|set-function funcfoo {}|complete bash foocmd {}
- Example value:
- Using following syntax:
- When unloading modulefile, content found for this modulefile in
__MODULES_LMSOURCESH
variable is evaluated to reverse environment changes- When reaching a
source-sh
modulefile command, recorded content is evaluated through a modulefile Tcl interpreter in unload mode, to get the reversed effect
- When reaching a
- When displaying modulefile
- If it is loaded
- the content found for this modulefile in
__MODULES_LMSOURCESH
variable is evaluated in display mode to report each resulting modulefile command - script is evaluated to fetch shell alias, function and completion definitions which are not recorded in
__MODULES_LMSOURCESH
- the content found for this modulefile in
- If not loaded, script is evaluated to gather environment changes and report each resulting modulefile command
- If it is loaded
- To keep track of environment changes made by
- Script targeted by a
source-sh
command has to be run and environment prior this run and after this run have to be compared to determine the environment changes the script performs- The shell to use to run script has to be specified to
source-sh
- This shell will be run to execute the following sequence:
- output current environment state
- source the script with its args
- output environment state after script source
- Script output is kept to return it in an error message in case its execution fails
- This comparison determines the environment changes performed by script which are then translated into corresponding modulefile commands
- Shell is run in a mode where neither its user nor its system-wide configuration is evaluated to avoid side effect
- Shell needs current environment to correctly evaluate script
- it seems desirable to run shell in an empty environment to get the full list of changes it does over the environment
- but the script may need the environment to be defined to correctly operate
- for instance it needs the
PATH
to be set to execute external commands
- for instance it needs the
- so shell run inherits current environment to ensure script will be properly evaluated
- but as a consequence if an environment change performed by script is already done prior script run, this environment change will not be seen
- The shell to use to run script has to be specified to
- Limitation: a variable already set by another module will not be seen set sourced script
- if this module is unloaded and if it does not trigger the unload of the modulefile using
source-sh
, variable will be unset as source-sh script has not increased variable reference counter
- if this module is unloaded and if it does not trigger the unload of the modulefile using
- Note: environment change done through
source-sh
will not preserve change order occurring in sourced script, as all changes are analyzed after sourcing script - Most shell will not get the full environment content when spawned as a sub-process
- For instance shell aliases are not transmitted into sub-shells
- As a result the environment prior script source will most of the time have no shell alias defined
- Note: shells may have specific behaviors
dash
cannot pass arguments to the sourced scriptksh93
reads the full script prior sourcing it which may cause issue if a shell alias is defined in script then used in script
- Limitation: implementation does not currently support:
- the
zsh
shell when used assh
or asksh
- the
mksh
shell - the BSD variant of the
sh
shell - the Windows
cmd
shell
- the
- Note: if sourced script produces shell alias or function, these alias or function may not be compatible with the current shell of the user
- Shell completion is defined for the shell used to evaluate script
- Note: the mechanism described here only applies for shell script as to understand the impact the script execution over the user environment, this environment need to be compared prior and after execution
source-sh
modulefile command relies of thesh-to-mod
procedure ofmodulecmd.tcl
sh-to-mod
procedure handles the evaluation of the targeted script and comparison of the environment prior and after this comparisonsh-to-mod
returns as a result the list of modulefile commands describing the environment changes made by the analyzed script
sh-to-mod
is a module sub-command, calling thesh-to-mod
procedure and outputting resulting modulefile commands- with a
#%Module
header - to enable users to convert the environment changes made by script in modulefiles
- with a
- There is no need to also make
sh-to-mod
a modulefile command andsource-sh
a module sub-command - Shell to use to source targeted script may be specified as a command name or as a path name
- When specified as a command name (e.g.,
bash
), command location will be determined based on currently setPATH
- When specified as a path name (e.g.,
/bin/bash
), this path name determines command location
- When specified as a command name (e.g.,
- Prior executing shell and making it sourcing script:
- Shell is checked to ensure an executable command matches it
- Script is checked to ensure it exists
- Those tests are done prior executing to avoid it if one check fails and provide a consistent error message whatever the shell used
- Environment changes to output as result should be enclosed and escaped
- Enclosed if they contains space character (like white-space, tab and newline characters)
- Escaped if they contains curly braces, as output is formatted as Tcl code, to avoid parsing issue
- If an error occurs during targeted script evaluation
- Error is thrown which leads to either a modulefile evaluation error or a module sub-command error
- Error and output messages reported by evaluated script will be reported along error by modulefile command or module sub-command
- To get prior and resulting environment state
env
command is not used to gather environment state through exec source execution- it would simplify environment state parsing, as same command would be used for every shell
- but it is an external command, so requires extra processing and an additional requirement
- moreover it does not return shell functions in general, only exported Bash functions
- Shell builtin commands are used to query existing environment variables, aliases, functions, completions and current working directory
- which provides best processing efficiency
- but leads to specific output parsing for each shell
- A separator string
%ModulesShToMod%
is printed between each kind of environment item (variable, alias, etc) and also prior and after script evaluation- to separate each output kind and then be able to split them for separate analysis
- De-duplication of path entries is applied for changes on path-like environment variables
- If the same path entry appears several times in the newly prepended entries for a variable, the first occurrence of this entry is kept others are dropped
- If the same path entry appears several times in the newly appended entries for a variable, the first occurrence of this entry is kept others are dropped
- De-duplication is not applied for path entries:
- appearing in both the new prepended entries and newly appended entries
- appearing in newly prepended entries or newly appended entries and in entries defined prior script evaluation
- An environment variable equaling to the path separator character (
:
) prior script evaluation is considered as undefined prior script evaluation to avoid misleading analysis - Environment variables made for Modules private use are filtered-out from the environment changes produced
LOADEDMODULES
,_LMFILES_
and any variable prefixed by__MODULES_
are concerned- Changes relative to Modules state are ignored this way
- If script loads in turn a modulefile, environment changes reported will not report the loaded module but only the environment changes it does
- Modules configuration variable (prefixed by
MODULES_
) are still taken into account
- There may be several shell completion changes found for the same command on particular shell like fish
- It produces multiple
complete
modulefile commands - But in
__MODULES_LMSOURCESH
variable, a single entry is recorded as a singleuncomplete
command should be generated when unloading modulefile - If completion definition is partial for a command when loading modulefile, on fish shell previous completion definition is cleared right before setting those defined in modulefile
- When a completion definition difference is spotted after script evaluation, new completion definition is set which means previous definition is cleared (either intrinsically by shell or for fish due to the definition clear specifically added)
- It produces multiple
- Fish shell allows nested definition of shell functions
- A separator string
%ModulesSubShToMod%
is printed between each function definition not to get main and nested functions mixed up - Such sub-separator is only applied on fish shell
- A separator string
- FUTURE: this feature may be extended to translate environment changes made by tools like Spack, Lmod or pkg-config. It may provide this way bridges between different realms.
Stashing environment¶
Stash the module environment changes compared to Initial environment
in current shell session away. Inspired from git stash
mechanisms and made
as close as possible to them to enable people knowing these mechanisms to use
them on module
.
Stash mechanism on Modules rely on collection and initial environment mechanisms. When stashing, current environment is saved in a collection and initial environment is restored.
stash sub-command¶
stash
sub-command saves current environment in a collection then
restore initial environment.
General properties:
- Shortcut name: none
- Accepted option:
--force
,--auto
,--no-auto
- Expected number of argument: 0
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: yes (
unload
andload
modes)
stash
is equivalent to save stash-<current_unixtime>
then reset
. Thus reset_target_state
configuration value
is taken into account to determine what is the initial environment state.
As it evaluates modules, --force
, --auto
and --no-auto
options can
be set for stash
sub-command. But, as for reset
sub-command these
options should have no impact.
Nothing happens and a warning message is emitted when current environment state equals initial environment state.
- When comparing current environment and initial one, only the extra tags set and state-specific tags (auto-loaded, keep-loaded) are compared by default.
- If
collection_pin_tag
is enabled, all tags set (extra and regular) are compared - A corner case exists if initial environment is recorded with
collection_pin_tag
disabled, then enabled afterward: in this situationstash
cannot detect current environment is the same than recorded initial environment, so a stash collection will be created but nothing is changed after that when restoring initial environment
Error is obtained:
- and processing stops if stash collection cannot be saved.
- if a super-sticky module has to be unloaded.
- and processing stops if collection to restore does not exist, cannot be read or is not valid.
- and processing stops if current environment is empty or if the module constraints described are not satisfied.
When saved, stash collection is named stash-<milliseconds>. milliseconds
is the current number of milliseconds since Unix Epoch. This 13-digit number
makes latest generated stash collection the highest stash collection name. If
collection_target
configuration is set, target value is appended
to the stash collection name, like for any other collection. For example, if
collection target equals foo
, stash collection file name is
stash-1662295591123.foo
.
Milliseconds is preferred over seconds as multiple stash operations may occur during the same second. This is for instance the case when running the non-regression testsuite.
By using current number of milliseconds we get a unique file name without the need to check existing stash file names.
stashpop sub-command¶
stashpop
sub-command restore a stashed collection then delete this
collection file.
General properties:
- Shortcut name: none
- Accepted option:
--force
,--auto
,--no-auto
- Expected number of argument: 0 or 1
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: yes (
unload
andload
modes)
stashpop
is equivalent to restore stash-<xxx>
then
saverm stash-<xxx>
.
As it evaluates modules, --force
, --auto
and --no-auto
options can
be set for stashpop
sub-command. But, as for reset
and stash
sub-commands these options should have no impact.
The stash collection to restore can be specified as argument to stashpop
sub-command. Either as:
- a stash index: 0 for the most recent stash, 1 for the one before it
- a stash collection name (e.g., stash-<milliseconds>)
Error is obtained and processing stops if:
- stash index does not correspond to an existing stash collection (for currently set collection target)
- stash collection name does not correspond to an existing collection (for currently set collection target)
- stash collection exists but cannot be accessed
- stash collection cannot be removed
If stash collection to pop is not different than current environment, collection restore will not change a thing and stash collection will be removed.
stashrm sub-command¶
stashrm
sub-command delete a stash collection file.
General properties:
- Shortcut name: none
- Accepted option: none
- Expected number of argument: 0 or 1
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: no
stashrm
is equivalent to saverm stash-<xxx>
.
The stash collection to delete can be specified as argument to stashrm
sub-command. Either as:
- a stash index: 0 for the most recent stash, 1 for the one before it
- a stash collection name (e.g., stash-<milliseconds>)
Error is obtained and processing stops if:
- stash index does not correspond to an existing stash collection (for currently set collection target)
- stash collection name does not correspond to an existing collection (for currently set collection target)
- stash collection exists but cannot be accessed
- stash collection cannot be removed
stashshow sub-command¶
stashshow
sub-command displays the content of a stash collection file.
General properties:
- Shortcut name: none
- Accepted option: none
- Expected number of argument: 0 or 1
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: no
stashshow
is equivalent to saveshow stash-<xxx>
.
The stash collection to display can be specified as argument to stashshow
sub-command. Either as:
- a stash index: 0 for the most recent stash, 1 for the one before it
- a stash collection name (e.g., stash-<milliseconds>)
Error is obtained and processing stops if:
- stash index does not correspond to an existing stash collection (for currently set collection target)
- stash collection name does not correspond to an existing collection (for currently set collection target)
- stash collection exists but cannot be accessed
- stash collection cannot be removed
stashclear sub-command¶
stashclear
sub-command delete all stash collection files.
General properties:
- Shortcut name: none
- Accepted option: none
- Expected number of argument: 0
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: no
stashclear
removes stash collection of currently defined
collection_target
.
stashclear
proceeds without a confirmation message and does not output
the list of stash collection removed, even in verbose mode.
Error is obtained and processing stops if:
- a stash collection cannot be removed
stashlist sub-command¶
stashlist
sub-command lists all stash collection files.
General properties:
- Shortcut name: none
- Accepted option:
--terse
,--long
,--json
- Expected number of argument: 0
- Accept boolean variant specification: no
- Parse module version specification: no
- Fully read modulefile when checking validity: yes
- Sub-command only called from top level: yes
- Lead to modulefile evaluation: no
stashlist
is equivalent to savelist stash-*
.
stashlist
lists stash collection of currently defined
collection_target
.
Returned stash collections are listed in the reverse order (most recent
collection first) and list index starts at 0. Index is this way consistent
with stash index argument value that could be provided to stashpop
,
stashshow
or stashrm
sub-commands.
stashlist
relies on savelist
sub-command. A difference exists however:
when no collection target is set, only the stash collections without a target
defined are returned.
Error is obtained and processing stops if:
- stash collection exists but cannot be accessed
Sticky modules¶
Configuration¶
- No specific configuration
Specification¶
- Once loaded a sticky module cannot be unloaded unless
- forced
- or reloaded
- or when restoring a collection
- or resetting to initial environment state
- If module is super-sticky instead of sticky, it cannot be unloaded even if forced, only if it is reloaded afterward
- Stickiness definition relies on Module tags
module-tag sticky foo/1.0
defines module foo/1.0 as stickymodule-tag super-sticky foo/1.0
defines module foo/1.0 as super-sticky
- Stickiness specified over a symbolic version or a module alias has no effect
module-tag
allows to specify a symbolic module version or a module alias- but associated tag will apply to the symbolic version or alias only
- as modulefile targeted by symbol or alias does not inherit their tags
- so a sticky or super-sticky tag set on a symbolic version or alias has no effect
- Sticky module can be swapped with another version from same module when stickiness is defined over module parent name
- For instance if stickiness is defined over module foo, foo/1.0 can be swapped with foo/2.0
- Such swap could occur from a
restore
or aswitch
sub-command - As soon as stickiness is defined over a precise module version name (like foo/1.0) such module cannot be swapped by another version of foo module
- Stickiness defined over module parent name (like foo) means any version from module foo must be loaded
- When stickiness is defined for several module versions using advanced version specifiers like foo@1: or foo@1.0,2.0
- it means stickiness applies to the module versions
- thus they cannot be swapped by another version
- In case stickiness is defined over module parent name and another
module-tag
defines stickiness over specific module version name- it means stickiness applies to the module version
- thus these versions targeted specifically with
module-tag
cannot be swapped by another version from same module
- When a super-sticky module depends on a non-super-sticky module
- If a forced
purge
command occurs, the dependent module will be unloaded - Which let the super-sticky module with a missing dependency
- If a forced
- Starting Modules 5.2, sticky modules are unloaded
- On
restore
sub-command - On
reset
sub-command ifreset_target_state
is not equal to__purge__
- No specific error or warning message
- This is allowed to fully restore the collection in its targeted state
- No change for super-sticky modules
- On
- An error is reported when trying to unload a sticky or super-sticky module
- As the expected unload is not performed
- So with the return code and message, user knows that what he/she asked for was not done
- Same goes for the
purge
command: user expects no more module loaded- so an error is returned as after the command the sticky module is still loaded
- When the unload is forced a warning message is reported
- the sticky module is unloaded as expected but a warning message is done
- as the module was tagged not to be unloaded by default
- user should know he/she has done something specific
Current limitations¶
- When swapping a sticky module explicitly targeted by the
module-tag
command and which is the default version- For instance
module-tag sticky foo/1.0
andmodule-version foo/1.0 default
- If specified swapped-on module is the generic module name, for instance foo
switch
sub-command raises an error even if the sticky module is the default version (either implicit or explicitly set) for this module
- For instance
Variants¶
Configuration¶
- Variant mechanism requires the
advanced_version_spec
option to be enabled- Variants can be seen as an extension of the advanced module version specifiers
Specification¶
Defining¶
- variants are defined for modulefiles within concerned modulefiles with the
variant
modulefile command- variants are bound to the modulefile they target
- especially modulefile evaluation may be guided by the value selected for the variants
- so it makes more sense to have variants defined within modulefiles rather in modulercs
variant --default? defaultval? --alias? {aliasname...?} name value? ...?
name
restrained to the accepted variable name- which should correspond to a sequence of one or more characters that are a letter, digit or underscore
- if we want to match Spack here also:
[A-Za-z0-9_][A-Za-z0-9_.-]*
- raise error otherwise
- a variant
name
that has already been defined as variant or variant alias for this modulefile evaluation overwrites previous definition- it is up to modulefile author to ensure there is no duplicate
- no need this way to check in
modulecmd.tcl
code if variant has already been defined
- may have a default value (when
--default
argument is passed)- if not, variant is undefined
- argument
--default
should be associated a defaultval argument- raise error otherwise
- default value should be part of possible value list if value list provided
- error is raised otherwise when default value is used, as it does not correspond to an accepted value
- ex:
variant name --default 1.8 1.0 2.0
- ex:
- when no list of accepted value is provided, default value could be any value
- error is raised otherwise when default value is used, as it does not correspond to an accepted value
- may be set as a Boolean variant (when
--boolean
argument is passed)- a Boolean variant may equal true or false
- may have a list of accepted values
- unless if defined as a Boolean variant
- passed value(s) must correspond to those accepted
- raise error otherwise
- raised error is a global error to signal specification issue, not a modulefile error
- an error is raised if one or more accepted values are defined on a Boolean variant
- non-Boolean variants cannot define Boolean value in their accepted value list
- as Boolean values are translated to their canonical form (0 or 1) when specified
- an error is raised otherwise
- exception made for the 0 and 1 integers
- when no list of accepted value is provided it means any value is accepted
- it is up to the modulefile author to write the appropriate test after variant declaration to check that the value provided is acceptable
- may be aliased (when argument
--alias
is passed) in which case:- argument
--alias
should be associated one or a list of alias names- raise error otherwise
- defined alias names should be valid variant name (i.e.:
[A-Za-z0-9_][A-Za-z0-9_.-]*
)- raise error otherwise
- should not be already defined as variant or variant alias
- raise error otherwise
- variant alias could negate its target (when alias name is prefixed by
-
)- meaning if alias variant is set to
false
its target is set totrue
- only possible if targeted variant is Boolean
- raise error otherwise
- no support of
~
as an alternative negated prefix to only get one way to write negation
- meaning if alias variant is set to
- argument
- require a value to be set
- raise error if no value set for variant (no value specified and no defined default)
- to validate variant value is coherent against other variant values or any other test
- it is up to the modulefile author to write the appropriate test after all variant declaration
- and then raise error if variant combination is not appropriate
- as there is no way to automatically determine when all variants are declared
Evaluating¶
- when reaching
variant
command in modulefile - set a key
name
in arrayModuleVariant
if variantname
has been specified or if it owns a default value- variable
ModuleVariant($name)
is not defined if variant not specified and no default for it- error is raised if used in this case
- variable
- if variant
name
can be aliased, if alias is set it specifies the value of variantname
- evaluated from left to right, in case variant is set and also its aliases
- negating aliases sets its reversed value to Boolean variant
- variant alias is not instantiated in
ModuleVariant
array- therefore accessing
$ModuleVariant($aliasname)
will raise an error
- therefore accessing
- raise error if variant
name
:- has been specified but passed value is incorrect
- is wrongly declared in modulefile
- then variable
$ModuleVariant(name)
could be used to adapt modulefile evaluation - to know all variant currently set, use
[array names ModuleVariant]
- but beware that only the variant already evaluated will be set in array
- must use after all the
variant
to be set in the modulefile to accurately get all variant defined
- if variant accepted values are Booleans, variable could be directly used in conditional tests
- like
if {$ModuleVariant($name)} {...
- like
- quoting Tcl doc, Booleans could have many forms:
- If string is any of 0, false, no, or off, then Tcl_GetBoolean stores a zero value at
*boolPtr
. - If string is any of 1, true, yes, or on, then 1 is stored at
*boolPtr
. - Any of these values may be abbreviated, and upper-case spellings are also acceptable
- If string is any of 0, false, no, or off, then Tcl_GetBoolean stores a zero value at
- variants with a shortcut defined for them, are resolved to their full name and transmitted this way to the modulefile
- therefore no entry in
ModuleVariant
array is made for the shortcut name
- therefore no entry in
- as special variant
version
will not be implemented on Modules 4.8, an error is raised if a variant is namedversion
- to ensure no usage of this variant name will be made before its special mechanism availability
- special variant
version
is instantiated as variableModuleVariant(version)
if declared- will be set to value that may be specified with the
@
shortcut - will initially work as any other variant (accepted list of value, default value)
- using
variant version --default 1.8 1.8 1.10
- is equivalent of having two modulefiles mod/1.8 and mod/1.10
- with a default defined:
module-version mod/1.8 default
- using
- FUTURE: could be refined later on to accept range then select latest version or defined default if in range
- note that
ModuleVariant(version)
is set only if aversion
variant is declared in modulefile - querying
[module-info name]
returns modulefile designation appended by the version variant:@versionvalue
- will be set to value that may be specified with the
- at the end of the modulefile evaluation, if module specification contains a variant which is not defined in modulefile
- an error is raised
- for the different evaluation modes:
- load, help and test apply evaluation mechanism described above
- for the help and test modes it helps to see how the modulefile reacts to the different variant value
- display applies evaluation mechanism described above but allow variant to be unspecified
- to help learning all the variant defined by the modulefile
- as a result unspecified variant is not instantiated in the
ModuleVariant
array variable - with unspecified variant a user will not accurately see how the modulefile reacts to the different variant value
- evaluation error is obtained if accessing the
ModuleVariant
array variable for an unspecified variant
- evaluation error is obtained if accessing the
- on display mode, the
variant
command is reported in addition of its evaluation
- unload evaluates the mechanism described above but the specified variants are fetched from loaded module persistent information
version
variant value is fetched from the module specification to identify the module to unload- other variant specification on the unload command are dropped once matching loaded module is identified
- however this specification remains available when querying
[module-info specified]
- however this specification remains available when querying
- variant values are defined within modulefile context by the evaluation of the
variant
modulefile commands- like it is done during a load modulefile evaluation
- this way variables related to variant are instantiated the same way whether module is loading or unloading
- so it is easier for modulefile author to understand how the modulefile code is evaluated
- variant evaluated during modulefile unload may produce an error
- if variant value not found defined or if value recorded in persistency does not match an allowed value
- should encourage variants to be consistent between the load and unload evaluation phases
- whatis ignores all variants from the module specification (only the module names are retained)
- like for
setenv
or*-path
modulefile commands on this mode,variant
will set theModuleVariant
array with a empty string for each variant defined in the modulefile - this is done to avoid the undefined variable error if these variables are used later in the modulefile
- however variant specified in module specification is used to filter modules to evaluate in whatis mode thanks to the extra match search mechanism
- FUTURE: if the different
version
variant values are considered as different modulefiles in the future, then whatis may evaluates theversion
variant from module specification
- like for
- load, help and test apply evaluation mechanism described above
getvariant¶
- A
getvariant
modulefile command is added following the same principle thangetenv
- A variant name is passed as argument
- Corresponding variant value is returned if it is defined
- If not defined the value if not defined argument is returned
- By default value if not defined argument equals to the empty string
getvariant
should be preferred to accessing variant value inModuleVariant
array- On display evaluation mode,
getvariant
returns the variant name enclosed in curly braces- Which helps to report where the variant is used in environment variable content
- The variant name and enclosing curly braces are graphically enhanced with
va
SGR code
Persistency¶
- once a module is loaded its defined variants are made persistent in user environment
- to keep track of how loaded modules were evaluated
- and enable query commands on these loaded modules without need to reevaluate modulefile
- variants defined are made persistent in
__MODULES_LMVARIANT
environment variable- following same approach than for
__MODULES_LMPREREQ
- each loaded module with defined variants (default value or specifically set) will expose:
- these variants value
- and if the value is the default one and if this default was specifically asked
- in a record with following syntax:
loadedmodule&boolvariantname1|isbooleanvariant|isdefaultvalue&variantname2|value2|value3...|isbooleanvariant|isdefaultvalue
- for each variant it is recorded if the variant is a Boolean variant
- which enables to compare value in a Boolean way
- and to report variant value with the +variant or -variant syntax
- for each variant it is recorded if the value set corresponds to the variant default value or not
- such information is useful to save collection when pin version mechanism is disabled
- on such setup the variant definition should not recorded in collection if this is the default value which is set
- in addition to know if the variant value is default or not, it is recorded if the default value was:
- specifically asked (isdefaultvalue=1)
- or automatically set (isdefaultvalue=2)
- this information will be useful in the FUTURE to determine if a variant may be automatically swapped by another
- each loadedmodule record are joined in
__MODULES_LMVARIANT
separated by:
character
- following same approach than for
- variant alias are also made persistent in
__MODULES_LMVARIANTALTNAME
environment variable- each loaded module with defined variants (default value or specifically set) which could be aliased will expose their aliases in a record with following syntax
loadedmodule&variantname1|aliasname1|-aliasname2&variant2|aliasname3...
- each loadedmodule record are joined in
__MODULES_LMVARIANTALTNAME
separated by:
character
- each loaded module with defined variants (default value or specifically set) which could be aliased will expose their aliases in a record with following syntax
- when persistency information is corrupted
- a missing or non Boolean
isdefaultvalue
information means variant value is not the default - a missing or non Boolean
isbooleanvariant
information means variant is not a Boolean variant - a non-Boolean value set on a Boolean variant means variant equals 0
- a missing or non Boolean
- Boolean variants are stored in the form
+name
or-name
- which enables to determine this variant is of Boolean type
- and check against query using different Boolean representations
- like
serial=0
,serial=on
,serial=false
, etc.
- like
- when the special variant
version
is defined for a loaded module- the value of this variant is part of loaded module identification
@versionvalue
is appended to the module name, for instancemod@1.2
- such identification is then recorded in persistency variables to designate loaded module (like
LOADEDMODULES
,__MODULES_LMPREREQ
,__MODULES_LMVARIANT
, etc) - this way in case a modulefile allows the load of two of its versions in the user environment, it is possible to distinguish these two loaded versions (to unload one of them for instance)
- with this identification, it is possible to distinguish a traditional module (identified by
mod/version
) from a module usingversion
variant (identified bymod@version
) - note that if a modulefile
mod/1.2
defines aversion
variant, it will be identified asmod/1.2@versionvalue
- so the
version
variant should not be defined if each version of the module has its own modulefile version
variant is useful if a single modulefile is used to instantiate every version of the module
- so the
- FUTURE: when it will be possible to override the shortcut for
version
variant it will be important to identify version value in loaded module identification string with a designation that is not dependent of the selected shortcut
- loaded module identification stops at the module name and
version
variant (if defined)- other variants are not considered as part of the identification
- as it is not foreseen useful to have the same module loaded multiple times with different variant values, unless for
version
variant
Specifying¶
following Spack spec
- see https://github.com/spack/spack/blob/develop/lib/spack/spack/spec.py
- or https://spack.readthedocs.io/en/latest/basic_usage.html#variants
- this specs covers all needs to specify variant on Modules
- Spack users are already familiar with it,
- it copes very well with command-line typing, avoiding most problematic characters
- that are interpreted by shells (like < or >)
- specification for one module could
- be almost condensed into one word hdf5@1.8+debug
- or be expanded into multiple hdf5 @1.8 +debug
same grammar used whatever the context
- command-line or as argument to modulefile command (like command)
variants are specified whether
- as specific words (separated by " ")
- or as suffix to module name
change command specifications which were previously accepting list of modules
- like module1 module2 module3
- now these modules could express variants appended to their name
- like module1@1.8+debug module2~shared module3
- or these variants could be defined as words next to module name
- like module1@1.8 +debug module2 shared=false module3
- as a consequence it denies:
- use of +, ~ and = in module names
- and use of - as first character of module names
- also a command-line argument starting with the - character is not anymore considered as an invalid option
- it is considered as an element of the module specification (potential negated boolean variant)
- unless if set prior the sub-command designation
- or set on sub-commands that do not accept module specification as argument
- such change requires an option to be enabled to avoid breaking compat
- this is why to enable variant, the
advanced_version_spec
option has to be enabled
- this is why to enable variant, the
a valued-variant is specified by name=value
- this kind of variant cannot be directly appended to module name
- thus it must be specified as a separate word
a Boolean variant can be specified with its bare name prefixed by +, - or ~
- when directly appended to module name string (no space) only + and ~ are recognized
- - in this case is retained as part of previous name/value
- the negation prefix - is not supported on the ml command
- as this - prefix means to unload a module on this command
- negation prefix plus Boolean variant name should not equal a command-line option short form
- command-line option takes precedence
- for instance the
-t
will always be treated as--terse
and not the negation of at
variant
- beware that the negation prefix ~ when used as a separate word may trigger the tilde resolution of the currently running shell
- if a username matches a Boolean variant name, using the
~name
form on the shell command-line will leads to the resolution of the HOME directory path of username
- if a username matches a Boolean variant name, using the
- module name could end with one or more + characters
- it could be distinguished from a Boolean variant specification as no character should follow these trailing +
- Boolean variant could also be specified using the name=value form
- in which case, it should be written as a separate word
- value could be any syntax recognized as a true or false string
- false: 0, false, no, or off
- true: 1, true, yes, or on
- Any of these values may be abbreviated, and upper-case spellings are also acceptable.
- when specified Boolean value is translated to its canonical form (0 or 1)
- when directly appended to module name string (no space) only + and ~ are recognized
variant may be specified with a shortcut if any set (see Variant shortcut)
- a shortcut is appended to the module designation word or specified as separate word, combined or not with other variant
- for instance for the
@
shortcut: module@versspec+boolvar, module+boolvar@versspec, module +boolvar@versspec
- for instance for the
- even if a shortcut is set, the variant could also be expressed as valued variant name
- a shortcut is appended to the module designation word or specified as separate word, combined or not with other variant
in case variant is specified multiple times
- lastly mentioned (read from left to right) value is retained (it overwrites previous values)
- a merge all passed values in list is not the methodology retained here
- same handling way whatever the variant properties
- a merge all passed values in list is not the methodology retained here
- like name=value1 name=value2
- or name=value name=value
- or name=value1,value2 name=value3
- or name=value1 name=value2,value3
- or @vers1 version=vers2
- or for boolean +name~name
- or ~name -name
- or ~name name=value1 name=value2,value3
- or in case of variant aliases +name~aliastoname
- at the specification time variant aliases are not known
- so the full module specification has to be transmitted toward the modulefile to determine what is the value at the most right position
- for instance name=value1 aliasname=value2 with aliasname being an alias of name
- specification can just be cleared from the obvious duplicates (same variant name defined multiple times on the line)
- lastly mentioned (read from left to right) value is retained (it overwrites previous values)
when special characters like ? or * are used in variant name or value
they are treated literally, no wildcard meaning is applied
like currently done when specifying module version on command-line
which leads to errors as no corresponding module is found:
$ module load loc_dv6/* ERROR: Unable to locate a modulefile for 'loc_dv6/*'
when a variant is specified but it does not correspond to a variant defined in the evaluated modulefile
- an error is raised at the end of modulefile evaluation
- need to wait for the end of modulefile evaluation to be sure the variant is defined nowhere in modulefile code
special variant
version
has to be specified with@
shortcut or by its full variant name (version=value
)- traditional separator character
/
cannot be used to specify variant version - if used, a modulefile named
mod/version
will be searched and a module not found error will be raised
- traditional separator character
specification may be passed to commands to verify a given module and variant combination is loaded
- which should be performed without evaluating modulefiles
- like for
is-loaded
sub-command:module is-loaded hdf5+parallel
- or
hdf5@1.8 parallel=true
- or
hdf5 -serial
- or
hdf5 serial=0
- checks rely on the content of the
__MODULES_LMVARIANT
and__MODULES_LMVARIANTALTNAME
variables- which store variants set for loaded modules and eventual variant aliases of variant set
- with this information it is possible to compare query against what is loaded
- a variant specified on query which is not part of the variables means a different module/variant combination
- even if variant from query is not valid for module, which cannot be known
- a variant specified on query which is not part of the variables means a different module/variant combination
- verification mechanism of a sub-command like
is-loaded
should be preserved- which means a query not mentioning a specific value for a variant should match a loaded module which specify a variant value that differs from this variant default
- the module identification part in specification may be resolved from a symbolic version or a module alias to an actual modulefile
the
@loaded
specification is translated into the name, version and variant list of corresponding loaded module- for instance
mod/3.0 foo=val1
is loaded somod@loaded
is translated intomod/3.0 foo=val1
- in case the
@loaded
specification is followed by variant specified, those variant specifications are ignored - following the above example,
mod@loaded foo=val2
is translated intomod/3.0 foo=val1
- for instance
variant can also be specified to designate module on
module-tag
,module-hide
ormodule-forbid
commands- tags may only apply when a given variant of a module is loaded
- it may be useful to decommission a given variant of a module prior others
- or to forbid the use of a given variant to some users
variants specified on search context are taken into account to filter results
- due to the Extra match search mechanism
- it concerns the
avail
,whatis
andpaths
sub-commands - only available modules matching the variant specification will be retained
- for instance
avail mod foo=var
returns all versions of mod module where a variant foo is defined with var as a possible value - exception is made for
is-avail
andpath
search sub-command- as they are more module selection commands rather an available module search commands
- it does not take info account variants defined within module specification
- these search commands (except
is-avail
andpath
) allow module specification without module name and version- only variant name and value specified (e.g.,
module avail foo=var
) - only modules declaring such variant with such version will be retained in result
- only variant name and value specified (e.g.,
variants specified on loaded module list context are taken into account to filter results
- concerns
list
sub-command - not related to extra match search as comparison is made against loaded modules not content of available modules
- only loaded modules matching the variant specification will be retained
- module specification without module name and version is allowed on this context
- only variant name and value specified (e.g.,
module list foo=var
) - only loaded modules declaring such variant set with this version will be retained in result
- only variant name and value specified (e.g.,
- concerns
variant cannot be specified over the
module-alias
,module-version
,module-virtual
commandsvariant passed as argument to
module-info
alias
,version
orsymbols
will not match anythingmodule-info loaded
only accepts modulefile as argument, not variant specification- it also only return loaded module name and version, without the variant set
Variant in requirement specification¶
prereq
/conflict
specification- could consolidate different variation set for same module on the same prereq/conflict list
- to indicate a preferred order (if available)
- like
prereq netcdf -debug netcdf +debug
- or
prereq netcdf var=val1 netcdf var=val2 netcdf
- in last example, could not currently consolidate definition into
prereq netcdf var=val1,val2,default
- in case of requirement alternatives, all possibilities should be written as independent
- like
prereq module@vers variant=val1 module@vers variant=val2
- like
- to clearly indicate a priority order to apply when for instance attempting to load these requirements
- FUTURE: a value selection mechanism, like when selecting a module version among others, would help here
- in case of requirement alternatives, all possibilities should be written as independent
- could consolidate different variation set for same module on the same prereq/conflict list
- prereq/conflict persistency
__MODULES_LMPREREQ
and__MODULES_LMCONFLICT
content should reflect specified variant constraint- it could be expressed in these variables as it is specified over the prereq/conflict modulefile commands
- for instance
__MODULES_LMPREREQ=hdf5/1.10&mpi@1.8 +shared variant=name&netcdf
- use of characters ``
, ``+
,~
,,
is not an issue- as delimiters characters in these environment variables are
:
,&
and|
- as delimiters characters in these environment variables are
- for instance
Variant shortcut¶
- shortcuts can be set to abbreviate variant names and simplify their specification
- a shortcut abbreviates
name=
into a unique character - when using shortcut, variant value is specified as
<shortcut>value
- for instance, if the
%
is set as the shortcut for atoolchain
variant, valuefoss21a
is specified as%foss21a
- a shortcut abbreviates
- shortcut can be set through the
variant_shortcut
configuration option- this option holds a colon separated list of shortcut definitions
- each definition have the following form:
variantname=shortcut_character
- for instance:
toolchain=%:foo=^
- shortcut must be:
- a single character
- excluding characters already used for other concerns or in module names (-, +, ~, /, @, =, [a-zA-Z0-9])
- when set through
config
sub-command or--with-variant-shortcut
installation option: an error is raised when a shortcut is badly specified - if a badly specified shortcut ends up in modulecmd configuration, it is purely ignored
- shortcut does not apply to Boolean variants
- as shortcuts are intended to be a prefix, they do not add benefit compared to -, + or ~ Boolean prefixes
- however a shortcut could be defined on a boolean variant (e.g.,
%true
or%0
)
- by default, when
advanced_version_spec
is enabled, the@
character is set as a shortcut for theversion
variant- this shortcut is not referred in
MODULES_VARIANT_SHORTCUT
thus it cannot be unset - FUTURE: superseding of this
@
shortcut inMODULES_VARIANT_SHORTCUT
may be introduced in the future- but currently entries in
MODULES_VARIANT_SHORTCUT
forversion
variant are ignored
- but currently entries in
- this shortcut is not referred in
- variant shortcuts could be used on the command-line or within modulefiles even if it is not recommended to use them in the latter case
- as if user updates the
variant_shortcut
configuration option, it will broke underlying modulefiles using a de-configured shortcuts
- as if user updates the
- module designation in collection does not use variant shortcuts
- when shortcut configuration is changed it should not impact collection definition
Reporting¶
- Defined variants are reported on
list
sub-command results- Reported joined to modulefile name, within curly braces
- Each variant definition separated by a colon
- For instance
module/version{vr=val:+boolvr}
- Variants are reported by default on
list
sub-command- as they qualify what exact flavor of the module is loaded
- so it enables users to really catch what has been loaded exactly
- They can be removed from output using the output configuration mechanism
- Variants defined by modulefiles may be reported on
avail
sub-command- Not by default, if
variant
value is added toavail_output
oravail_terse_output
- Or if
variantifspec
value is added toavail_output
oravail_terse_output
and a variant is specified in search query - It requires an Extra match search
- Which in turns requires more processing time as modulefiles are evaluated
- Having cache file available helps to reduce the I/O load caused by such process
- Not by default, if
- A specific color key is defined to highlight variants:
va
- Variant report depends on variant type
- valued variant:
variant=value
- boolean variant:
+variant
or-variant
- valued variant with shortcut set:
<shortcut>value
(for instance if%
is a defined shortcut:%value
) - in case a shortcut is defined over a Boolean variant, Boolean report prevails over shortcut
- valued variant:
- On
avail
, all possible values of variant are reported- Values are separated from each other with
,
character - Boolean variant are reported as valued variant with
on
andoff
values reported - Example:
mod/1.0{variant=val1,val2,boolvariant=on,off:%val1,val2}
- A
*
value is reported in possible value list for free-value variant- To indicate all values are possible
- Loaded variant value and default variant value are also reported if any
- Values are separated from each other with
- Variant aliases are not reported
- to keep output tight
- Special variant
version
is reported right after the module name- with
@
shortcut - using variant highlight color if any
- for instance:
module@version{othervariant=value}
- with
- Variants are reported on the Loading, Unloading and Switching informational messages
- As they qualify what exact flavor of the module is loaded, unloaded or switched
- They are put along the module name and version designation
- They are reported using their short form, like for
list
sub-command to keep output tight - Separated between each other by space character
- Each variant specification is enclosed between single quotes if it contains a space character
- The whole variant specification is enclosed between curly braces (
{}
) and separated from module name version by space character- Easier this way to distinguish variant specification from module name version on informational messages where multiple module designation are reported
- These designations have to be recorded
- prior module evaluation and based on variant specification (passed as argument) in order to be ready for any report prior the end of modulefile evaluation (in case of error for instance)
- then refined after module evaluation with the variant accurately set in loaded environment
- Variants are also reported along module name and version in the
auto_handling
informational messages
Recording collection¶
- The variant specification set for loaded modules has to be recorded when saving it in a collection
- Restoring such environment should apply the variant specified on the module to load
- Lines like the following one could now be found in collection:
module load hdf5@1.10 +parallel
- Important to distinguish multiple modules specified on a single line from a module specified with variant defined
- In case the
collection_pin_version
configuration option is disabled variant set to their default value should not be recorded in collection- Following the same scheme than for module version
- When saving collection, the is-default-value information stored in persistency variable (
__MODULES_LMVARIANT
) helps to know whether the value set to a variant is or not the default one - The save mechanism will rely on this information to exclude or not the variant specification in the generated collection output
- Within this is-default-value hint, the was-this-default-specified-by-user sub-information is not preserved when saving collection
- if collection is not pinned, default value is excluded whether it was specifically set by user or not
Comparing module specification including variants¶
- When a module specification has to be compared on a non-loaded or non-loading modules context
- If this specification contains variants
- Applies especially to the search commands taking a module specification as argument
- Specified variants are taken into account through Extra match search mechanism
- Once matching name and version are found
- A scan evaluation is made on them
- Only those declaring specified variants and values are retained in results
- It applies to
avail
,whatis
andpaths
sub-commands - Exception is made for
is-avail
andpath
sub-commands- do not trigger extra match search process
- even if variant specified in module specification argument
- If this specification does not contain variant
- There is no variant set on non-loaded or non-loading modules we are comparing to
- Match is performed over module name and version
- If this specification contains variants
- When a module specification has to be compared against loaded or loading modules
- If this specification contains variants
- It should be matched against the variants set on loaded or loading modules
- No variant set for loaded or loading module means no match
- If this specification does not contain variant
- Loaded or loading modules match is only made on their name
- No comparison occurs over the variants set on loaded or loading modules
- If this specification contains variants
- To compare variant set on loaded or loading modules
- A
ismodlo
flag is added to themodEq
procedure - With this flag it is known if
modEq
operates on a:- non-loaded or non-loading context (0),
- loading context (1)
- loaded context (2)
- Variants set on loading or loaded modules will be fetched in case
ismodlo
is equal to 1 or 2 - Loaded or loading modules are passed to
modEq
by their name/version designation- No change here
- And no change required in all procedures that perform such comparison
- Alternative names should also be tested like main module name with variants set
- As the alternative names currently apply to module name and version only
- Name and version could be compared on their own
- Then variants could be compared
- Which means all applying names are compared then if a match is found variants are compared
- A
- Specific comparison occurs when restoring collection
- When a collection is restored an unspecified variant for a given module to load means this variant has to be set at its default value
- So when comparing against loaded environment, an unspecified variant in collection only matches if variant set on loaded environment is the default one
- Collection procedures now rely on the
modEq
procedureismodlo
flag is set to3
to indicate a collection context- This collection context leads to also compare simplified module names (in addition to alternative names)
- And to treat an unspecified variant on tested pattern as a default variant value
- There is no need to compare variants on following procedures
getLoadedWithClosestName
- Find a loaded module whose name and version is the closest to passed specification
- Variant specified on loaded modules or on specification is ignored here
modStartNb
- Only used to compare module name and versions
- Used by
getLoadedWithClosestName
andisModuleHidden
modEqStatic
- Always used over non-loaded or non-loading context
- Used by
findModules
andgetModules
getEqArrayKey
cmdModuleSearch
cmdModuleSwitch
getModules
- Unless if module specification contains a variant definition, which triggers an extra match search process
- Used by
cmdModuleAvail
,getPathToModule
,isStickinessReloading
,cmdModulePaths
,cmdModuleSearch
andcmdModuleAliases
getPathToModule
- Which calls to
getModules
- Used by
cmdModulePath
,cmdModuleSearch
,cmdModuleSwitch
,cmdModuleLoad
,cmdModuleUnload
,cmdModuleTest
,cmdModuleHelp
,getAllModuleResolvedName
,is-avail
,getSimplifiedLoadedModuleList
andcmdModuleDisplay
- Which calls to
getAllModuleResolvedName
- Variant comparison is needed on following procedures
setModuleDependency
getUnmetDependentLoadedModuleList
getDirectDependentList
cmdModuleLoad
cmdModuleList
conflict
getLoadedMatchingName
doesModuleConflict
getModuleTag
- Useful when a tag is defined only when a specific variant is set
collectModuleTag
- Useful when a tag is defined only when a specific variant is set
getModuleHidingLevel
- Useful when a module with a specific variant value set is defined hidden
- FUTURE: if variants are reported on
avail
, hiding a variant specific value would have an effect on this sub-command
isModuleHidden
- Useful when a module with a specific variant value set is defined hidden
- FUTURE: if variants are reported on
avail
, hiding a variant specific value would have an effect on this sub-command
Specific impact¶
- When loading a module with variant, if this module is already loaded but with a different variant set an error is raised
- Tags applying specifically on variants do not appear over
avail
result- Even when variants are processed on
avail
mode - However if a module is loaded and tags apply to the variant selected, these tags will appear on the module designation within
avail
result
- Even when variants are processed on
- Forbidding a specific variant of a module will not exclude it from search results
- The module will still be reported on
avail
or evaluated onwhatis
- Even if this specific variant is searched
- As search sub-commands report all possible variants of available modules
- The module will still be reported on
- Hiding a specific variant of a module will not hide the module from search results
- Even if this specific variant is searched
- As search sub-commands report all possible variants of available modules
- Sticky modules can be swapped by another sticky modules if the stickiness applies to the generic module name
- It stays true even if module has variants
- Which means if stickiness designate module version or several versions, sticky module cannot be changed once loaded
- Variant change cannot either occur
- FUTURE: this may be revised to allow variant change if needs arise
- Stickiness can be defined over specific variant value, like any other tag
- In case stickiness applies to the default value of a variant
- When swapping sticky modules by another still matching the sticky rule
- The variant with default value has to be explicitly specified for the swap to be allowed
- As it cannot be guessed prior loading module that the default value of the variant will match the sticky rule
- It applies to both sticky module swap context:
restore
andswitch
- On
module-info tags
, currently defined tags need to get fetched when called- As variant specified prior
module-info tags
call may change the list of tags that apply - Especially when a variant inherits its default value as it is not specified when loading module
- As variant specified prior
module-info specified
returns module name version and variants specified to designate the currently evaluating modulemodule-info name
only returns module name and version, variants are not part of the result- Variants can be fetched in the
ModuleVariant
array within evaluation context
- Variants can be fetched in the
Corner cases¶
- When loading a variant which is an optional requirement for an already loaded module
- If this optional requirement is loaded without specifying its variant value to get the default variant value
- Currently it is not seen as an optional requirement at the load time
- Thus dependent module is not reloaded
- FUTURE: the deps evaluation mode that will be triggered prior module load may fix this current limitation
Get started with Modules¶
Learn how to retrieve and install Modules on Unix or on Windows. An overlook on the new functionalities introduced by each version is available in the New features guide. Release notes provides the full list of changes added in each version. The Changes between versions document gives an in-depth view of the modified behaviors and new features between major versions.
Reference manual page for the module and ml commands and for modulefile script provide details on all supported options.
A Cookbook of recipes describes how to use the various features of Modules and how to extend the module command to achieve specific needs.
If you have questions, comments or development suggestions for the Modules community, please read the Contributing guide.
License¶
Modules is distributed under the GNU General Public License, either version 2 or (at your option) any later version (GPL v2+).