SeisSol, from a Spack recipe to a PR¶
The old easyconfig is the next file. Spack names missing deps. The site names the generation.¶
Parent bump of 1.1.4, then companions, then a PR. Spack is not the file eb builds.¶
The generation is a site fact. eb-stack writes the next file. eb still has to run.¶
Questions
When both a Spack
package.pyand an old easyconfig exist, which eb-stack command writes the next file EasyBuild will build?What does a parent
package bumpprint when ASAGI, easi, or PSpaMM have no candidate on the target generation?What names the toolchain generation: the newest common toolchain, or the site stack the module will load?
Which two EasyBuild claims look like checksums or sanity and are not, until the named artifact is the one that was hashed or imported?
What you will be able to do
Given a Spack package and an older easyconfig for the same software, name the parent command, the companion commands, and the command that still has to be
eb.Read a parent bump that exits 1 and say what
companion=andre_run=mean, and when the overlay is done.Name the generation the production stack already built, and say what a
foss/2026.1recipe does on that stack.Tell a git-config checksum of the wrong tarball from a Python sanity check that imports the EasyBuild name rather than the module.
Before this page
eb-stack ports a recipe and bumps one: port versus bump.
A pin is for one generation: a version is a pin.
A checksum is a claim about bytes: the hash names one archive.
SeisSol 1.3.2 is the tagged release this case used.
The EasyBuild robot on develop had SeisSol-1.1.4-foss-2023a.eb.
Spack’s seissol recipe stopped at tag 1.3.1.
The next EasyBuild file is a bump of 1.1.4 rather than a blank plan of that Spack file.
eb-stack ports a recipe and bumps one already split those two jobs.
This page is the overlay that came out, the site install, and the PR.
The first site build found two defects.
The overlay, the site install, and the PR are not a compile.
The parent is the old easyconfig¶
package inspect --format spack on Spack’s seissol recipe writes a plan and an SBOM.
It does not write a .eb.
The residuals are tight pins that Spack states and that SeisSol 1.3.2 CMake does not: yaml-cpp@0.6.2, eigen@3.4.0 exact, netcdf-c@4.6:4.8.1.
The 1.1.4 easyconfig already used netCDF 4.9.2, above that Spack upper bound.
CMake for 1.3.2 asks for Eigen 3.4 or newer and handles yaml-cpp 0.8.
Those inspect residuals are Spack conservatism, not SeisSol bounds.
package bump of SeisSol-1.1.4-foss-2023a.eb is the parent.
Leave out --toolchain-name. The family stays foss.
A SeisSol-only bump that exits 0 while ASAGI, easi, or PSpaMM have no
foss-2025a candidate is a hole. The parent exits 1 and prints the
holes. The text after each companion= is a full eb-stack package
command. re_run= is the parent command again.
The transcript that follows is a recorded parent bump rather than a
description of a PR. Each companion= line is a command that was printed.
Parent bump exits 1; three companion= lines, then re_run=
$ eb-stack package bump \
> --source SeisSol-1.1.4-foss-2023a.eb \
> --version 1.3.2 \
> --toolchain-version 2025a \
> --package-config seissol.toml \
> --easyconfigs ROBOT \
> --out-dir OUT
generation_target=foss-2025a
residual=unresolved-generation-dep ASAGI =1.0
residual=unresolved-generation-dep easi =1.7.0
residual=unresolved-generation-dep PSpaMM =0.3.1
companion=eb-stack package bump --source ASAGI-1.0-foss-2023a.eb --toolchain-name foss --toolchain-version 2025a --version 1.0 --easyconfigs ROBOT --out-dir OUT
companion=eb-stack package bump --source easi-1.3.0-foss-2023a.eb --toolchain-name foss --toolchain-version 2025a --version 1.7.0 --package-config easi.toml --easyconfigs ROBOT --out-dir OUT
companion=eb-stack package plan --package-config pspamm.toml --source py-pspamm/package.py --toolchain-name gfbf --toolchain-version 2025a --easyconfigs ROBOT --out-dir OUT
re_run=eb-stack package bump --source SeisSol-1.1.4-foss-2023a.eb --toolchain-name foss --toolchain-version 2025a --version 1.3.2 --package-config seissol.toml --easyconfigs ROBOT --out-dir OUT
done_when=exit 0
next=eval each companion= line as a shell command, then eval re_run=
Error: unresolved on this generation; run each companion= line, then re_run=
Recorded: eb-stack package bump, 2026-09-11
ASAGI 1.0: the first
companion=ispackage bumpof the 2023a recipe.easi 1.7.0: the second is
package bump --version 1.7.0with the easi package-config. ImpalaJIT isexclude_from_solve. 1.7.0 is Lua-only.PSpaMM 0.3.1: the third is
package planfrom the Spackpy_pspammrecipe, ongfbf-2025a. PSpaMM has no easyconfig to bump. The package-config setsoptions.modulenametopypspamm.
First companion=: ASAGI bump exits 0
$ eb-stack package bump --source ASAGI-1.0-foss-2023a.eb --toolchain-name foss --toolchain-version 2025a --version 1.0 --easyconfigs ROBOT --out-dir OUT
generation_target=foss-2025a
done_when=exit 0
Recorded: eb-stack companion ASAGI, 2026-09-11
Second companion=: easi bump exits 0
$ eb-stack package bump --source easi-1.3.0-foss-2023a.eb --toolchain-name foss --toolchain-version 2025a --version 1.7.0 --package-config easi.toml --easyconfigs ROBOT --out-dir OUT
generation_target=foss-2025a
done_when=exit 0
Recorded: eb-stack companion easi, 2026-09-11
Third companion=: PSpaMM plan exits 0
$ eb-stack package plan --package-config pspamm.toml --source py-pspamm/package.py --toolchain-name gfbf --toolchain-version 2025a --easyconfigs ROBOT --out-dir OUT
generation_target=gfbf-2025a
done_when=exit 0
Recorded: eb-stack companion PSpaMM, 2026-09-11
After those three recorded commands, the same parent is re_run=. The overlay is
done when that line exits 0 and writes the four .eb files.
re_run= after the three companions; parent exits 0
$ eval "$re_run"
generation_target=foss-2025a
done_when=exit 0
$ ls OUT/*.eb
OUT/ASAGI-1.0-foss-2025a.eb
OUT/PSpaMM-0.3.1-gfbf-2025a.eb
OUT/SeisSol-1.3.2-foss-2025a.eb
OUT/easi-1.7.0-foss-2025a.eb
Recorded: eb-stack package bump re_run, 2026-09-11
seissol.toml stores the inject digest and the local_* names. The
digest is not a Spack hash and not a working-tree hash.
[source_checksums]
# inject digest of the recursive git_config archive EasyBuild packed
"seissol-v1.3.2.tar.gz" = "inject"
[easyconfig]
local_host_arch = "hsw"
local_order = "6"
local_equations = "elastic"
EB-SeisSol-1 — Inspect, bump, or plan
For each starting point, name the eb-stack command, or say the work is not eb-stack’s.
spack/packages/seissol/package.py, and SeisSol-1.1.4-foss-2023a.eb already in the robot.easi-1.3.0-foss-2023a.eb, latest tag
v1.7.0, ImpalaJIT gone from CMake.PSpaMM0.3.1, Spackpackage.py, no easyconfig in the robot.The four
.ebfiles, nobody has runebyet.
Solution
Bump the existing easyconfig. That is the file EasyBuild will build. Inspect the Spack file for residuals. Do not emit from it.
package bump --version 1.7.0with the easi package-config. ImpalaJIT isexclude_from_solve. A missing ImpalaJIT on 2025a is not a companion.package planfrom the Spack recipe, ongfbf-2025a. PSpaMM has no easyconfig to bump.eb, or the site wrapper that isebon that machine.recipe checkis not a build.
The generation is a site fact¶
The newest common toolchain on develop in September 2026 is foss/2026.1.
A first bump onto that generation resolves.
It does not load on a node whose production stack is 2025.
foss/2025a is the generation that stack is built from.
eb -S SeisSol on that login node returns only SeisSol-1.1.4-foss-2023a.eb.
A foss/2026.1 recipe asks the robot for a generation the site has not built.
--robot will try to compile GCC 15 and the rest of 2026.1 beside the 2025 tree.
That compile writes into the user’s prefix and consumes home quota.
Which file loads on the 2025 stack
A login node has just run module load 2025.
Which of these four files can eblocalinstall resolve against
the modules already on the node?
SeisSol-1.3.2-foss-2026.1.ebSeisSol-1.3.2-intel-2025a.eb
What happens
(2).
foss/2025a is present.
2026.1 is not.
2025b exists as a toolchain module in some listings and is not
the generation the 2025 production recipes use.
intel is documented for local builds by experienced users, not
the default site stack.
The 2025a robot includes Lua 5.4.8 and libxsmm 1.17. easi 1.7.0 provides lmathx via Lua 5.4.
A warning states that Lua 5.5 may fail to compile.
The companion Lua 5.4.8 recipe that a 2026.1 bump would have added is unnecessary on 2025a.
The site wrapper is the install¶
The Snellius EasyBuild tutorial loads the site EasyBuild module after
module load 2025 and installs with eblocalinstall, not a raw eb
plus hand-set --installpath-software.
The wrapper writes software and modulefiles under the 2025 prefix:
$ eblocalinstall OUT/ASAGI-1.0-foss-2025a.eb
$ eblocalinstall OUT/PSpaMM-0.3.1-gfbf-2025a.eb
$ eblocalinstall OUT/easi-1.7.0-foss-2025a.eb
$ eblocalinstall OUT/SeisSol-1.3.2-foss-2025a.eb
Those four commands write under:
~/.local/easybuild/RHEL9/2025/software
~/.local/easybuild/RHEL9/2025/modules
Two defects the first build named¶
The patch that was no longer the patch¶
The first eblocalinstall failed on ASAGI.
EasyBuild hashed the file next to the recipe and compared it to da8c1c8c....
The file on disk hashed to something else.
A paste through a narrow terminal had wrapped the patch into a different byte string.
The named checksum was still the official ASAGI-1.0_fix-level.h.patch from develop.
The file under that name was not that archive.
A checksum is a claim about bytes is this failure, at site scale.
The repair fetches the upstream patch; hashing the broken file again repairs nothing.
The import that was the EasyBuild name¶
ASAGI then installed. PSpaMM failed sanity:
Default PythonPackage import
ModuleNotFoundError: No module named 'pspamm'
Recorded: site login node, 2026-09-11
The easyconfig is named PSpaMM.
EasyBuild’s PythonPackage imports pspamm.
The distribution’s module is pypspamm.
The console script is pspamm-generator.
The failed check was the one nobody wrote.
options = {'modulename': 'pypspamm'}
That line is the fix.
It now lives in the PSpaMM package-config, so the next package plan writes it.
A second eblocalinstall then completed PSpaMM, easi 1.7.0, and SeisSol 1.3.2.
SeisSol_Release_dhsw_6_elastic --help printed Show this help message.
HOST_ARCH=hsw is the CMake default.
The recipe stores it as local_host_arch, with local_order and local_equations.
local_binary and configopts are formatted from those three names.
A site that retargets the arch edits one assignment.
The binary runs on the login node and is not zen-tuned.
EB-SeisSol-2 — Which claim failed
Three failures. For each, name the claim that was false, and the smallest change that makes the claim true.
checksumslists the hash of a recursive working tree. EasyBuildgit_confighashes the tarball it packed.sanity_check_commandsrunspython -c "import pspamm"through the defaultPythonPackageimport.The recipe toolchain is
foss/2026.1. The node hasmodule load 2025andfoss/2025a.
Solution
The checksum named the wrong archive. Inject with
eb --inject-checksumson the EasyBuild host, or hash thegit_configtarball EasyBuild wrote. Do not keep the working-tree hash.The import name is
pypspamm. Setoptions = {'modulename': 'pypspamm'}. Leave thepspamm-generatorsanity command.The generation is not on the node. Retarget to
foss/2025a. A 2026.1 recipe is a different consume, not a fix of this one.
The overlay the PR names¶
The overlay is four files on the 2025 generation.
ASAGI 1.0, easi 1.7.0, PSpaMM 0.3.1 on
gfbf-2025a, SeisSol 1.3.2.The SeisSol checksum is the inject digest of the recursive
git_configarchive. It lives in the package-config assource_checksums. That digest is neither a Spack hash nor a working-tree hash.eb --check-contribpassed style and SHA256 on those four files.eb --new-propened easybuild-easyconfigs#26851 from the HaoZeke fork ontodevelop. The body names the four files and the Lua 5.4 bound on easi 1.7.0.resolvesis the SAT of the 2025a robot plus the overlay.buildsis the site wrapper install of those four files.A login-node
--helpis the sanity the recipe declared, not a TPV run.eb --from-pr 26851 --robot --forcerebuilt the same four files in 14 minutes 49 seconds. All results were SUCCESS. That is the report in the PR comment.
What to remember
The next file is a bump of the old easyconfig. Inspect Spack for residuals. Do not emit the EasyBuild file from Spack.
A parent bump that still needs companions exits 1 and prints
companion=. The overlay is done when the parent exits 0.PSpaMM is a
package planongfbf. easi drops ImpalaJIT in package-config, not in a hand edit.The generation is the one the site module environment already built. Newest-on-develop is a different consume.
The site wrapper is the install. Raw
ebwith hand-set prefixes is a different consume.A checksum names one archive. A PythonPackage import names one module. Neither is the EasyBuild software name.