What a module exports¶
Questions
What does a generated modulefile actually export?
Which variables are always set, and how are they spelled?
What is the citable name of an installed package?
What you will be able to do
Read a generated modulefile and say where each line came from.
Name the variables EasyBuild always sets, and use one from an easyconfig.
Say what a module naming scheme changes, and what a hierarchical one does to
MODULEPATH.
The citable unit consists of name, version, toolchain, and versionsuffix, not the easyconfig filename nor EasyBuild. FORCE11 software citation requires the specific version that was executed. What “installed” means stated that the modulefile is the only artifact a user encounters, and then did not open one. An example is provided.
A real modulefile¶
QMCPACK 4.4.0, abridged
$ sed -n '1,34p' \
> .../modulefiles/chem/QMCPACK/4.4.0-foss-2025a.lua
help([==[
Description
===========
QMCPACK is an open-source quantum Monte Carlo simulation code.
More information
================
- Homepage: https://qmcpack.org
]==])
whatis([==[Description: QMCPACK is an open-source quantum Monte ...]==])
whatis([==[Homepage: https://qmcpack.org]==])
whatis([==[URL: https://qmcpack.org]==])
local root = ".../software/QMCPACK/4.4.0-foss-2025a"
conflict("QMCPACK")
depends_on("foss/2025a")
depends_on("Boost/1.88.0-GCC-14.2.0")
depends_on("HDF5/1.14.6-gompi-2025a")
depends_on("Python/3.13.1-GCCcore-14.2.0")
depends_on("libxml2/2.13.4-GCCcore-14.2.0")
prepend_path("CMAKE_PREFIX_PATH", root)
prepend_path("LD_LIBRARY_PATH", pathJoin(root, "lib"))
prepend_path("LIBRARY_PATH", pathJoin(root, "lib"))
prepend_path("PATH", pathJoin(root, "bin"))
Recorded: SURF Snellius, generated modulefile, 2026-09-10, EasyBuild 5.3.1
Nobody wrote that file.
Every line came from somewhere in the easyconfig, and being able to point at the source of each is most of what this chapter is for.
help and whatis come from description and homepage, which is why those parameters exist and why a one-line description is worth writing properly: it is what a user sees from module whatis.
conflict("QMCPACK") comes from the name.
Two versions of the same software cannot be loaded at once, and the module says so rather than letting a user discover it through a strange failure.
Smith et al. [2016] require a citation to name the specific version and the platform variant.
The module’s full name is that variant: software, version, toolchain, versionsuffix.
A paper that writes “GROMACS” has not cited a module.
depends_on is the dependencies list from Build dependencies are not dependencies, resolved to specific modules by the robot.
Note it is depends_on and not load: Lmod counts references, so unloading QMCPACK unloads HDF5 only if nothing else still depends on it.
The prepend_path lines are the standard set, added.
No parameter asked for them.
The variables EasyBuild always sets¶
These entries are not shown in the excerpt above.
Variable |
Contents |
|---|---|
|
the install directory |
|
the version |
|
a path to the development-support file |
convert_name converts characters to uppercase, translates - to min, + to plus, and removes periods.
code-server is transformed into EBROOTCODEMINSERVER.
netcdf-c is transformed into EBROOTNETCDFMINC rather than EBROOTNETCDFC.
The min convention follows the easyblock filename pattern instead of merely stripping punctuation.
The name entered by the user is constructed at this point.
Modifying the toolchain or the suffix causes the module name and the .eb filename to change correspondingly.
$EBROOT* is used by a recipe.
It shows how an easyconfig points at a dependency without hardcoding a path, as described in How a build executes’s --with-hdf5=$EBROOTHDF5.
The dependency’s module was loaded during prepare, so the variable is set, and the build never needs to know where the site puts things.
Adding to the module¶
Four parameters are listed in approximate order of frequency of use.
modextravars defines additional environment variables.
A package whose runtime requires FOO_DATA_DIR located within its own installation receives it via this parameter.
modextrapaths inserts a prefix into a path-like variable.
This mechanism allows a Python package to add its own lib/python3.13/site-packages to $PYTHONPATH and an R package to extend $R_LIBS_SITE.
modluafooter appends raw Lua code to the modulefile, and modtclfooter performs the same for Tcl.
It provides an escape hatch for situations not covered by the other parameters.
Use it with the understanding that it binds the easyconfig to a specific module syntax.
modaltsoftname alters the filename under which the module is stored while preserving the software’s original name.
It is uncommon and exists.
A rule for all four parameters is that they affect what a user receives, not what the build receives.
Setting modextravars does not assist a build that requires an environment variable, since the module is generated in the module step after the build has completed several steps earlier.
Naming schemes¶
The path in that transcript is modulefiles/chem/QMCPACK/4.4.0-foss-2025a.lua, and the chem comes from moduleclass.
That is a categorised scheme, and it is one of several.
Flat, EasyBuild’s default, EasyBuildMNS: every module in one directory, named name/version-toolchain-versionsuffix.
Everything is visible in module avail at once.
Simple, and long lists.
Categorised: the same names, filed under moduleclass.
What Snellius uses above.
Hierarchical, HierarchicalMNS: the toolchain moves out of the module name and into the path.
Loading a compiler changes MODULEPATH, and only then are the modules built with it visible.
The hierarchical scheme is worth understanding even if a site does not use it. A module that cannot be seen is not absent; it is behind a toolchain that has not been loaded. That is A toolchain is a hierarchy’s hierarchy made into directories, with the advantage that the module system enforces it and the cost that discovery becomes a two-step process users find baffling until somebody explains it once.
--module-naming-scheme sets it, and it is a site decision made once.
Changing it later renames every module a site has, so it is not a decision anyone revisits casually.
EB-Module-1 — Where did that line come from
Using the modulefile above:
A user runs
module whatis QMCPACK/4.4.0-foss-2025aand gets one line. Which easyconfig parameter produced it?They then run
module unload QMCPACKand find HDF5 still loaded. Is that a bug?Your package installs data files in
share/mydataand its binary needs$MYPKG_DATAto find them. Which parameter, and what is the wrong way to do it?A colleague adds
modextravars = {'CC': 'mpicc'}so builds against the module pick up MPI. Why will that not do what they expect?
Solution
1 is description, via whatis. Which is the argument for writing a
description that reads as a sentence: it is the one line most users ever
see about your package.
2 is not a bug. depends_on is reference-counted, so HDF5 stays loaded
while anything else still depends on it. If nothing does and it stays,
that is worth investigating; if something does, Lmod is doing its job.
3 is modextravars = {'MYPKG_DATA': '%(installdir)s/share/mydata'}. The
wrong way is modluafooter with a hand-written setenv, which works
and ties the easyconfig to Lua, so it breaks for a site using Tcl
modules.
4 will set $CC for a user who loads the module, and will do nothing
for a build. A build’s environment is constructed in prepare, as
What a build is allowed to see describes, and its $CC
comes from the toolchain object rather than from any module. Those builds need
toolchainopts = {'usempi': True} in the consuming easyconfig, which is
What a toolchain injects.