Skip to content

Commit 6e49f96

Browse files
authored
fix: Add capabilities for stackinator to utilize LMOD modules. (#299)
Previously, stackinator did not have the capability to utilize an LMOD module structure and defaulted to TCL. This will allow both to be utilized via an update to the Makefile template.
1 parent 2c6f380 commit 6e49f96

3 files changed

Lines changed: 42 additions & 4 deletions

File tree

stackinator/builder.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,11 +220,18 @@ def generate(self, recipe):
220220
# generate top level makefiles
221221
makefile_template = jinja_env.get_template("Makefile")
222222

223+
# Extract module types that were configured in recipe.py
224+
module_types = []
225+
if recipe.with_modules and recipe.modules:
226+
roots = recipe.modules.get("modules", {}).get("default", {}).get("roots", {})
227+
module_types = list(roots.keys())
228+
223229
with (self.path / "Makefile").open("w") as f:
224230
f.write(
225231
makefile_template.render(
226232
cache=recipe.mirror,
227233
modules=recipe.with_modules,
234+
module_types=module_types,
228235
post_install_hook=recipe.post_install_hook,
229236
pre_install_hook=recipe.pre_install_hook,
230237
spack_version=spack_version,

stackinator/recipe.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,38 @@ def __init__(self, args):
7474
# Note:
7575
# modules root should match MODULEPATH set by envvars and used by uenv view "modules"
7676
# so we enforce that the user does not override it in modules.yaml
77-
self.modules["modules"].setdefault("default", {}).setdefault("roots", {}).setdefault(
78-
"tcl", (self.mount / "modules").as_posix()
79-
)
77+
78+
# Spack supports these module types (as of Spack 1.0+)
79+
VALID_MODULE_TYPES = {"tcl", "lmod"}
80+
81+
# Update the root path for each module type that the user configured
82+
# This respects the user's choice of tcl, lmod, or both
83+
defaults = self.modules["modules"].setdefault("default", {})
84+
roots = defaults.setdefault("roots", {})
85+
86+
# Determine which module types to configure
87+
# Priority: 1) explicit roots:, 2) enable: list, 3) default to tcl
88+
if not roots:
89+
# No explicit roots configured, check enable: list
90+
enabled = defaults.get("enable", [])
91+
if enabled:
92+
# Use the enabled module types
93+
module_types = enabled
94+
else:
95+
# No enable list either, default to tcl for backward compatibility
96+
module_types = ["tcl"]
97+
else:
98+
# Use explicitly configured roots
99+
module_types = list(roots.keys())
100+
101+
# Set the root path for each module type
102+
for module_type in module_types:
103+
if module_type not in VALID_MODULE_TYPES:
104+
raise ValueError(
105+
f"Invalid module type '{module_type}' in modules.yaml. "
106+
f"Supported types: {', '.join(sorted(VALID_MODULE_TYPES))}"
107+
)
108+
roots[module_type] = (self.mount / "modules").as_posix()
80109

81110
# DEPRECATED field `config:modules`
82111
if "modules" in self.config:

stackinator/templates/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ environments: compilers
5252

5353
{% if modules %}
5454
modules-done: environments generate-config
55-
$(SANDBOX) $(SPACK) -C $(BUILD_ROOT)/modules module tcl refresh --upstream-modules --delete-tree --yes-to-all
55+
{% for module_type in module_types %}
56+
$(SANDBOX) $(SPACK) -C $(BUILD_ROOT)/modules module {{ module_type }} refresh --upstream-modules --delete-tree --yes-to-all
57+
{% endfor %}
5658
touch modules-done
5759
{% endif %}
5860

0 commit comments

Comments
 (0)