EasySpack is a set of utilities that exposes packages built with EasyBuild and distributed by EESSI to Spack. This makes Spack aware of the available EasyBuild/EESSI installation, thus letting it reuse the available packages when building new ones.
Most of the examples provided consider an existing EESSI installation, but similar logic can be applied to any EasyBuild installation that uses rpaths.
- Python 3.7+
- Spack 1.1+ (ideally Spack 1.2, will include several bug fixes and improvements)
IMPORTANT
To work with EESSI, you currently need a patched version of Spack: https://github.com/lorisercole/spack/tree/eessi\ This includes bug fixes and improvements for EESSI integration. - EESSI environment if you want to mirror the published stacks.
Development installation:
pip install -e .Before running examples, make sure that the EESSI is activated, e.g.
export EESSI_VERSION=2023.06
module unuse ${MODULEPATH} && module use /cvmfs/software.eessi.io/init/modules && module load EESSI/${EESSI_VERSION}- Most of the scripts in this package should be run using the
spack-pythonwrapper. This ensures the Spack is correctly imported and initialized. - Set the env variable
EASYSPACK_DEBUG=1for verbose logging. - Check the sections below for specific instructions and examples. A quick-start demo example is provided.
If you want to define a custom Spack user-scope configuration directory, you can set the following env vars, as described in the documentation:
export SPACK_USER_CONFIG_PATH=/home/lercole/eessi/spack
export SPACK_USER_CACHE_PATH=/home/lercole/eessi/spack/cacheNOTE – The user should have write access to these paths.
You typically want to edit Spack's configuration files:
concretizer.yaml: to reuse installed packages.config.yaml: to set the location of Spack-installed packages.modules.yaml: to set the location of modules generated by Spack (if needed).upstreams.yaml: to use an upstream database that was generated by easyspack (only if you generate a db).
A typical Spack user-scope configuration that would work with a system/site installation of Spack can be generated from the templates available in the share/spack_config folder, by replacing INSTALL_BASE_PATH with the absolute path of the installation directory (it can be the same as SPACK_USER_CONFIG_PATH). To do so, you can run this code:
SHARE_DIR="./share/spack_config"
export INSTALL_BASE_PATH=$SPACK_USER_CONFIG_PATH # Set to your installation path
envsubst < $SHARE_DIR/config.yaml.tpl > $SPACK_USER_CONFIG_PATH/config.yaml
envsubst < $SHARE_DIR/modules.yaml.tpl > $SPACK_USER_CONFIG_PATH/modules.yaml
envsubst < $SHARE_DIR/upstreams.yaml.tpl > $SPACK_USER_CONFIG_PATH/upstreams.yaml
cp $SHARE_DIR/concretizer.yaml $SPACK_USER_CONFIG_PATH/concretizer.yamlThis is the official Spack-onic way of exposing EESSI software builds to a Spack installation.
It consists of these steps:
-
Declare EESSI software-layer builds as external packages in a
packages.yamlSpack configuration file (with external dependencies).
Example:examples/ext_install/externals_nocompat.yaml. -
(optional, suggested) detect OS packages available under the EESSI compat-layer, and configure Spack to use them as externals. In EESSI, these packages are often dependencies of software-layer packages, so it is suggested to include them. This can be done with:
spack external find --all -p "${EESSI_EPREFIX}" --exclude gcc spack external find --all -p "${EESSI_EPREFIX}/usr" --exclude gcc
-
Externals are then visible via
spack find --show-configured-externalsand get reused during Spack solves by default.
The steps above will suffice to have Spack reuse an available software stack. The first time you want to concretize a new spec that is not yet installed, the only packages that Spack may need to install (not build from source) are:
gcc-runtime: Spack will simply copy the GCC runtime libraries into the local installation folder. This is a small set of libraries.compiler-wrapper: Spack's own compiler wrapper, needed to compile packages.- anything that is not available as external package, of course.
The quick_start.sh bash script demonstrates the recommended approach to configure a new Spack installation and prepare the packages.yaml config file that exposes EESSI-provided packages to Spack.
The generated packages.yaml file includes software-layer and compat-layer packages, and should be equivalent to examples/ext_install/packages.yaml.
It will then try to build a new version of Quantum ESPRESSO (without MPI support):
$ spack spec -Ilt quantum-espresso~mpi
- [ ] quantum-espresso@7.4.1~clock+epw~fox~gipaw~ipo~libxc~mpi~nvtx+openmp+patch~qmcpack build_system=cmake build_type=Release generator=make hdf5=none platform=linux os=ubuntu24.04 target=skylake %c,cxx,fortran=gcc@13.2.0
[e] [b ] ^cmake@3.31.8~doc+ncurses+ownlibs~qtgui build_system=generic build_type=Release platform=linux os=ubuntu24.04 target=haswell %c,cxx=gcc@13.2.0
[e] [ l ] ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu24.04 target=x86_64
[e] [bl ] ^curl@8.3.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs:=shared,static tls:=openssl platform=linux os=ubuntu24.04 target=haswell %c,cxx=gcc@13.2.0
[e] [bl ] ^libarchive@3.7.2+iconv build_system=autotools compression:=bz2lib,lz4,lzma,lzo2,zlib,zstd crypto=openssl libs:=shared,static programs:=none xar=libxml2 platform=linux os=ubuntu24.04 target=haswell %c,cxx=gcc@13.2.0
[e] [bl ] ^ncurses@6.4.20230401+symlinks+termlib abi:=6 build_system=autotools platform=linux os=ubuntu24.04 target=x86_64
[e] [bl ] ^openssl@1.1.1w~docs+shared build_system=generic certs=mozilla platform=linux os=ubuntu24.04 target=x86_64
[e] [bl ] ^zlib@1.2.13+optimize+pic+shared build_system=makefile platform=linux os=ubuntu24.04 target=x86_64
- [b ] ^compiler-wrapper@1.0 build_system=generic platform=linux os=ubuntu24.04 target=skylake
[e] [bl ] ^fftw@3.3.10~mpi+openmp~pfft_patches+shared build_system=autotools precision:=double,float,long_double,quad platform=linux os=ubuntu24.04 target=haswell %c,fortran=gcc@13.2.0
[e] [b ] ^gcc@13.2.0~binutils+bootstrap~graphite~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu24.04 target=haswell
- [ l ] ^gcc-runtime@13.2.0 build_system=generic platform=linux os=ubuntu24.04 target=skylake
[e] [b ] ^git@2.41.0+man+nls+perl+subtree~svn~tcltk build_system=autotools platform=linux os=ubuntu24.04 target=x86_64
[e] [ l ] ^glibc@2.37 build_system=autotools platform=linux os=ubuntu24.04 target=x86_64
[e] [b ] ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu24.04 target=haswell %c=gcc@13.2.0
[e] [b ] ^m4@1.4.19+sigsegv build_system=autotools platform=linux os=ubuntu24.04 target=x86_64
[e] [bl ] ^openblas@0.3.24~bignuma~consistent_fpcsr+dynamic_dispatch+fortran~ilp64+locking+pic+shared build_system=makefile symbol_suffix=none threads:=openmp platform=linux os=ubuntu24.04 target=haswell %c,cxx,fortran=gcc@13.2.0
Most of the dependencies are taken from EESSI as external packages. Only gcc-runtime and compiler-wrapper need to be built.
The default build target (microarchitecture) is the one detected by spack arch, i.e. "skylake" in this case.
Notice however that the software provided by EESSI and reused by Spack was built for the "haswell" microarchitecture, that is compatible with skylake.
Packages from the compat-layer are built for an even more generic architecture: "x86_64".
-
Specs:
- Default variants are automatically completed by Spack concretizer if they are not specified. This behavior can be configured, but it seems the best approach according to our tests.
- If a version of a package does not exist in Spack, that is not a problem.
-
Dependencies:
- Only link & runtime dependencies need to be declared for externals that might be reused; pure build deps can be omitted.
- Only exception: it is advised to specify the compiler as build-type dependency. Spack may use this information when deciding which packages to reuse.
- Skipping dependencies that are not needed for EasyBuild or Spack does not seem to lead to problems. But you should declare dependencies that you know of according to the above considerations.
- If you declare a dependency that is not supposed to be a dependency according to the package Spack recipe, it is not a problem.
glibcis detected and injected automatically by Spack when compilers are present.
-
Compilers:
- Compilers do not need dependencies, but you should specify
extra_attributeswith compiler paths pointing to the compiler binaries, see spack docs.
- Compilers do not need dependencies, but you should specify
-
EESSI specific considerations:
- The EESSI compatibility layer filters some packages (e.g.,
glibc,binutils,ncurses,xz); be cautious when mirroring or detecting from it. - Some packages are filtered out in EESSI, as they are installed in the compatibility layer:
Autoconf,Automake,Autotools,binutils,bzip2,DBus,flex,gettext,gperf,help2man,intltool,libreadline,libtool,M4,makeinfo,ncurses,util-linux,XZ,zlib. - If you want to explicitly declare a dependency on one of them, you should detect them using
spack external find, as explained in the example above, in order to make sure they are included inpackages.yaml.
- The EESSI compatibility layer filters some packages (e.g.,
-
See NOTES.md for more technical information.
Externals defined in a YAML file such as examples/ext_install/packages.yaml can be converted into a Spack database that can be then used as an upstream database, without the need to define external packages. Runtime deps (glibc, gcc-runtime) can be automatically injected.
This is not the officially-supported method, but it works, and it should avoid the need to have a separate gcc-runtime copy. The only packages that need to be defined in packages.yaml are compilers.
Example script:
external_pkgs_install.py
Reads a YAML file defining externals, likeexamples/ext_install/externals_nocompat.yaml, injects runtime deps, detects OS packages, installs them into a Spack upstream DB, and updatespackages.yaml.
What happens:
UpstreamInstallerparses the YAML, completes architectures/variants, and injectsglibc/gcc-runtimeruntime dependencies when relevant.- Additional detectable packages under
EESSI_EPREFIXandEESSI_EPREFIX/usrare discovered and added as externals. - All externals are registered into an upstream DB (e.g. at
/home/lercole/eessi/spack/upstreams/eessi). Only compilers are added to apackages.yaml.
This older approach uses SpecLoader in easyspack/legacy/loader.py to read a dictionary provided by the user (following easyspack/legacy/schema.py), generate concrete specs, inject runtime libs, and writes a full upstream DB. This flow is kept for reference, but it is superseded by the external packages approach.
Example script:
upstreamdb_legacy.py
Example script for this approach, that uses theexamples/upstream_db/eessi_example.pyexample data.
Note: only works with Spack 1.1
You can join the discussion on the #spack channel of EESSI Slack.
Notes of previous meetings can be found here.