Rules for PATH-like variables¶
Lmod provides great flexibility in handling prepending and appending
to path-like variables. This is especially true when there are
duplicate entries. A modulefile can modify a variable like PATH
using append_path()
or prepend_path()
or their TCL
equivalents. For example, suppose that PATH=/usr/bin:/usr/local/bin
then:
prepend_path("PATH","/bin")
would change PATH
to /bin:/usr/bin:/usr/local/bin
. The
interesting question is what happens when the following is executed:
prepend_path("PATH","/usr/bin")
That is, when /usr/bin
is already in $PATH or any other duplicate entry.
LMOD_DUPLICATE_PATHS == yes¶
Lmod supports two main styles for dealing with duplicates. If $LMOD_DUPLICATE_PATHS is yes (or Lmod is configured that way). Then duplicates entries are allowed (assume PATH is empty):
prepend_path("PATH","/A") --> PATH = /A
prepend_path("PATH","/B") --> PATH = /B:/A
prepend_path("PATH","/A") --> PATH = /A:/B:/A
When unloading a modulefile with prepend_path(), Lmod removes the first matching entry it finds. Reversing an append_path(), Lmod removes the last matching entry.
LMOD_DUPLICATE_PATHS == no¶
The default setting of Lmod is that duplicates are not allowed. When prepending, Lmod pushes the directory to be first even if it is a duplicate (assume PATH is empty):
append_path("PATH","/A") --> PATH = /A
prepend_path("PATH","/B") --> PATH = /B:/A
prepend_path("PATH","/A") --> PATH = /A:/B
When duplicates are not allowed, Lmod maintains a reference count on each entry. That is, Lmod knows that “/A” has appended/prepended twice and “/B” once. This means that two prepend_path(“PATH”,”/A”) will be required to completely remove “/A” from $PATH.
LMOD_TMOD_PATH_RULE == yes¶
If this env. var is set (or configured), then Lmod does not change the order of entries but it does increase the reference count (assume $PATH is empty):
append_path("PATH","/A") --> PATH = /A
prepend_path("PATH","/B") --> PATH = /B:/A
prepend_path("PATH","/A") --> PATH = /B:/A
Here we see that prepending “/A” does not change the order of directories in $PATH. Obviously if LMOD_TMOD_PATH_RULE is yes then duplicates are not allowed.
Special treatment for $MODULEPATH¶
The MODULEPATH environment variable is treated special. No duplicates entries are ever allowed even if LMOD_DUPLICATE_PATHS == yes. It always uses reference counting for PATH entries. In order to not confuse users. The command:
$ module unuse /foo/bar
will always remove the path entry, even if the reference count is greater than 1. Also a user can always clear $MODULEPATH with:
$ module unuse $MODULEPATH
Specifying Priorities for PATH entries¶
There are rare occasions where a site might want a directory to at the beginning of the PATH. This can be done by giving a priority to a path:
prepend_path{"PATH","/foo/bar",priority=100}
Note the use of curly braces instead of parentheses and setting
priority to a number. Lmod groups the entries of the same priority
together. This means that /foo/bar
will likely be at the
beginning of $PATH as long as no other entry has a higher priority.
Assuming that PATH is initially empty, here is an example:
prepend_path{"PATH","/foo",priority=100} --> PATH = /foo
prepend_path("PATH","/A") --> PATH = /foo:/A
prepend_path("PATH","/B") --> PATH = /foo:/B/A
Lmod remembers the priority between invocations, meaning that you’ll get the same results even if the following where in three separate modulefiles.
An Example of Loading and Unloading a Module¶
Above we showed that there are three modes for path like variables:
LMOD_DUPLICATE_PATH=no
LMOD_DUPLICATE_PATH=no, LMOD_TMOD_PATH_RULE=yes
LMOD_DUPLICATE_PATH=yes
Let’s assume that $PATH = /A:/B:/C
and the module FOO is:
prepend_path("PATH","/C")
then the following table shows what happens for each of the three modes when
loading and unloading FOO. Note that /A(2)
is the path entry
/A
a reference count of 2:
Action |
1 |
2 |
3 |
---|---|---|---|
original PATH |
/A(1):/B(1):/C(1) |
/A(1):/B(1):/C(1) |
/A:/B:/C |
module load FOO |
/C(2):/A(1):/B(1) |
/A(1):/B(1):/C(2) |
/C:/A:/B:/C |
module unload FOO |
/C(1):/A(1):/B(1) |
/A(1):/B(1):/C(1) |
/A:/B:/C |
For mode (1) where no duplicates are allowed, upon loading FOO path
/C
is moved to the beginning and stays there when unloading FOO.
For mode (2), If a directory is already in $PATH
, it is not moved,
only the ref count is increased on load and decreased upon unload.
Finally in mode (3), loading causes /C
to be placed at the
beginning and unloading removes it from the beginning.
When duplicates are allowed and unloading a module, Lmod does not remember which module inserted which directory where, it just removes the first or last entry depending on whether it was a prepend_path() or append_path() respectively. Also there is no reference counting when duplicates are allowed. It is not necessary and doesn’t make sense.