Solve a consistent stack lock#

Use stack solve for a multi-root EasyBuild generation lock. This is separate from per-profile stack-policy TOML used by package plan and package bump.

Write a whole-stack policy#

{
  "toolchain": {"name": "foss", "version": "2025b"},
  "roots": ["GROMACS"],
  "root_priority": ["GROMACS"],
  "pins": [],
  "forbid": [],
  "objective": "prefer_newer",
  "require_upgrade": {"name": "GROMACS", "relative_to_baseline": true}
}

Roots and all declared runtime/build requirements are co-selected. Explicit root_priority makes multi-root optimization stable under root-list order.

Solve with overlays and reports#

eb-stack stack solve \
  --easyconfigs fixtures/gromacs_2025_to_next/easyconfigs \
  --policy fixtures/gromacs_2025_to_next/policies/prefer_newer.json \
  --baseline-easyconfigs fixtures/gromacs_2025_to_next/easyconfigs \
  --lock-out stack.lock.json \
  --sbom-out stack.cdx.json \
  --build-list-out build.list \
  --stack-diff-out stack.diff.md

--easyconfigs is repeatable. Later paths override earlier paths for the same name, version, toolchain, and versionsuffix identity. A site-only package is added to the universe normally.

When the baseline tree includes several generations, use --baseline-toolchain-version to select one explicitly. A relative require_upgrade fails if the baseline package is absent or no newer candidate is jointly feasible.

Pin or forbid candidates#

Policy pins use EasyBuild-shaped requirements such as ==0.3.24, >=1.14, or a compound range. forbid accepts a package name or full easyconfig path. An unsatisfiable solve reports package names and versions from the actual candidate graph.

Emit an SBOM from an existing lock#

eb-stack stack sbom --lock stack.lock.json --out stack.cdx.json

A lock-only SBOM cannot reconstruct dependency edges and does not invent them. Use --sbom-out during stack solve when the full candidate graph is available.

See the policy reference and the format reference.