eb-stack ports a recipe and bumps one¶
Port writes a file from someone else’s recipe. Bump moves pins on a file that already works. eb still has to run.¶
Questions
What does a conda-forge
recipe.yamlbecome, as an easyconfig?What does a bump change in a GROMACS file, and what does it leave?
What still has to run
eb?
What you will be able to do
Given a conda-forge recipe or a Spack
package.py, name the command that writes the.eb, and say what still has to be built.Read a bump: name every pin that moved with the toolchain, and the lines that did not.
Tell a port of software EasyBuild does not have from an annual retarget of software it does.
eb-stack performs two tasks.
One task is a port that takes input from conda-forge or Spack and produces an EasyBuild recipe.
The other task is a bump that rewrites an easyconfig written for one toolchain generation for the next.
Neither task invokes eb.
Both generate files that a human then builds.
eb-stack is the tool.
A planned CycloneDX SBOM is one of the files it writes.
The next figure is that SBOM for a GROMACS bump, drawn by eb-stack stack graph (and by scripts/sbom_to_dot.py).
Planned SBOM for a GROMACS generation. Edges are runtime dependsOn.¶
eb-stack writes an easyconfig. A port starts from someone else’s recipe. A bump retargets a generation. eb still has to run.¶
This page describes those two tasks and includes the files on the page.
A port starts as someone else’s recipe¶
The conda-forge feedstock for eOn 2.16.0 is frozen in eb-stack’s fixtures. It includes name, version, sources, host dependencies, and tests. That file is a conda-forge feedstock, which EasyBuild cannot read.
context:
version: "2.16.0"
package:
name: eon
version: ${{ version }}
source:
- url: https://github.com/TheochemUI/eOn/releases/download/v${{ version }}/eon-v${{ version }}.tar.xz
sha256: 3d4da89a393c8821bf370cb97c9d2403718d83f9cbb5e8b918cd90af14ed52dc
- url: https://github.com/OmniPotentRPC/rgpot/archive/refs/tags/v2.2.1.tar.gz
sha256: d4687bc719e19174e89288dd16dd45d7a8645d7205c7f8d8fc4d677266055918
target_directory: subprojects/rgpot
- url: https://github.com/lode-org/readcon-core/archive/refs/tags/v0.13.1.tar.gz
sha256: a261e69b87228dcc8f161eef800590b0395b4c93605b838c6216d40a1780f0bf
target_directory: readcon-core-src
requirements:
host:
- python
- numpy
- pyyaml
- eigen >=3.4,<3.5
- libblas
- quill
- xtb
- libtorch
- libmetatomic-torch >=0.1.15,<0.2
The command package plan converts the file to an easyconfig.
--format conda-forge selects the parser.
--stack-policy is required.
eb-stack package plan \
--source fixtures/foreign_ingest/conda_eon/recipe.yaml \
--format conda-forge \
--toolchain-name foss \
--toolchain-version 2024a \
--package-config examples/packages/common.toml \
--package-config examples/packages/eon.toml \
--easyconfigs /path/to/easybuild-easyconfigs \
--stack-policy site/foss-2024a.toml \
--out-dir /tmp/eon-from-conda
The command writes this tree:
package.plan.json
package.sbom.cdx.json
locks/default.lock.json
easyconfigs/e/eOn/eOn-2.16.0-foss-2024a.eb
The .eb is an emitted recipe; EasyBuild has compiled nothing yet.
Lock denotes solver assignment.
Plan includes parsed foreign recipe and residuals; parser‑invented items appear as typed leftovers, not guessed dependencies.
Inspect writes a work queue, not a recipe.
The feedstock and the Spack recipe are side by side.
Name and version remain retained.
eon transformed into eOn.
eigen >=3.4,<3.5 converted into pin for this generation.
libtorch renamed to PyTorch.
Meson flags originally set by feedstock’s build.sh now represented as configopts.
Three sources are used.
The target_directory: subprojects/rgpot entry became a staged extract in the full file; the widget above keeps the names.
In the full recipe, sanity_check_commands runs eonclient --version and python -c "import eon"; this mirrors the feedstock’s tests: block.
A Spack package.py file is the other input.
The paper Gamblin et al. [2015] describes that format.
A spec is a DAG of constraints (name, versions, variants, compiler, arch, deps). A concretiser selects one graph.
The same software is parsed differently.
--format spack specifies the parser.
The file is Python and is not executed; literal depends_on and version calls are interpreted as syntax.
class Eon(MesonPackage):
homepage = "https://eondocs.org/"
url = "https://github.com/TheochemUI/eOn/releases/download/v2.16.0/eon-v2.16.0.tar.xz"
version("2.16.0", sha256="3d4da89a393c8821bf370cb97c9d2403718d83f9cbb5e8b918cd90af14ed52dc")
depends_on("meson@1.8.0:", type="build") # meson 1.8.0 or newer
depends_on("python@3.11:", type=("build", "run"))
depends_on("py-numpy", type=("build", "run"))
depends_on("eigen@3.4:")
depends_on("quill@11:")
depends_on("readcon-core@0.13.1:")
depends_on("highway")
depends_on("libinih")
depends_on("eigen@3.4:") (eigen 3.4 or newer) defines a range.
EasyBuild does not support ranges (A pin is for one generation).
The solver selects Eigen-3.4.0 from the robot tree for that generation.
A def patch(self): that executes sed is not a file.
It becomes a judgment residual.
The emitted .eb does not claim that the sed occurred.
Inspect writes the work queue. The campaign then runs it.
The queue is visible first.
Plan then consumes the robot tree only for items already decided.
package inspect uses the same parsers without performing the solve.
It writes package.plan.json.
It writes a planned SBOM.
It produces no .eb.
Use it to read residuals.
Use package plan to select non‑blocking items.
Use package plan to emit the file.
A bump starts as an easyconfig that already works¶
GROMACS 2024.4 builds with foss/2023b.
The file exists.
The yearly job uses the same software on foss/2024a.
Manual copying of the file and alteration of four version strings creates pins that become undocumented floors.
A bump writes one file. EasyBuild has not started.
$ eb-stack package bump \
> --source tests/repro_fixtures/gromacs/GROMACS-2024.4-foss-2023b.eb \
> --toolchain-name foss \
> --toolchain-version 2024a \
> --easyconfigs tests/repro_fixtures/universe_foss_2024a \
> --out-dir /tmp/gromacs-2024a
wrote /tmp/gromacs-2024a/GROMACS-2024.4-foss-2024a.eb
Recorded: workstation, eb-stack 0.2.0, 2026-09-11, tests/repro_fixtures/gromacs plus universe_foss_2024a
Parameter |
2023b |
2024a |
|---|---|---|
|
|
|
|
3.27.6 |
3.29.3 |
|
0.9.3 |
0.11.1 |
|
3.11.5 |
3.12.3 |
|
2023.11 |
2024.05 |
|
3.2.1 |
3.4.2 |
|
3.1.5 |
4.0.1 |
Unchanged lines include name, version, sources, patches, checksums, configopts, exts_list.
The application version is 2024.4.
Tarball bytes are identical.
Each pin on the toolchain moved together with the toolchain.
The candidate set is the 2024a robot tree.
Resolvo chose a single consistent closure.
Use the same command with --version and --source-checksum to increase the application version.
If the checksum is omitted, the tarball name changes.
The hash becomes stale.
That missing hash is a blocking residual, and nothing guesses a checksum for it.
Two commands, then eb¶
Job |
Command |
Input |
Output |
|---|---|---|---|
read a foreign recipe |
|
|
plan + SBOM, no |
port it |
|
the same, plus a robot tree and a stack policy |
plan, lock, |
retarget a generation |
|
an existing |
plan, lock, new |
build what was written |
|
the bundle |
|
recipe lint examines the file.
recipe check examines the file.
See Format, lint and check are three different questions.
campaign run is the initial command that performs compilation.
See A campaign finding is a typed failure, not a log.
A green plan represents the claim resolves.
It does not represent the claim builds.
EB-Port-1 — Port, bump, or neither
Four starting points. For each, name the eb-stack command, or say the work is not eb-stack’s.
fixtures/foreign_ingest/spack_qmcpack/package.py, no QMCPACK easyconfig in the robot.
GROMACS-2024.4-foss-2023b.eb, site moving to
foss/2024a.The
.ebfrom (1), in a bundle, nobody has runebyet.A tarball and a README, no conda-forge recipe, no Spack package, no easyconfig.
Solution
package plan --format spack. Inspect first if the residuals are unknown. The output is an easyconfig plus a lock.package bump. The source is already an easyconfig. The robot tree for 2024a is the candidate set.campaign run, orebon that file. eb-stack has finished the generator’s job.Writing one from nothing. There is nothing to parse. The five mandatory parameters are written by hand.
The full sequence of inspect, bump, site generation, and upstream PR appears in SeisSol, from a Spack recipe to a PR.
What to remember
A port reads conda-forge or Spack and writes an easyconfig.
package plan --format conda-forgeor--format spack.A bump reads an easyconfig and writes the same software on a new toolchain generation. Application version, sources and patches stay; every pin that lives on the toolchain moves.
A Spack
eigen@3.4:is a lower bound. The robot either finds a pin this generation ships or the range stays a residual.Nothing in inspect, plan or bump compiles the package.
campaign runcallseb.