What a toolchain injects¶
Loading the toolchain module does not set $CC. The toolchain object sets the compilers inside prepare.¶
The toolchain injects compilers and flags during prepare, not when the module is loaded.¶
The toolchain injects compilers, flags, and libraries the easyconfig never lists.¶
What you will be able to do
Say which environment variables a toolchain sets during a build, and where they come from.
Read a
toolchainoptsdictionary and say what each option changes.Say what
optarchdoes and why it decides where a binary can run.
A toolchain is a hierarchy covered the dependencies a toolchain makes visible. This page addresses the other half: the impact on the compiler.
The variables, and where they are not¶
The isolation policy measured the surprising part.
Restating is worthwhile.
Loading a toolchain module provides EBROOTFOSS and EBVERSIONFOSS.
$CC is not provided.
EasyBuild’s toolchain object sets the compiler variables during prepare inside the build.
A foss build receives, among others, the following variables:
Variable |
Contents |
|---|---|
|
the compiler drivers |
|
the MPI wrappers |
|
optimisation and architecture flags |
|
library and include paths for every dependency |
|
the link lines for the numerical libraries |
The final row explains why a foss easyconfig seldom names a BLAS.
The toolchain identifies the BLAS and supplies the build with its link line.
An easyconfig that hardcodes -lopenblas describes a specific toolchain and will become incorrect for subsequent toolchains.
The practical consequence matches that described in the isolation policy.
Reproducing a build’s environment requires more than loading its toolchain.
eb --dump-env-script is necessary, as explained in Standing where the build stood.
toolchainopts is a dictionary of switches¶
Each key sets the values that the toolchain object places into those variables.
foss in EasyBuild 5.3 accepts roughly thirty entries.
The list is:
The options a foss build accepts, abridged
$ eb --avail-toolchain-opts=foss
Available options for foss toolchain:
cstd: Specify C standard (default: None)
debug: Keep debug symbols (default: None)
extra_cflags: Specify extra CFLAGS options. (default: None)
i8: Integers are 8 byte integers (default: False)
ieee: Adhere to IEEE-754 rules (default: False)
lto: Enable Link Time Optimization (default: False)
noopt: Disable compiler optimizations (default: False)
openmp: Enable OpenMP (default: False)
opt: High compiler optimizations (default: False)
optarch: Enable architecture optimizations (default: True)
pic: Use PIC (default: False)
shared: Build shared library (default: False)
static: Build static library (default: False)
strict: Strict (highest) precision (default: False)
usempi: Use MPI compiler as default compiler (default: False)
verbose: Verbose output (default: False)
veryloose: Very loose precision (default: False)
Recorded: SURF Snellius, 2026-09-10, EasyBuild 5.3.1
Four of them cover most of the entries found in real easyconfigs.
usempi sets $CC to the MPI wrapper instead of the bare compiler.
A package whose build system lacks MPI wrapper awareness and uses $CC receives MPI through those variables.
Use it for parallel software whose configure script does not provide --with-mpi.
openmp adds the compiler’s OpenMP flag.
It is required.
The source contains #pragma omp.
The build system does not supply the flag.
pic adds -fPIC.
It is required.
A static library is linked into a shared one.
The resulting error without it mentions a relocation rather than a recognizable symbol.
The precision family strict through veryloose should remain unchanged.
A specific reason must exist to change it.
It alters floating-point semantics.
It changes results.
A physics code that specifies strict asserts a claim about its own numerics.
Altering it without saying so modifies the scientific outcome.
optarch decides where the binary runs¶
optarch is enabled by default and has the greatest impact.
When enabled, the compiler receives -march=native or the toolchain’s equivalent to optimise for the current microarchitecture.
That binary runs faster and may use instructions unavailable on other processors in the same cluster.
Those variables underlie What “installed” means’s per-architecture install trees.
A site with mixed hardware maintains separate trees not for tidiness but.
There are two methods for a site to control this.
Specifying --optarch on the command line sets the flag globally.
The site can then build for a named baseline instead of the specific node where the build occurs.
Setting toolchainopts = {'optarch': False} disables it for a single package.
Use this option when a package is known to miscompile under aggressive optimisation.
An easyconfig requiring optarch: False must include an explanatory comment.
The comment is a claim about the software rather than the site.
It stops a later reader from taking the setting for a cargo‑culted one.
EB-Toolchainopts-1 — Four errors, four options
Four build failures, each fixed by one toolchainopts key.
undefined reference to `omp_get_num_threads'relocation R_X86_64_32S against `.rodata' can not be used when making a shared objectmpi.h: No such file or directory, from a Makefile that compiles with$(CC)The build succeeds on the build host and dies with
Illegal instructionon an older node in the same cluster.
Give the key for each. Then say which of the four is not really a toolchain question at all, and what you would rather do about it.
Solution
1 is openmp. The source uses OpenMP and nothing added the flag.
2 is pic. Something static is being linked into something shared.
3 is usempi, so $CC becomes the MPI wrapper and mpi.h is on the
include path. The alternative is patching the Makefile to use $(MPICC),
which is more honest and more work.
4 is optarch, and it is the one that is not really a toolchain
question. Setting optarch: False for this package would fix the symptom
by making the binary slower everywhere, to accommodate a node it was
never built for. The real answer is the site’s: either build per
architecture, as What “installed” means describes, or set a site-wide --optarch
baseline that every node can run. A per-easyconfig fix for a site-wide
hardware fact is the wrong layer.
What to remember
Loading a toolchain module does not set
$CCor$LIBBLAS.Those variables exist only inside a build, from the toolchain class and
toolchainopts.Debugging by loading
fossand re-running the failing command misses that injection.