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:

  1. LMOD_DUPLICATE_PATH=no

  2. LMOD_DUPLICATE_PATH=no, LMOD_TMOD_PATH_RULE=yes

  3. 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.