Tutorial setup
If you have not done the prior sections, you’ll need to start the docker image:
docker run -it ghcr.io/spack/tutorial:hpcic24
and then set Spack up like this:
git clone --depth=100 --branch=releases/v0.22 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack tutorial -y
spack bootstrap now
spack compiler find
See the Basic Installation Tutorial for full details on setup. For more
help, join us in the #tutorial
channel on Slack – get an
invitation at slack.spack.io
Configuration Tutorial
This tutorial will guide you through various configuration options that allow you to customize Spack’s behavior with respect to software installation. We will first cover the configuration file hierarchy. Then, we will cover configuration options for compilers, focusing on how they can be used to extend Spack’s compiler auto-detection. Next, we will cover the packages configuration file, focusing on how it can be used to override default build options as well as specify external package installations to use. Finally, we will briefly touch on the config configuration file, which manages more high-level Spack configuration options.
For all of these features, we will demonstrate how we build up a full
configuration file. For some, we will then demonstrate how the
configuration affects the install command, and for others we will use
the spack spec
command to demonstrate how the configuration
changes have affected Spack’s concretization algorithm. The provided
output is all from a server running Ubuntu version 22.04.
Configuration from the command line
One of the most convenient ways to set configuration options is through the command line. For the purpose of this tutorial section, we actually want to start out with that, as we need to tell Spack it should consider package preferences more important than reuse of available binaries:
$ spack config add concretizer:reuse:false
Spack will set this option in your user configuration scope.
Configuration Scopes
Depending on your use case, you may want to provide configuration settings common to everyone on your team, or you may want to set default behaviors specific to a single user account. Spack provides six configuration scopes to handle this customization. These scopes, in order of decreasing priority, are:
Scope |
Directory |
---|---|
Command-line |
N/A |
Environment |
In environment base directory (in |
Custom |
Custom directory, specified with |
User |
|
Site |
|
System |
|
Defaults |
|
Spack’s default configuration settings reside in
$SPACK_ROOT/etc/spack/defaults
. These are useful for reference,
but should never be directly edited. To override these settings,
create new configuration files in any of the higher-priority
configuration scopes.
A particular cluster may have multiple Spack installations associated
with different projects. To provide settings common to all Spack
installations, put your configuration files in /etc/spack
.
To provide settings specific to a particular Spack installation,
you can use the $SPACK_ROOT/etc/spack
directory.
For settings specific to a particular user, you will want to add
configuration files to the ~/.spack
directory. When Spack first
checked for compilers on your system, you may have noticed that it
placed your compiler configuration in this directory.
Configuration settings can also be placed in a custom location,
which is then specified on the command line via --config-scope
.
An example use case is managing two sets of configurations, one for
development and another for production preferences.
Settings specified on the command line have precedence over all other configuration scopes.
You can also use spack config blame <config>
for displaying
the effective configuration. Spack will show from which scopes
the configuration has been assembled.
Platform-specific scopes
Some facilities manage multiple platforms from a single shared file system. In order to handle this, each of the configuration scopes listed above has two sub-scopes: platform-specific and platform-independent. For example, compiler settings can be stored in the following locations:
$ENVIRONMENT_ROOT/spack.yaml
~/.spack/<platform>/compilers.yaml
~/.spack/compilers.yaml
$SPACK_ROOT/etc/spack/<platform>/compilers.yaml
$SPACK_ROOT/etc/spack/compilers.yaml
/etc/spack/<platform>/compilers.yaml
/etc/spack/compilers.yaml
$SPACK_ROOT/etc/defaults/<platform>/compilers.yaml
$SPACK_ROOT/etc/defaults/compilers.yaml
These files are listed in decreasing order of precedence, so files in
~/.spack/<platform>
will override settings in ~/.spack
.
YAML Format
Spack configurations are nested YAML dictionaries with a specified
schema. The configuration is organized into sections based on theme
(e.g., a ‘compilers’ section) and the highest-level keys of the dictionary
specify the section. Spack generally maintains a separate file for
each section, although environments keep them together (in
spack.yaml
).
When Spack checks its configuration, the configuration scopes are updated as dictionaries in increasing order of precedence, allowing higher precedence files to override lower. YAML dictionaries use a colon “:” to specify key-value pairs. Spack extends YAML syntax slightly to allow a double-colon “::” to specify a key-value pair. When a double-colon is used, instead of adding that section, Spack replaces what was in that section with the new value. For example, consider a user’s compilers configuration file as follows:
compilers::
- compiler:
spec: gcc@11.4.0
paths:
cc: /usr/bin/gcc
cxx: /usr/bin/g++
f77: /usr/bin/gfortran
fc: /usr/bin/gfortran
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
This ensures that no other compilers are used, as the user configuration
scope is the last scope searched and the compilers::
line replaces
information from all previous configuration files. If the same
configuration file had a single colon instead of the double colon, it
would add the GCC version 11.3.0 compiler to whatever other compilers
were listed in other configuration files.
A configuration section appears nearly the same when managed in an
environment’s spack.yaml
file except that the section is nested 1
level underneath the top-level ‘spack’ key. For example the above
compilers.yaml
could be incorporated into an environment’s
spack.yaml
like so:
spack:
specs: []
view: true
compilers::
- compiler:
spec: gcc@11.4.0
paths:
cc: /usr/bin/gcc
cxx: /usr/bin/g++
f77: /usr/bin/gfortran
fc: /usr/bin/gfortran
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
Compiler Configuration
For most tasks, we can use Spack with the compilers auto-detected the
first time Spack runs on a system. As discussed in the basic
installation tutorial, we can also tell Spack where compilers are
located using the spack compiler add
command. However, in some
circumstances we want even more fine-grained control over the
compilers available. This section will teach you how to exercise that
control using the compilers configuration file.
We will start by opening the compilers configuration file:
$ spack config edit compilers
We start with no active environment, so this will open a
compilers.yaml
file for editing (you can also do this with an
active environment):
compilers:
- compiler:
spec: clang@=14.0.0
paths:
cc: /usr/bin/clang
cxx: /usr/bin/clang++
f77:
fc:
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@=10.5.0
paths:
cc: /usr/bin/gcc-10
cxx: /usr/bin/g++-10
f77: usr/bin/gfortran-10
fc: usr/bin/gfortran-10
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
- compiler:
spec: gcc@=11.4.0
paths:
cc: /usr/bin/gcc
cxx: /usr/bin/g++
f77: /usr/bin/gfortran
fc: /usr/bin/gfortran
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
This specifies two versions of the GCC compiler and one version of the
Clang compiler with no Flang compiler. Now suppose we have a code that
we want to compile with the Clang compiler for C/C++ code, but with
gfortran for Fortran components. We can do this by adding another entry
to the compilers.yaml
file:
- compiler:
spec: clang@=14.0.0-gfortran
paths:
cc: /usr/bin/clang
cxx: /usr/bin/clang++
f77: /usr/bin/gfortran
fc: /usr/bin/gfortran
flags: {}
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
Let’s talk about the sections of this compiler entry that we’ve changed.
The biggest change we’ve made is to the paths
section. This lists
the paths to the compilers to use for each language/specification.
In this case, we point to the Clang compiler for C/C++ and the gfortran
compiler for both specifications of Fortran. We’ve also changed the
spec
entry for this compiler. The spec
entry is effectively the
name of the compiler for Spack. It consists of a name and a version
number, separated by the @
sigil. The name must be one of the supported
compiler names in Spack (aocc, apple-clang, arm, cce, clang, dpcpp, fj,
gcc, intel, msvc, nag, nvhpc, oneapi, pgi, rocmcc, xl, xl_r).
The version number can be an arbitrary string of alphanumeric characters,
as well as -
, .
, and _
. The target
and operating_system
sections we leave unchanged. These sections specify when Spack can use
different compilers, and are primarily useful for configuration files that
will be used across multiple systems.
We can verify that our new compiler works by invoking it now:
$ spack install --no-cache zlib %clang@14.0.0-gfortran
...
This new compiler also works on Fortran codes. We’ll show it by
compiling a small package using as a build dependency cmake%gcc@11.4.0
since it is already available in our binary cache:
$ spack install --reuse cmake %gcc@11.4.0
...
$ spack install --no-cache --reuse json-fortran %clang@=14.0.0-gfortran ^cmake%gcc@11.4.0
...
Compiler flags
Some compilers may require specific compiler flags to work properly in
a particular computing environment. Spack provides configuration
options for setting compiler flags every time a specific compiler is
invoked. These flags become part of the package spec and therefore of
the build provenance. As on the command line, the flags are set
through the implicit build variables cflags
, cxxflags
, cppflags
,
fflags
, ldflags
, and ldlibs
.
Let’s open our compilers configuration file again and add a compiler flag:
- compiler:
spec: clang@=14.0.0-gfortran
paths:
cc: /usr/bin/clang
cxx: /usr/bin/clang++
f77: /usr/bin/gfortran
fc: /usr/bin/gfortran
flags:
cppflags: -g
operating_system: ubuntu22.04
target: x86_64
modules: []
environment: {}
extra_rpaths: []
We can test this out using the spack spec
command to show how the
spec is concretized:
$ spack spec json-fortran%clang@14.0.0-gfortran
Input spec
--------------------------------
- json-fortran%clang@14.0.0-gfortran
Concretized
--------------------------------
- json-fortran@8.3.0%clang@14.0.0-gfortran cppflags="-g" ~ipo build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%clang@14.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%clang@14.0.0-gfortran cppflags="-g" ~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
- ^nghttp2@1.57.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%clang@14.0.0-gfortran cppflags="-g" ~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
- ^ca-certificates-mozilla@2023-05-30%clang@14.0.0-gfortran cppflags="-g" build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^perl@5.38.0%clang@14.0.0-gfortran cppflags="-g" +cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-ubuntu22.04-x86_64_v3
- ^berkeley-db@18.1.40%clang@14.0.0-gfortran cppflags="-g" +cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-ubuntu22.04-x86_64_v3
- ^bzip2@1.0.8%clang@14.0.0-gfortran cppflags="-g" ~debug~pic+shared build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^diffutils@3.9%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libiconv@1.17%clang@14.0.0-gfortran cppflags="-g" build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^gdbm@1.23%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^readline@8.2%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=bbf97f1 arch=linux-ubuntu22.04-x86_64_v3
- ^pkgconf@1.9.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^ncurses@6.4%clang@14.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^zlib-ng@2.1.4%clang@14.0.0-gfortran cppflags="-g" +compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gmake@4.4.1%clang@14.0.0-gfortran cppflags="-g" ~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
We can see that cppflags="-g"
has been added to every node in the DAG.
Advanced compiler configuration
There are four fields of the compiler configuration entry that we have not yet talked about.
The target
field of the compiler defines the cpu architecture family
that the compiler supports.
- compiler:
...
target: ppc64le
...
The modules
field of the compiler was originally designed to
support older Cray systems, but can be useful on any system that has
compilers that are only usable when a particular module is loaded. Any
modules in the modules
field of the compiler configuration will be
loaded as part of the build environment for packages using that
compiler:
- compiler:
...
modules:
- PrgEnv-gnu
- gcc/5.3.0
...
The environment
field of the compiler configuration is used for
compilers that require environment variables to be set during build
time. For example, if your Intel compiler suite requires the
INTEL_LICENSE_FILE
environment variable to point to the proper
license server, you can set this in compilers.yaml
as follows:
- compiler:
...
environment:
set:
INTEL_LICENSE_FILE: 1713@license4
...
In addition to set
, environment
also supports unset
,
prepend_path
, and append_path
.
The extra_rpaths
field of the compiler configuration is used for
compilers that do not rpath all of their dependencies by
default. Since compilers are often installed externally to Spack,
Spack is unable to manage compiler dependencies and enforce
rpath usage. This can lead to packages not finding link dependencies
imposed by the compiler properly. For compilers that impose link
dependencies on the resulting executables that are not rpath’ed into
the executable automatically, the extra_rpaths
field of the compiler
configuration tells Spack which dependencies to rpath into every
executable created by that compiler. The executables will then be able
to find the link dependencies imposed by the compiler. As an example,
this field can be set by:
- compiler:
...
extra_rpaths:
- /apps/intel/ComposerXE2017/compilers_and_libraries_2017.5.239/linux/compiler/lib/intel64_lin
...
Configuring Package Preferences
Package preferences in Spack are managed through the packages
configuration section. First, we will look at the default packages.yaml
file.
$ spack config --scope defaults edit packages
# -------------------------------------------------------------------------
# This file controls default concretization preferences for Spack.
#
# Settings here are versioned with Spack and are intended to provide
# sensible defaults out of the box. Spack maintainers should edit this
# file to keep it current.
#
# Users can override these settings by editing the following files.
#
# Per-spack-instance settings (overrides defaults):
# $SPACK_ROOT/etc/spack/packages.yaml
#
# Per-user settings (overrides default and site settings):
# ~/.spack/packages.yaml
# -------------------------------------------------------------------------
packages:
all:
compiler: [gcc, intel, pgi, clang, xl, nag, fj, aocc]
providers:
awk: [gawk]
blas: [openblas, amdblis]
D: [ldc]
daal: [intel-daal]
elf: [elfutils]
fftw-api: [fftw, amdfftw]
flame: [libflame, amdlibflame]
fuse: [libfuse]
gl: [glx, osmesa]
glu: [mesa-glu, openglu]
golang: [go, gcc]
go-external-or-gccgo-bootstrap: [go-bootstrap, gcc]
iconv: [libiconv]
ipp: [intel-ipp]
java: [openjdk, jdk, ibm-java]
jpeg: [libjpeg-turbo, libjpeg]
lapack: [openblas, amdlibflame]
libglx: [mesa+glx, mesa18+glx]
libllvm: [llvm]
libosmesa: [mesa+osmesa, mesa18+osmesa]
lua-lang: [lua, lua-luajit-openresty, lua-luajit]
luajit: [lua-luajit-openresty, lua-luajit]
mariadb-client: [mariadb-c-client, mariadb]
mkl: [intel-mkl]
mpe: [mpe2]
mpi: [openmpi, mpich]
mysql-client: [mysql, mariadb-c-client]
opencl: [pocl]
onedal: [intel-oneapi-dal]
pbs: [openpbs, torque]
pil: [py-pillow]
pkgconfig: [pkgconf, pkg-config]
rpc: [libtirpc]
scalapack: [netlib-scalapack, amdscalapack]
sycl: [hipsycl]
szip: [libaec, libszip]
tbb: [intel-tbb]
unwind: [libunwind]
uuid: [util-linux-uuid, libuuid]
xxd: [xxd-standalone, vim]
yacc: [bison, byacc]
ziglang: [zig]
permissions:
read: world
write: user
This sets the default preferences for compilers and for providers of virtual packages. To illustrate how this works, suppose we want to change the preferences to prefer the Clang compiler and to prefer MPICH over OpenMPI. Currently, we prefer GCC and OpenMPI.
$ spack spec hdf5
Input spec
--------------------------------
- hdf5
Concretized
--------------------------------
[+] hdf5@1.14.3%gcc@11.4.0~cxx~fortran~hl~ipo~java~map+mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
[+] ^cmake@3.27.7%gcc@11.4.0~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
[+] ^curl@8.4.0%gcc@11.4.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
[+] ^nghttp2@1.57.0%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^openssl@3.1.3%gcc@11.4.0~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
[+] ^ca-certificates-mozilla@2023-05-30%gcc@11.4.0 build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[+] ^ncurses@6.4%gcc@11.4.0~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^gmake@4.4.1%gcc@11.4.0~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[+] ^openmpi@4.1.6%gcc@11.4.0~atomics~cuda~cxx~cxx_exceptions~gpfs~internal-hwloc~internal-pmix~java~legacylaunchers~lustre~memchecker~openshmem~orterunprefix+romio+rsh~singularity+static+vt+wrapper-rpath build_system=autotools fabrics=none schedulers=none arch=linux-ubuntu22.04-x86_64_v3
[+] ^hwloc@2.9.1%gcc@11.4.0~cairo~cuda~gl~libudev+libxml2~netloc~nvml~oneapi-level-zero~opencl+pci~rocm build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
[+] ^libpciaccess@0.17%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^util-macros@1.19.3%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libxml2@2.10.3%gcc@11.4.0+pic~python+shared build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libiconv@1.17%gcc@11.4.0 build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
[+] ^xz@5.4.1%gcc@11.4.0~pic build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
[+] ^numactl@2.0.14%gcc@11.4.0 build_system=autotools patches=4e1d78c,62fc8a8,ff37630 arch=linux-ubuntu22.04-x86_64_v3
[+] ^autoconf@2.69%gcc@11.4.0 build_system=autotools patches=35c4492,7793209,a49dd5b arch=linux-ubuntu22.04-x86_64_v3
[+] ^automake@1.16.5%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libtool@2.4.7%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^m4@1.4.19%gcc@11.4.0+sigsegv build_system=autotools patches=9dc5fbd,bfdffa7 arch=linux-ubuntu22.04-x86_64_v3
[+] ^diffutils@3.9%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libsigsegv@2.14%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^openssh@9.5p1%gcc@11.4.0+gssapi build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^krb5@1.20.1%gcc@11.4.0+shared build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^bison@3.8.2%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^findutils@4.9.0%gcc@11.4.0 build_system=autotools patches=440b954 arch=linux-ubuntu22.04-x86_64_v3
[+] ^gettext@0.22.3%gcc@11.4.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^tar@1.34%gcc@11.4.0 build_system=autotools zip=pigz arch=linux-ubuntu22.04-x86_64_v3
[+] ^pigz@2.7%gcc@11.4.0 build_system=makefile arch=linux-ubuntu22.04-x86_64_v3
[+] ^zstd@1.5.5%gcc@11.4.0+programs build_system=makefile compression=none libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
[+] ^libedit@3.1-20210216%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libxcrypt@4.4.35%gcc@11.4.0~obsolete_api build_system=autotools patches=4885da3 arch=linux-ubuntu22.04-x86_64_v3
[+] ^perl@5.38.0%gcc@11.4.0+cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-ubuntu22.04-x86_64_v3
[+] ^berkeley-db@18.1.40%gcc@11.4.0+cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-ubuntu22.04-x86_64_v3
[+] ^bzip2@1.0.8%gcc@11.4.0~debug~pic+shared build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[+] ^gdbm@1.23%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^readline@8.2%gcc@11.4.0 build_system=autotools patches=bbf97f1 arch=linux-ubuntu22.04-x86_64_v3
[+] ^pmix@5.0.1%gcc@11.4.0~docs+pmi_backwards_compatibility~python~restful build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^libevent@2.1.12%gcc@11.4.0+openssl build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^pkgconf@1.9.5%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^zlib-ng@2.1.4%gcc@11.4.0+compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
Let’s override these default preferences in an environment. When you
have an activated environment, you can edit the associated
configuration with spack config edit
(you don’t have to provide
a section name):
$ spack env create config-env
$ spack env activate config-env
$ spack config edit
Warning
You will get exactly the same effects if you make these changes
without using an environment, but you must delete the
associated packages.yaml
file after the config tutorial or
the commands you run in later tutorial sections will not
produce the same output (because they weren’t run with the
configuration changes made here)
spack:
specs: []
view: true
packages:
all:
compiler: [clang, gcc, intel, pgi, xl, nag, fj]
providers:
mpi: [mpich, openmpi]
Because of the configuration scoping we discussed earlier, this overrides the default settings just for these two items.
$ spack spec hdf5
Input spec
--------------------------------
- hdf5
Concretized
--------------------------------
- hdf5@1.14.3%clang@14.0.0-gfortran cppflags="-g" ~cxx~fortran~hl~ipo~java~map+mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%clang@14.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%clang@14.0.0-gfortran cppflags="-g" ~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
- ^nghttp2@1.57.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%clang@14.0.0-gfortran cppflags="-g" ~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
- ^ca-certificates-mozilla@2023-05-30%clang@14.0.0-gfortran cppflags="-g" build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^perl@5.38.0%clang@14.0.0-gfortran cppflags="-g" +cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-ubuntu22.04-x86_64_v3
- ^berkeley-db@18.1.40%clang@14.0.0-gfortran cppflags="-g" +cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-ubuntu22.04-x86_64_v3
- ^ncurses@6.4%clang@14.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gmake@4.4.1%clang@14.0.0-gfortran cppflags="-g" ~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^mpich@4.1.2%clang@14.0.0-gfortran cppflags="-g" ~argobots~cuda+fortran+hwloc+hydra+libxml2+pci~rocm+romio~slurm~vci~verbs+wrapperrpath build_system=autotools datatype-engine=auto device=ch4 netmod=ofi pmi=pmi arch=linux-ubuntu22.04-x86_64_v3
- ^findutils@4.9.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=440b954 arch=linux-ubuntu22.04-x86_64_v3
- ^hwloc@2.9.1%clang@14.0.0-gfortran cppflags="-g" ~cairo~cuda~gl~libudev+libxml2~netloc~nvml~oneapi-level-zero~opencl+pci~rocm build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^libfabric@1.19.0%clang@14.0.0-gfortran cppflags="-g" ~debug~kdreg build_system=autotools fabrics=sockets,tcp,udp arch=linux-ubuntu22.04-x86_64_v3
- ^libpciaccess@0.17%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libtool@2.4.7%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^util-macros@1.19.3%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libxml2@2.10.3%clang@14.0.0-gfortran cppflags="-g" +pic~python+shared build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libiconv@1.17%clang@14.0.0-gfortran cppflags="-g" build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^xz@5.4.1%clang@14.0.0-gfortran cppflags="-g" ~pic build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^yaksa@0.3%clang@14.0.0-gfortran cppflags="-g" ~cuda~rocm build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^autoconf@2.69%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=35c4492,7793209,a49dd5b arch=linux-ubuntu22.04-x86_64_v3
- ^automake@1.16.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^m4@1.4.19%clang@14.0.0-gfortran cppflags="-g" +sigsegv build_system=autotools patches=9dc5fbd,bfdffa7 arch=linux-ubuntu22.04-x86_64_v3
- ^diffutils@3.9%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libsigsegv@2.14%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^python@3.11.6%clang@14.0.0-gfortran cppflags="-g" +bz2+crypt+ctypes+dbm~debug+libxml2+lzma~nis~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~tkinter+uuid+zlib build_system=generic patches=13fa8bf,b0615b2,ebdca64,f2fd060 arch=linux-ubuntu22.04-x86_64_v3
- ^bzip2@1.0.8%clang@14.0.0-gfortran cppflags="-g" ~debug~pic+shared build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^expat@2.5.0%clang@14.0.0-gfortran cppflags="-g" +libbsd build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libbsd@0.11.7%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libmd@1.0.4%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gdbm@1.23%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gettext@0.22.3%clang@14.0.0-gfortran cppflags="-g" +bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^tar@1.34%clang@14.0.0-gfortran cppflags="-g" build_system=autotools zip=pigz arch=linux-ubuntu22.04-x86_64_v3
- ^pigz@2.7%clang@14.0.0-gfortran cppflags="-g" build_system=makefile arch=linux-ubuntu22.04-x86_64_v3
- ^zstd@1.5.5%clang@14.0.0-gfortran cppflags="-g" +programs build_system=makefile compression=none libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^libffi@3.4.4%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libxcrypt@4.4.35%clang@14.0.0-gfortran cppflags="-g" ~obsolete_api build_system=autotools patches=4885da3 arch=linux-ubuntu22.04-x86_64_v3
- ^readline@8.2%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=bbf97f1 arch=linux-ubuntu22.04-x86_64_v3
- ^sqlite@3.43.2%clang@14.0.0-gfortran cppflags="-g" +column_metadata+dynamic_extensions+fts~functions+rtree build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^util-linux-uuid@2.38.1%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^pkgconf@1.9.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^zlib-ng@2.1.4%clang@14.0.0-gfortran cppflags="-g" +compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
Variant preferences
As we’ve seen throughout this tutorial, HDF5 builds with MPI enabled by
default in Spack. If we were working on a project that would routinely
need serial HDF5, that might get annoying quickly, having to type
hdf5~mpi
all the time. Instead, we’ll update our preferences for
HDF5.
spack:
specs: []
view: true
packages:
all:
compiler: [clang, gcc, intel, pgi, xl, nag, fj]
providers:
mpi: [mpich, openmpi]
hdf5:
require: ~mpi
Now hdf5 will concretize without an MPI dependency by default.
$ spack spec hdf5
Input spec
--------------------------------
- hdf5
Concretized
--------------------------------
- hdf5@1.14.3%clang@14.0.0-gfortran cppflags="-g" ~cxx~fortran~hl~ipo~java~map~mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%clang@14.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%clang@14.0.0-gfortran cppflags="-g" ~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
- ^nghttp2@1.57.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%clang@14.0.0-gfortran cppflags="-g" ~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
- ^ca-certificates-mozilla@2023-05-30%clang@14.0.0-gfortran cppflags="-g" build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^perl@5.38.0%clang@14.0.0-gfortran cppflags="-g" +cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-ubuntu22.04-x86_64_v3
- ^berkeley-db@18.1.40%clang@14.0.0-gfortran cppflags="-g" +cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-ubuntu22.04-x86_64_v3
- ^bzip2@1.0.8%clang@14.0.0-gfortran cppflags="-g" ~debug~pic+shared build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^diffutils@3.9%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libiconv@1.17%clang@14.0.0-gfortran cppflags="-g" build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^gdbm@1.23%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^readline@8.2%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=bbf97f1 arch=linux-ubuntu22.04-x86_64_v3
- ^ncurses@6.4%clang@14.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gmake@4.4.1%clang@14.0.0-gfortran cppflags="-g" ~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^pkgconf@1.9.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^zlib-ng@2.1.4%clang@14.0.0-gfortran cppflags="-g" +compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
In general, every attribute that we can set for all packages we can set separately for an individual package.
External packages
The packages configuration file also controls when Spack will build
against an externally installed package. Spack has a
spack external find
command that can automatically discover and
register externally installed packages. This works for many common
build dependencies, but it’s also important to know how to do this
manually for packages that Spack cannot yet detect.
On these systems we have a pre-installed Perl. Let’s tell Spack about this package and where it can be found:
spack:
specs: []
view: true
packages:
all:
compiler: [clang, gcc, intel, pgi, xl, nag, fj]
providers:
mpi: [mpich, openmpi]
hdf5:
require: ~mpi
perl:
externals:
- spec: perl@5.34.0 %gcc@11.4.0
prefix: /usr
Here, we’ve told Spack that Perl 5.34.0 is installed on our system. We’ve also told it the installation prefix where Perl can be found. We don’t know exactly which variants it was built with, but that’s okay.
$ spack spec hdf5
Input spec
--------------------------------
- hdf5
Concretized
--------------------------------
- hdf5@1.14.3%gcc@11.4.0~cxx~fortran~hl~ipo~java~map~mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%gcc@11.4.0~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%gcc@11.4.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
[+] ^nghttp2@1.57.0%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%gcc@11.4.0~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
[+] ^ca-certificates-mozilla@2023-05-30%gcc@11.4.0 build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[e] ^perl@5.34.0%gcc@11.4.0~cpanm+opcode+open+shared+threads build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[+] ^ncurses@6.4%gcc@11.4.0~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^gmake@4.4.1%gcc@11.4.0~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[+] ^pkgconf@1.9.5%gcc@11.4.0 build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
[+] ^zlib-ng@2.1.4%gcc@11.4.0+compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
You’ll notice that Spack is now using the external Perl installation, but the compiler used to build Perl is now overriding our compiler preference of clang. If we explicitly specify Clang:
$ spack spec hdf5%clang
Input spec
--------------------------------
- hdf5%clang
Concretized
--------------------------------
- hdf5@1.14.3%clang@14.0.0-gfortran cppflags="-g" ~cxx~fortran~hl~ipo~java~map~mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%clang@14.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%clang@14.0.0-gfortran cppflags="-g" ~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
- ^nghttp2@1.57.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%clang@14.0.0-gfortran cppflags="-g" ~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
- ^ca-certificates-mozilla@2023-05-30%clang@14.0.0-gfortran cppflags="-g" build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^perl@5.38.0%clang@14.0.0-gfortran cppflags="-g" +cpanm+opcode+open+shared+threads build_system=generic patches=714e4d1 arch=linux-ubuntu22.04-x86_64_v3
- ^berkeley-db@18.1.40%clang@14.0.0-gfortran cppflags="-g" +cxx~docs+stl build_system=autotools patches=26090f4,b231fcc arch=linux-ubuntu22.04-x86_64_v3
- ^bzip2@1.0.8%clang@14.0.0-gfortran cppflags="-g" ~debug~pic+shared build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^diffutils@3.9%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^libiconv@1.17%clang@14.0.0-gfortran cppflags="-g" build_system=autotools libs=shared,static arch=linux-ubuntu22.04-x86_64_v3
- ^gdbm@1.23%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^readline@8.2%clang@14.0.0-gfortran cppflags="-g" build_system=autotools patches=bbf97f1 arch=linux-ubuntu22.04-x86_64_v3
- ^ncurses@6.4%clang@14.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gmake@4.4.1%clang@14.0.0-gfortran cppflags="-g" ~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^pkgconf@1.9.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^zlib-ng@2.1.4%clang@14.0.0-gfortran cppflags="-g" +compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
Spack concretizes to both HDF5 and Perl being built with Clang. This has a side-effect of rebuilding Perl. If we want to force Spack to use the system Perl, we have two choices. We can either specify it on the command line, or we can tell Spack that it’s not allowed to build its own Perl. We’ll go with the latter.
spack:
specs: []
view: true
packages:
all:
compiler: [clang, gcc, intel, pgi, xl, nag, fj]
providers:
mpi: [mpich, openmpi]
hdf5:
require: ~mpi
perl:
externals:
- spec: perl@5.34.0 %gcc@11.4.0
prefix: /usr
buildable: false
Now Spack will be forced to choose the external Perl.
$ spack spec hdf5%clang
Input spec
--------------------------------
- hdf5%clang
Concretized
--------------------------------
- hdf5@1.14.3%clang@14.0.0-gfortran cppflags="-g" ~cxx~fortran~hl~ipo~java~map~mpi+shared~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make arch=linux-ubuntu22.04-x86_64_v3
- ^cmake@3.27.7%clang@14.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs build_system=generic build_type=Release arch=linux-ubuntu22.04-x86_64_v3
- ^curl@8.4.0%clang@14.0.0-gfortran cppflags="-g" ~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs=shared,static tls=openssl arch=linux-ubuntu22.04-x86_64_v3
- ^nghttp2@1.57.0%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^openssl@3.1.3%clang@14.0.0-gfortran cppflags="-g" ~docs+shared build_system=generic certs=mozilla arch=linux-ubuntu22.04-x86_64_v3
- ^ca-certificates-mozilla@2023-05-30%clang@14.0.0-gfortran cppflags="-g" build_system=generic arch=linux-ubuntu22.04-x86_64_v3
[e] ^perl@5.34.0%gcc@11.4.0~cpanm+opcode+open+shared+threads build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^ncurses@6.4%clang@14.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^gmake@4.4.1%clang@14.0.0-gfortran cppflags="-g" ~guile build_system=generic arch=linux-ubuntu22.04-x86_64_v3
- ^pkgconf@1.9.5%clang@14.0.0-gfortran cppflags="-g" build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
- ^zlib-ng@2.1.4%clang@14.0.0-gfortran cppflags="-g" +compat+opt build_system=autotools arch=linux-ubuntu22.04-x86_64_v3
This gets slightly more complicated with virtual dependencies. Suppose we don’t want to build our own MPI, but we now want a parallel version of HDF5. Well, fortunately we have MPICH installed on these systems.
Instead of manually configuring an external for MPICH like we did for
perl
we will use the spack external find
command. For packages
that support this option, this is a useful way to avoid typos and get
more accurate external specs.
$ spack external find mpich
==> The following specs have been detected on this system and added to /home/spack1/spack/var/spack/environments/config-env/spack.yaml
mpich@4.0
To express that we don’t want any other MPI installed we can use the
virtual mpi
package as a key. While we’re editing the
spack.yaml
file, make sure to configure HDF5 to be able to build
with MPI again:
spack:
specs: []
view: true
packages:
all:
compiler: [clang, gcc, intel, pgi, xl, nag, fj]
providers:
mpi: [mpich, openmpi]
perl:
externals:
- spec: perl@5.34.0 %gcc@11.4.0
prefix: /usr
buildable: false
mpich:
externals:
- spec: mpich@4.0+hydra device=ch4 netmod=ofi
prefix: /usr
mpi:
buildable: false
Now that we have configured Spack not to build any possible provider for MPI, we can try again.
$ spack spec hdf5 %clang
Input spec
--------------------------------
hdf5%clang
Concretized
--------------------------------
hdf5@1.12.2%clang@7.0.0-gfortran cppflags="-g" ~cxx~fortran~hl~ipo~java+mpi+shared~szip~threadsafe+tools api=default build_type=RelWithDebInfo arch=linux-ubuntu18.04-x86_64
^cmake@3.23.1%clang@7.0.0-gfortran cppflags="-g" ~doc+ncurses+ownlibs~qt build_type=Release arch=linux-ubuntu18.04-x86_64
^ncurses@6.2%clang@7.0.0-gfortran cppflags="-g" ~symlinks+termlib abi=none arch=linux-ubuntu18.04-x86_64
^pkgconf@1.8.0%clang@7.0.0-gfortran cppflags="-g" arch=linux-ubuntu18.04-x86_64
^openssl@1.1.1o%clang@7.0.0-gfortran cppflags="-g" ~docs~shared certs=system arch=linux-ubuntu18.04-x86_64
^perl@5.26.1%gcc@7.5.0+cpanm+shared+threads patches=0eac10e,8cf4302 arch=linux-ubuntu18.04-x86_64
^zlib@1.2.12%clang@7.0.0-gfortran cppflags="-g" +optimize+pic+shared patches=0d38234 arch=linux-ubuntu18.04-x86_64
^mpich@3.3%gcc@7.5.0~argobots~cuda+fortran+hwloc+hydra+libxml2+pci~rocm+romio~slurm~two_level_namespace~verbs+wrapperrpath device=ch4 netmod=ofi patches=5f48d2d,d2dafc0 pmi=pmi arch=linux-ubuntu18.04-x86_64
Notice that we still haven’t build hdf5
with our external
mpich
. The concretizer has instead turned off mpi
support in
hdf5
. To debug this, we will force Spack to use hdf5+mpi
.
$ spack spec hdf5%clang+mpi
==> Error: concretization failed for the following reasons:
1. hdf5: '+mpi' conflicts with '^mpich@4.0:4.0.3'
2. hdf5: '+mpi' conflicts with '^mpich@4.0:4.0.3'
required because conflict applies to spec ^mpich@4.0:4.0.3
required because hdf5%clang+mpi requested from CLI
required because conflict is triggered when +mpi
required because hdf5%clang+mpi requested from CLI
In this case, we cannot use the external mpich. The version is
incompatible with hdf5
. At this point, the best option is to give
up and let Spack build mpi
for us. The alternative is to try to
find a version of hdf5
which doesn’t have this conflict.
By configuring most of our package preferences in packages.yaml
,
we can cut down on the amount of work we need to do when specifying
a spec on the command line. In addition to compiler and variant
preferences, we can specify version preferences as well. Except for
specifying dependencies via ^
, anything that you can specify on the
command line can be specified in packages.yaml
with the exact
same spec syntax.
Installation permissions
The packages
configuration also controls the default permissions
to use when installing a package. You’ll notice that by default,
the installation prefix will be world-readable but only user-writable.
Let’s say we need to install converge
, a licensed software package.
Since a specific research group, fluid_dynamics
, pays for this
license, we want to ensure that only members of this group can access
the software. We can do this like so:
packages:
converge:
permissions:
read: group
group: fluid_dynamics
Now, only members of the fluid_dynamics
group can use any
converge
installations.
At this point we want to discard the configuration changes we made in this tutorial section, so we can deactivate the environment:
$ spack env deactivate
Warning
If you do not deactivate the config-env
environment, then
specs will be concretized differently in later tutorial sections
and your results will not match.
High-level Config
In addition to compiler and package settings, Spack allows customization
of several high-level settings. These settings are managed in the config
section (in config.yaml
when stored as an individual file outside of
an environment). You can see the default settings by running:
$ spack config --scope defaults edit config
# -------------------------------------------------------------------------
# This is the default spack configuration file.
#
# Settings here are versioned with Spack and are intended to provide
# sensible defaults out of the box. Spack maintainers should edit this
# file to keep it current.
#
# Users can override these settings by editing the following files.
#
# Per-spack-instance settings (overrides defaults):
# $SPACK_ROOT/etc/spack/config.yaml
#
# Per-user settings (overrides default and site settings):
# ~/.spack/config.yaml
# -------------------------------------------------------------------------
config:
# This is the path to the root of the Spack install tree.
# You can use $spack here to refer to the root of the spack instance.
install_tree:
root: $spack/opt/spack
projections:
all: "${ARCHITECTURE}/${COMPILERNAME}-${COMPILERVER}/${PACKAGE}-${VERSION}-${HASH}"
# install_tree can include an optional padded length (int or boolean)
# default is False (do not pad)
# if padded_length is True, Spack will pad as close to the system max path
# length as possible
# if padded_length is an integer, Spack will pad to that many characters,
# assuming it is higher than the length of the install_tree root.
# padded_length: 128
# Locations where templates should be found
template_dirs:
- $spack/share/spack/templates
# Directory where licenses should be located
license_dir: $spack/etc/spack/licenses
# Temporary locations Spack can try to use for builds.
#
# Recommended options are given below.
#
# Builds can be faster in temporary directories on some (e.g., HPC) systems.
# Specifying `$tempdir` will ensure use of the default temporary directory
# (i.e., ``$TMP` or ``$TMPDIR``).
#
# Another option that prevents conflicts and potential permission issues is
# to specify `$user_cache_path/stage`, which ensures each user builds in their
# home directory.
#
# A more traditional path uses the value of `$spack/var/spack/stage`, which
# builds directly inside Spack's instance without staging them in a
# temporary space. Problems with specifying a path inside a Spack instance
# are that it precludes its use as a system package and its ability to be
# pip installable.
#
# In any case, if the username is not already in the path, Spack will append
# the value of `$user` in an attempt to avoid potential conflicts between
# users in shared temporary spaces.
#
# The build stage can be purged with `spack clean --stage` and
# `spack clean -a`, so it is important that the specified directory uniquely
# identifies Spack staging to avoid accidentally wiping out non-Spack work.
build_stage:
- $tempdir/$user/spack-stage
- $user_cache_path/stage
# - $spack/var/spack/stage
# Directory in which to run tests and store test results.
# Tests will be stored in directories named by date/time and package
# name/hash.
test_stage: $user_cache_path/test
# Cache directory for already downloaded source tarballs and archived
# repositories. This can be purged with `spack clean --downloads`.
source_cache: $spack/var/spack/cache
# Cache directory for miscellaneous files, like the package index.
# This can be purged with `spack clean --misc-cache`
misc_cache: $user_cache_path/cache
# Timeout in seconds used for downloading sources etc. This only applies
# to the connection phase and can be increased for slow connections or
# servers. 0 means no timeout.
connect_timeout: 10
# If this is false, tools like curl that use SSL will not verify
# certifiates. (e.g., curl will use use the -k option)
verify_ssl: true
# Suppress gpg warnings from binary package verification
# Only suppresses warnings, gpg failure will still fail the install
# Potential rationale to set True: users have already explicitly trusted the
# gpg key they are using, and may not want to see repeated warnings that it
# is self-signed or something of the sort.
suppress_gpg_warnings: false
# If set to true, Spack will attempt to build any compiler on the spec
# that is not already available. If set to False, Spack will only use
# compilers already configured in compilers.yaml
install_missing_compilers: false
# If set to true, Spack will always check checksums after downloading
# archives. If false, Spack skips the checksum step.
checksum: true
# If set to true, Spack will fetch deprecated versions without warning.
# If false, Spack will raise an error when trying to install a deprecated version.
deprecated: false
# If set to true, `spack install` and friends will NOT clean
# potentially harmful variables from the build environment. Use wisely.
dirty: false
# The language the build environment will use. This will produce English
# compiler messages by default, so the log parser can highlight errors.
# If set to C, it will use English (see man locale).
# If set to the empty string (''), it will use the language from the
# user's environment.
build_language: C
# When set to true, concurrent instances of Spack will use locks to
# avoid modifying the install tree, database file, etc. If false, Spack
# will disable all locking, but you must NOT run concurrent instances
# of Spack. For filesystems that don't support locking, you should set
# this to false and run one Spack at a time, but otherwise we recommend
# enabling locks.
locks: true
# The default url fetch method to use.
# If set to 'curl', Spack will require curl on the user's system
# If set to 'urllib', Spack will use python built-in libs to fetch
url_fetch_method: urllib
# The maximum number of jobs to use for the build system (e.g. `make`), when
# the -j flag is not given on the command line. Defaults to 16 when not set.
# Note that the maximum number of jobs is limited by the number of cores
# available, taking thread affinity into account when supported. For instance:
# - With `build_jobs: 16` and 4 cores available `spack install` will run `make -j4`
# - With `build_jobs: 16` and 32 cores available `spack install` will run `make -j16`
# - With `build_jobs: 2` and 4 cores available `spack install -j6` will run `make -j6`
# build_jobs: 16
# If set to true, Spack will use ccache to cache C compiles.
ccache: false
# The concretization algorithm to use in Spack. Options are:
#
# 'clingo': Uses a logic solver under the hood to solve DAGs with full
# backtracking and optimization for user preferences. Spack will
# try to bootstrap the logic solver, if not already available.
#
# 'original': Spack's original greedy, fixed-point concretizer. This
# algorithm can make decisions too early and will not backtrack
# sufficiently for many specs. This will soon be deprecated in
# favor of clingo.
#
# See `concretizer.yaml` for more settings you can fine-tune when
# using clingo.
concretizer: clingo
# How long to wait to lock the Spack installation database. This lock is used
# when Spack needs to manage its own package metadata and all operations are
# expected to complete within the default time limit. The timeout should
# therefore generally be left untouched.
db_lock_timeout: 3
# How long to wait when attempting to modify a package (e.g. to install it).
# This value should typically be 'null' (never time out) unless the Spack
# instance only ever has a single user at a time, and only if the user
# anticipates that a significant delay indicates that the lock attempt will
# never succeed.
package_lock_timeout: null
# Control how shared libraries are located at runtime on Linux. See the
# the Spack documentation for details.
shared_linking:
# Spack automatically embeds runtime search paths in ELF binaries for their
# dependencies. Their type can either be "rpath" or "runpath". For glibc, rpath is
# inherited and has precedence over LD_LIBRARY_PATH; runpath is not inherited
# and of lower precedence. DO NOT MIX these within the same install tree.
type: rpath
# (Experimental) Embed absolute paths of dependent libraries directly in ELF
# binaries to avoid runtime search. This can improve startup time of
# executables with many dependencies, in particular on slow filesystems.
bind: false
# Set to 'false' to allow installation on filesystems that doesn't allow setgid bit
# manipulation by unprivileged user (e.g. AFS)
allow_sgid: true
# Whether to set the terminal title to display status information during
# building and installing packages. This gives information about Spack's
# current progress as well as the current and total number of packages.
terminal_title: false
# Number of seconds a buildcache's index.json is cached locally before probing
# for updates, within a single Spack invocation. Defaults to 10 minutes.
binary_index_ttl: 600
As you can see, many of the directories Spack uses can be customized.
For example, you can tell Spack to install packages to a prefix
outside of the $SPACK_ROOT
hierarchy. Module files can be
written to a central location if you are using multiple Spack
instances. If you have a fast scratch file system, you can run builds
from this file system with the following config.yaml
:
config:
build_stage:
- /scratch/$user/spack-stage
Note
It is important to distinguish the build stage directory from other
directories in your scratch space to ensure spack clean
does not
inadvertently remove unrelated files. This can be accomplished by
including a combination of spack
and or stage
in each path
as shown in the default settings and documented examples. See
Basic Settings for details.
On systems with compilers that absolutely require environment variables
like LD_LIBRARY_PATH
, it is possible to prevent Spack from cleaning
the build environment with the dirty
setting:
config:
dirty: true
However, this is strongly discouraged, as it can pull unwanted libraries into the build.
One last setting that may be of interest to many users is the ability to customize the parallelism of Spack builds. By default, Spack installs all packages in parallel with the number of jobs equal to the number of cores on the node (up to a maximum of 16). For example, on a node with 16 cores, this will look like:
$ spack install --no-cache --verbose --overwrite --yes-to-all zlib
==> Installing zlib
==> Executing phase: 'install'
==> './configure' '--prefix=/home/user/spack/opt/spack/linux-ubuntu22.04-x86_64/gcc-11.3.0/zlib-1.2.12-fntvsj6xevbz5gyq7kfa4xg7oxnaolxs'
...
==> 'make' '-j16'
...
==> 'make' '-j16' 'install'
...
[+] /home/user/spack/opt/spack/linux-ubuntu22.04-x86_64/gcc-11.3.0/zlib-1.2.12-fntvsj6xevbz5gyq7kfa4xg7oxnaolxs
As you can see, we are building with all 16 cores on the node. If you are
on a shared login node, this can slow down the system for other users. If
you have a strict ulimit or restriction on the number of available licenses,
you may not be able to build at all with this many cores. To limit the
number of cores our build uses, set build_jobs
like so:
$ spack config edit config
config:
build_jobs: 2
If we uninstall and reinstall zlib-ng, we see that it now uses only 2 cores:
$ spack install --no-cache --verbose --overwrite --yes-to-all zlib-ng
==> Installing zlib
==> Executing phase: 'install'
==> './configure' '--prefix=/home/user/spack/opt/spack/linux-ubuntu22.04...
...
==> 'make' '-j2'
...
==> 'make' '-j2' 'install'
...
[+] /home/user/spack/opt/spack/linux-ubuntu22.04...
Obviously, if you want to build everything in serial for whatever reason,
you would set build_jobs
to 1.
Last we’ll unset concretizer:reuse:false
since we’ll want to
enable concretizer reuse for the rest of this tutorial.
$ spack config rm concretizer:reuse
Warning
If you do not do this step, the rest of the tutorial will not reuse binaries!
Conclusion
In this tutorial, we covered basic Spack configuration using compilers.yaml
,
packages.yaml
, and config.yaml
. Spack has many more configuration files,
including modules.yaml
, which will be covered in the Module Files Tutorial.
For more detailed documentation on Spack’s many configuration settings, see
the configuration section
of Spack’s main documentation.
For examples of how other sites configure Spack, see https://github.com/spack/spack-configs. If you use Spack at your site and want to share your config files, feel free to submit a pull request!