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:isc26

and then set Spack up like this:

git clone --depth=2 --branch=releases/v1.2 https://github.com/spack/spack
. spack/share/spack/setup-env.sh
spack mirror add --unsigned tutorial /mirror
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

Environments Tutorial

So far in this tutorial, we’ve covered the basic commands for managing individual packages:

Now we’ll explore Spack environments, a powerful feature that lets us manage collections of packages together in a documented and reproducible way. Spack environments are similar to virtual environments in other package managers (e.g., Python venv, Conda environments, or nix-env).

Managing a software stack with many packages and varying configuration can quickly become hard to track by hand. An environment lets you:

  • Establish a standard set of requirements for a project,

  • Install and use them together as a unit,

  • Reproduce the same build on another machine, and

  • Document your software stack for collaborators, CI/CD pipelines, and releases.

Each environment is captured in two shareable files: spack.yaml records the requested specs and configuration, while spack.lock captures the fully concrete build for reproducibility. We’ll look at both in detail later in this tutorial.

Working with Environments

Let’s look at the output of spack find at this point in the tutorial.

$ spack find
-- linux-ubuntu26.04-x86_64 / no compilers ----------------------
gcc@15.2.0  glibc@2.43

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
mpich@5.0.1  openblas@0.3.33  openmpi@5.0.10  trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=clang@21.1.8 ------------
zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
binutils@2.46.0	 hwloc@2.13.0  openssh@10.3p1  zlib-ng@2.3.3  zstd@1.5.7
gettext@1.0	 krb5@1.22.2   openssl@3.6.1   zlib-ng@2.3.3
gmp@6.3.0	 ncurses@6.6   zlib-ng@2.0.7   zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8  hdf5@1.14.6	   libiconv@1.18      mpc@1.4.1	      pkgconf@2.5.1  xz@5.8.3
gmake@4.4.1  libedit@3.1-20251016  libpciaccess@0.17  mpfr@4.2.2      pmix@6.1.0
hdf5@1.14.6  libevent@2.1.12	   libxcrypt@4.5.2    numactl@2.0.19  prrte@4.1.0
hdf5@1.14.6  libfabric@2.5.1	   libxml2@2.15.3     pigz@2.8	      tar@1.35

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0	    gcc-runtime@15.2.0	llvm@21.1.8
gcc@14.3.0		gcc-runtime@15.2.0  glibc@2.43
==> 50 installed packages

This is a complete, but cluttered list of all our installed packages and their dependencies. It contains packages built with both openmpi and mpich, as well as multiple variants of other packages, like hdf5 and zlib-ng.

The query mechanism we learned about with spack find can help, but it would be nice if we could see only the software that is relevant to our current project instead of seeing everything on the machine.

Creating and Activating Environments

Let’s create a new environment called myproject using the spack env create command:

$ spack env create myproject
==> Created environment myproject in: /home/spack/spack/var/spack/environments/myproject
==> Activate with: spack env activate myproject

To see all of our environments we’ve created so far we can run spack env list:

$ spack env list
==> 1 environments
    myproject

Now let’s activate our environment by running the spack env activate command or spacktivate alias. The -p flag prepends the environment name to our shell prompt, which is a handy reminder of which environment we are in:

$ spack env activate myproject

Note

For quick experiments you don’t intend to keep, spack env activate --temp creates and activates a fresh, unnamed environment in a temporary directory. We’ll use a regular named environment throughout this tutorial, but --temp is handy when you just want to try something out.

Once we activate an environment, spack find will only show what is in the current environment. For example, because we just created this environment the output below doesn’t show any installed packages.

$ spack find
==> In environment myproject (no root specs)
==> 0 installed packages
==> 0 concretized packages to be installed (show with `spack find -c`)

Although Spack doesn’t show all installed software when in an active environment, it will reuse packages across environments to save disk space and reduce build times. Additionally the output now tells us that we’re in the myproject environment, so there is no need to panic when we no longer see our previously installed packages. It also states that there are no root specs. We’ll get back to what that means later.

While this detailed output is useful, if we only want to check what environment we are in, we can use spack env status:

$ spack env status
==> In environment myproject

To now exit out of this environment, we can use spack env deactivate or despacktivate if we’re feeling fancy.

After deactivating, we can see everything installed in this Spack instance:

$ despacktivate	   # short alias for 'spack env deactivate'
$ spack env status
==> No active environment
$ spack find
-- linux-ubuntu26.04-x86_64 / no compilers ----------------------
gcc@15.2.0  glibc@2.43

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
mpich@5.0.1  openblas@0.3.33  openmpi@5.0.10  trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=clang@21.1.8 ------------
zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
binutils@2.46.0	 hwloc@2.13.0  openssh@10.3p1  zlib-ng@2.3.3  zstd@1.5.7
gettext@1.0	 krb5@1.22.2   openssl@3.6.1   zlib-ng@2.3.3
gmp@6.3.0	 ncurses@6.6   zlib-ng@2.0.7   zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8  hdf5@1.14.6	   libiconv@1.18      mpc@1.4.1	      pkgconf@2.5.1  xz@5.8.3
gmake@4.4.1  libedit@3.1-20251016  libpciaccess@0.17  mpfr@4.2.2      pmix@6.1.0
hdf5@1.14.6  libevent@2.1.12	   libxcrypt@4.5.2    numactl@2.0.19  prrte@4.1.0
hdf5@1.14.6  libfabric@2.5.1	   libxml2@2.15.3     pigz@2.8	      tar@1.35

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0	    gcc-runtime@15.2.0	llvm@21.1.8
gcc@14.3.0		gcc-runtime@15.2.0  glibc@2.43
==> 50 installed packages

Installing Packages

Now that we understand how creation and activation work, let’s go back to our myproject environment and install a couple of packages, specifically tcl and trilinos.

Installing software in an environment follows three steps:

  1. add the specs we want, registering them as root specs of the environment;

  2. concretize the environment, resolving every root and its dependencies into a concrete set; and

  3. install the concretized specs.

We’ll walk through them one at a time.

First, we add our two specs with spack add:

$ spack add tcl
==> Adding tcl to environment myproject
$ spack add trilinos
==> Adding trilinos to environment myproject

tcl and trilinos are now registered as root specs, i.e., the packages we’ve explicitly requested. They’re called “roots” because they sit at the top of the dependency graph, with their dependency packages sitting below them.

If we run spack find now, it lists them as roots but reports nothing concretized yet. Adding a spec only records our intent:

$ spack find
==> In environment myproject (2 root specs)
 -  tcl	  -  trilinos

==> 0 installed packages
==> 0 concretized packages to be installed (show with `spack find -c`)

Next, we concretize the environment, resolving those roots and all their dependencies into a concrete set:

$ spack concretize
==> Concretized 2 specs:
[b]  d4ibosb  tcl@8.6.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  mmywg7x	  ^compiler-wrapper@1.1.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yjlog5x	  ^gcc@15.2.0+binutils+bootstrap~graphite+libsanitizer~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  xm76mt3	  ^gcc-runtime@15.2.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yc4n2pp	  ^glibc@2.43 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  r4lhaok	  ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  g72d7i3	  ^zlib-ng@2.3.3+compat+new_strategies+opt+pic+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  u43pchx  trilinos@17.1.1~adelus~adios2+amesos2+anasazi~basker+belos~boost~chaco~complex~cuda~cuda_constexpr~cuda_rdc~cusparse~debug~dtk~exodus+explicit_template_instantiation~float+fortran~gtest~hdf5~hypre+ifpack2~intrepid2~ipo+kokkos~mesquite~minitensor+mpi+muelu~mumps~nox~openmp~pamgen~panzer~phalanx~piro~python~rocm~rocm_rdc~rol+sacado~scorec~shards+shared~shylu~stk~stokhos~stratimikos~strumpack~suite-sparse~superlu-dist~teko~tempus~test~thyra+tpetra~trilinoscouplings~wrapper~x11~zoltan~zoltan2 build_system=cmake build_type=Release cxxstd=20 generator=make gotype=long_long platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  a4wqsr7	  ^cmake@3.31.11~doc+ncurses+ownlibs~qtgui build_system=generic build_type=Release platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  j2fa7xl	      ^curl@8.20.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs:=shared,static tls:=openssl platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  4lyasaz		  ^nghttp2@1.67.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  ao2onuz		      ^diffutils@3.12 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  33yozp5		  ^openssl@3.6.1~docs+shared build_system=generic certs=mozilla platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  axeuqg3		      ^ca-certificates-mozilla@2026-03-19 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  ekvivpv	      ^ncurses@6.6~symlinks+termlib abi=none build_system=autotools patches:=7a351bc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  ujctyey	  ^hwloc@2.13.0~cairo~cuda~gl~level_zero~libudev+libxml2~nvml~opencl+pci~rocm build_system=autotools libs:=shared,static patches:=b4db98b platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  qzkk5ym	      ^libpciaccess@0.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  o5fy6wf		  ^util-macros@1.20.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  ujlg2ua	      ^libxml2@2.15.3+pic~python+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  vbwvgwx		  ^libiconv@1.18 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  hhjyyqy		  ^xz@5.8.3~pic build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  yvl6jpi	      ^pkgconf@2.5.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  kpwomw3	  ^kokkos@5.1.1~aggressive_vectorization~cmake_lang~complex_align~cuda~debug~debug_bounds_check+deprecated_code~hip_relocatable_device_code~hpx~hwloc~ipo~openmp+pic~rocm+serial+shared~sycl~tests~threads~tuning~wrapper build_system=cmake build_type=Release cxxstd=20 generator=make intel_gpu_arch=none platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  5zilkuz	  ^kokkos-kernels@5.1.1~blas~cblas~cublas~cuda~cusolver~cusparse~execspace_cuda~execspace_openmp~execspace_serial~execspace_threads~ipo~lapack~lapacke~memspace_cudaspace~memspace_cudauvmspace~mkl~openmp~rocblas~rocsolver~rocsparse~serial+shared~superlu~threads build_system=cmake build_type=Release generator=make layouts=left offsets:=int,size_t ordinals:=int scalars:=double platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  7kdghmr	  ^openblas@0.3.33~bignuma~consistent_fpcsr+dynamic_dispatch+fortran~ilp64+locking+pic+shared~static build_system=makefile patches:=723ddc1 symbol_suffix=none threads=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[+]  qfut5qq	  ^openmpi@5.0.10+atomics~cuda~debug+fortran~gpfs~internal-hwloc~internal-libevent~internal-pmix~ipv6~java~lustre~memchecker~openshmem~rocm~romio+rsh~static~two_level_namespace+vt+wrapper-rpath build_system=autotools fabrics:=none patches:=646eb1a romio-filesystem:=none schedulers:=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  jo3eg4r	      ^autoconf@2.72 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  y6uqrto		  ^m4@1.4.21+sigsegv build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  phcmfqk		      ^libsigsegv@2.15 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  yhkgfai	      ^automake@1.18.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  oopqoag	      ^libevent@2.1.12+openssl build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  3gdq456	      ^libtool@2.5.4 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  mguwetc		  ^file@5.46+static build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  63aruxk		      ^zstd@1.5.7+programs build_system=makefile compression:=none libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  punbqrx		  ^findutils@4.10.0 build_system=autotools patches:=440b954 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  sle3ix4		      ^gettext@1.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  f5xe4px			  ^tar@1.35 build_system=autotools zip=pigz platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  afklka7			      ^pigz@2.8 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  2t2useu	      ^numactl@2.0.19 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  m6yx5j3	      ^openssh@10.3p1+gssapi build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  ldqeqfw		  ^krb5@1.22.2+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  lbkegpi		      ^bison@3.8.2~color build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  uwyh3xy		  ^libedit@3.1-20251016 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  bkzcu2s		  ^libxcrypt@4.5.2~obsolete_api build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  bvphs3b	      ^perl@5.42.0+cpanm+opcode+open+shared+threads build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  27d4iyp		  ^berkeley-db@18.1.40+cxx~docs+stl build_system=autotools patches:=26090f4,b231fcc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  cbtgjrh		  ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  cq4dkuc		  ^gdbm@1.26 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  k25xiih		      ^readline@8.3 build_system=autotools patches:=21f0a03,72dee13,e273643 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  ohmdb2l		  ^less@692 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ycyqykw	      ^pmix@6.1.0~munge~python build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  nldxmxw	      ^prrte@4.1.0 build_system=autotools patches:=64faa1a,91b28f5 schedulers:=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  vwo3ajm		  ^flex@2.6.3+lex~nls build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0

==> Updating view at /home/spack/spack/var/spack/environments/myproject/.spack-env/view

The spack find above hinted at this with show with spack find -c. Now that the environment is concretized, that command lists the concrete set, including the packages still to be installed:

$ spack find -c
==> In environment myproject (2 root specs)
[b] tcl	 [b] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
[+]  openblas@0.3.33  [+]  openmpi@5.0.10  [b]	trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
[b]  berkeley-db@18.1.40  [b]  flex@2.6.3    [b]  m4@1.4.21	  [+]  openssl@3.6.1
[b]  bison@3.8.2	  [+]  gettext@1.0   [+]  ncurses@6.6	  [b]  tcl@8.6.17
[b]  cmake@3.31.11	  [+]  hwloc@2.13.0  [b]  nghttp2@1.67.1  [+]  zlib-ng@2.3.3
[b]  curl@8.20.0	  [+]  krb5@1.22.2   [+]  openssh@10.3p1  [+]  zstd@1.5.7

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
[b]  automake@1.18.1   [b]  less@692		  [+]  libxcrypt@4.5.2	[+]  prrte@4.1.0
[+]  bzip2@1.0.8       [+]  libedit@3.1-20251016  [+]  libxml2@2.15.3	[b]  readline@8.3
[b]  diffutils@3.12    [+]  libevent@2.1.12	  [+]  numactl@2.0.19	[+]  tar@1.35
[b]  file@5.46	       [+]  libiconv@1.18	  [b]  perl@5.42.0	[+]  xz@5.8.3
[b]  findutils@4.10.0  [+]  libpciaccess@0.17	  [+]  pigz@2.8
[b]  gdbm@1.26	       [b]  libsigsegv@2.15	  [+]  pkgconf@2.5.1
[b]  gmake@4.4.1       [b]  libtool@2.5.4	  [+]  pmix@6.1.0

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
[+]  kokkos@5.1.1  [+]	kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
[b]  autoconf@2.72			 [e]  gcc@15.2.0	  [b]  util-macros@1.20.2
[b]  ca-certificates-mozilla@2026-03-19	 [+]  gcc-runtime@15.2.0
[+]  compiler-wrapper@1.1.0		 [e]  glibc@2.43
==> 30 installed packages
==> 23 concretized packages to be installed

Finally, we install:

$ spack install
[ ] u43pchx trilinos@17.1.1 fetching from build cache (0s)
[ ] d4ibosb tcl@8.6.17 fetching from build cache (0s)
[ ] d4ibosb tcl@8.6.17 relocating (0s)
[ ] u43pchx trilinos@17.1.1 relocating (0s)
[+] d4ibosb tcl@8.6.17 /home/spack/spack/opt/spack/linux-x86_64_v3/tcl-8.6.17-d4ibosbgfm7536ij2dmdu6nnll5g5zpm (0s)
[+] u43pchx trilinos@17.1.1 /home/spack/spack/opt/spack/linux-x86_64_v3/trilinos-17.1.1-u43pchxcfkd7syptwimxl4lozm5jmy2h (1s)
==> Updating view at /home/spack/spack/var/spack/environments/myproject/.spack-env/view

We can see that Spack reused existing installations of tcl and the dependencies of trilinos that were already present on the system, rather than rebuilding them from scratch. Additionally, the environment’s view was automatically updated to include the installations. This means all the software in this environment has been added to our PATH, making the installed packages readily accessible from the command line while we have the environment activated.

Let’s confirm the contents of the environment using spack find:

$ spack find
==> In environment myproject (2 root specs)
[+] tcl	 [+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
gettext@1.0   krb5@1.22.2  openssh@10.3p1  tcl@8.6.17	  zstd@1.5.7
hwloc@2.13.0  ncurses@6.6  openssl@3.6.1   zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libiconv@1.18	 libxml2@2.15.3	 pkgconf@2.5.1	tar@1.35
libedit@3.1-20251016  libpciaccess@0.17	 numactl@2.0.19	 pmix@6.1.0	xz@5.8.3
libevent@2.1.12	      libxcrypt@4.5.2	 pigz@2.8	 prrte@4.1.0

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43
==> 32 installed packages
==> 21 concretized packages to be installed (show with `spack find -c`)

We can see that the roots and their dependencies have been installed. The packages reported as concretized packages to be installed are build-only dependencies, which Spack skips when it installs from binaries.

Note

We walked through the three steps separately, but in practice spack install concretizes for you, so spack add followed by spack install is all you need. You must still add a spec before installing it, which prevents you from accidentally changing a shared environment. Adding all specs before installing also lets Spack concretize them together, so they share dependencies and can all build in parallel.

Using installed packages

Activating an environment adds all of its installed software to our shell search paths through a feature called environment views. A view is a directory tree of symlinks to all installed packages, structured like a standard Linux filesystem (bin/, lib/, include/, …).

For example, tcl ships a shell called tclsh. Activating myproject puts it on our PATH:

$ which tclsh
/home/spack/spack/var/spack/environments/myproject/.spack-env/view/bin/tclsh

Notice the path includes the environment name and a view subdirectory. With openmpi installed in myproject as a dependency of trilinos, mpicc is also on our PATH:

$ spack env activate myproject
$ spack env status
==> In environment myproject
$ which mpicc
/home/spack/spack/var/spack/environments/myproject/.spack-env/view/bin/mpicc

This means we can compile code against the environment’s packages without any manual -I or -L flags. Let’s build a small program that uses both MPI and zlib:

#include <stdio.h>
#include <mpi.h>
#include <zlib.h>

int main(int argc, char **argv) {
  int rank;
  MPI_Init(&argc, &argv);

  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  printf("Hello world from rank %d\n", rank);

  if (rank == 0) {
    printf("zlib version: %s\n", ZLIB_VERSION);
    printf("zlib-ng version: %s\n", ZLIBNG_VERSION);
  }

  MPI_Finalize();
}
$ mpicc ./mpi-hello.c -I$(spack location -i zlib-ng)/include
$ mpirun -n 2 ./a.out
Hello world from rank 1
Hello world from rank 0
zlib version: 1.3.1.zlib-ng
zlib-ng version: 2.3.3

If we look at the full set of path variables set by activation:

$ env | grep PATH=
PKG_CONFIG_PATH=/home/spack/spack/var/spack/environments/myproject/.spack-env/view/lib/pkgconfig:/home/spack/spack/var/spack/environments/myproject/.spack-env/view/lib64/pkgconfig:/usr/share/pkgconfig:/home/spack/spack/var/spack/environments/myproject/.spack-env/view/share/pkgconfig:.
ACLOCAL_PATH=/home/spack/spack/var/spack/environments/myproject/.spack-env/view/share/aclocal:.
PATH=/home/spack/spack/var/spack/environments/myproject/.spack-env/view/bin:/home/spack/spack/bin:/opt/spack/view/bin:/root/spack/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MANPATH=/home/spack/spack/var/spack/environments/myproject/.spack-env/view/share/man:/home/spack/spack/var/spack/environments/myproject/.spack-env/view/man:/usr/share/man:.:
CMAKE_PREFIX_PATH=/home/spack/spack/var/spack/environments/myproject/.spack-env/view:.

we find CMAKE_PREFIX_PATH and PKG_CONFIG_PATH too, so build tools find the environment’s libraries and headers automatically.

Removing Packages

Spack offers two ways to get rid of a package in an environment:

  • spack remove takes a spec out of the environment

  • spack uninstall deletes the installed files from disk

In a setup with several environments these behave quite differently, so let’s create a second environment to see how. We’ll create myproject2, activate it, and add both scr and trilinos:

$ spack env create myproject2
==> Created environment myproject2 in: /home/spack/spack/var/spack/environments/myproject2
==> Activate with: spack env activate myproject2
$ spack env activate myproject2
$ spack add scr trilinos
==> Adding scr to environment myproject2
==> Adding trilinos to environment myproject2

then concretize and install as usual:

$ spack concretize
$ spack install

spack find lets us confirm the environment now holds both roots and their dependencies:

$ spack find
==> In environment myproject2 (2 root specs)
[+] scr	 [+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 scr@2.0.0  trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
berkeley-db@18.1.40  expat@2.8.1  gmp@6.3.0	libffi@3.5.2  nghttp2@1.67.1  python@3.14.5
curl@8.20.0	     gettext@1.0  hwloc@2.13.0	lz4@1.10.0    openssh@10.3p1  zlib-ng@2.3.3
elfutils@0.194	     glib@2.88.1  krb5@1.22.2	ncurses@6.6   openssl@3.6.1   zstd@1.5.7

-- linux-ubuntu26.04-x86_64_v3 / %c,fortran=gcc@15.2.0 ----------
libyogrt@1.35

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libgcrypt@1.12.2	 mpfr@4.2.2	 pmix@6.1.0
dtcmp@1.1.5	      libgpg-error@1.61	 munge@0.5.18	 prrte@4.1.0
gdbm@1.26	      libiconv@1.18	 numactl@2.0.19	 readline@8.3
json-c@0.18	      libmd@1.1.0	 pcre2@10.44	 slurm@25-05-1-1
less@692	      libpciaccess@0.17	 pdsh@2.35	 sqlite@3.53.1
libbsd@0.12.2	      libxcrypt@4.5.2	 perl@5.42.0	 tar@1.35
libedit@3.1-20251016  libxml2@2.15.3	 pigz@2.8	 util-linux-uuid@2.41
libevent@2.1.12	      lwgrp@1.0.6	 pkgconf@2.5.1	 xz@5.8.3

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43  python-venv@1.0
==> 62 installed packages
==> 25 concretized packages to be installed (show with `spack find -c`)

So myproject contains tcl and trilinos, while myproject2 contains scr and trilinos.

Let’s start with the simplest case. scr is used only by myproject2, so we can remove it cleanly. spack remove is the counterpart to spack add: it drops scr as a root spec.

$ spack remove scr
==> scr has been removed from /home/spack/spack/var/spack/environments/myproject2/spack.yaml

That only updates the environment’s configuration, though. Right afterward, spack find still lists scr. It is no longer a root, but it is still part of the environment:

$ spack find
==> In environment myproject2 (1 root spec)
[+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 scr@2.0.0  trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
berkeley-db@18.1.40  expat@2.8.1  gmp@6.3.0	libffi@3.5.2  nghttp2@1.67.1  python@3.14.5
curl@8.20.0	     gettext@1.0  hwloc@2.13.0	lz4@1.10.0    openssh@10.3p1  zlib-ng@2.3.3
elfutils@0.194	     glib@2.88.1  krb5@1.22.2	ncurses@6.6   openssl@3.6.1   zstd@1.5.7

-- linux-ubuntu26.04-x86_64_v3 / %c,fortran=gcc@15.2.0 ----------
libyogrt@1.35

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libgcrypt@1.12.2	 mpfr@4.2.2	 pmix@6.1.0
dtcmp@1.1.5	      libgpg-error@1.61	 munge@0.5.18	 prrte@4.1.0
gdbm@1.26	      libiconv@1.18	 numactl@2.0.19	 readline@8.3
json-c@0.18	      libmd@1.1.0	 pcre2@10.44	 slurm@25-05-1-1
less@692	      libpciaccess@0.17	 pdsh@2.35	 sqlite@3.53.1
libbsd@0.12.2	      libxcrypt@4.5.2	 perl@5.42.0	 tar@1.35
libedit@3.1-20251016  libxml2@2.15.3	 pigz@2.8	 util-linux-uuid@2.41
libevent@2.1.12	      lwgrp@1.0.6	 pkgconf@2.5.1	 xz@5.8.3

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43  python-venv@1.0
==> 62 installed packages
==> 25 concretized packages to be installed (show with `spack find -c`)

To actually drop it, we reconcretize the environment:

$ spack concretize
==> No new specs to concretize.
==> Updating view at /home/spack/spack/var/spack/environments/myproject2/.spack-env/view

Now scr, along with any dependencies nothing else needs, has been pruned, and spack find no longer lists it:

$ spack find
==> In environment myproject2 (1 root spec)
[+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
berkeley-db@18.1.40  gettext@1.0   krb5@1.22.2	nghttp2@1.67.1	openssl@3.6.1  zstd@1.5.7
curl@8.20.0	     hwloc@2.13.0  ncurses@6.6	openssh@10.3p1	zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libevent@2.1.12	 libxml2@2.15.3	 pkgconf@2.5.1	tar@1.35
gdbm@1.26	      libiconv@1.18	 numactl@2.0.19	 pmix@6.1.0	xz@5.8.3
less@692	      libpciaccess@0.17	 perl@5.42.0	 prrte@4.1.0
libedit@3.1-20251016  libxcrypt@4.5.2	 pigz@2.8	 readline@8.3

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43
==> 38 installed packages
==> 14 concretized packages to be installed (show with `spack find -c`)

trilinos is a more interesting case, because myproject uses it too. Environments only point to shared installations rather than owning the files, so Spack won’t let us delete one out from under another environment. If we try to uninstall trilinos from myproject2, Spack refuses, since myproject still references it:

$ spack uninstall -y trilinos
==> Refusing to uninstall the following specs
    -- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
    u43pchx trilinos@17.1.1

==> The following environments still reference these specs:
    myproject

==> Error: There are still dependents.
  use `spack remove` to remove the spec from the current environment
  use `spack env remove` to remove environments
  use `spack uninstall --force` to override

As the error suggests, spack remove is the right tool: it takes trilinos out of myproject2 without touching the shared installation.

$ spack remove trilinos
==> trilinos has been removed from /home/spack/spack/var/spack/environments/myproject2/spack.yaml
$ spack concretize
==> No new specs to concretize.

We know trilinos is still needed by myproject, so let’s switch back and confirm it’s still there:

$ spack env activate myproject
$ spack find
==> In environment myproject (2 root specs)
[+] tcl	 [+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
berkeley-db@18.1.40  gettext@1.0   krb5@1.22.2	nghttp2@1.67.1	openssl@3.6.1  zlib-ng@2.3.3
curl@8.20.0	     hwloc@2.13.0  ncurses@6.6	openssh@10.3p1	tcl@8.6.17     zstd@1.5.7

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libevent@2.1.12	 libxml2@2.15.3	 pkgconf@2.5.1	tar@1.35
gdbm@1.26	      libiconv@1.18	 numactl@2.0.19	 pmix@6.1.0	xz@5.8.3
less@692	      libpciaccess@0.17	 perl@5.42.0	 prrte@4.1.0
libedit@3.1-20251016  libxcrypt@4.5.2	 pigz@2.8	 readline@8.3

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43
==> 39 installed packages
==> 14 concretized packages to be installed (show with `spack find -c`)

myproject still has trilinos as a root spec.

Environments on disk

We have been treating an environment as an abstraction, but it is really just a directory on disk. spack cd -e takes us to myproject’s directory:

$ spack cd -e myproject
$ pwd
/home/spack/spack/var/spack/environments/myproject
$ ls
spack.lock  spack.yaml

Because we created myproject with spack env create <name>, it lives under var/spack/environments inside the Spack installation. This is what makes it a managed environment: we can refer to it by name. Environments can also be independent, with their files placed in any directory of our choosing.

The directory holds the two files that define the environment:

  • spack.yaml: the manifest file containing the abstract specs we asked for plus configuration settings.

  • spack.lock: the lockfile containing the concrete specs generated whenever the environment is concretized.

spack.yaml is the human-readable file we have been editing indirectly with spack add and spack remove:

$ cat spack.yaml
# This is a Spack Environment file.
#
# It describes a set of packages to be installed, along with
# configuration settings.
spack:
  # add package specs to the `specs` list
  specs:
  - tcl
  - trilinos
  view: true
  concretizer:
    unify: true

The concretizer:unify: true setting ensures all specs in the environment share a single version of each dependency. spack.lock records the fully concretized environment (every package, version, variant, and dependency) so the build can be reproduced exactly. It is machine-readable JSON:

$ jq < spack.lock | head -30
{
  "_meta": {
    "file-type": "spack-lockfile",
    "lockfile-version": 6,
    "specfile-version": 5
  },
  "spack": {
    "version": "1.2.0.dev0",
    "type": "git",
    "commit": "3d24b94ef3d15a4864794f98807a7fcc17b83f48"
  },
  "roots": [
    {
      "hash": "d4ibosbgfm7536ij2dmdu6nnll5g5zpm",
      "spec": "tcl"
    },
    {
      "hash": "u43pchxcfkd7syptwimxl4lozm5jmy2h",
      "spec": "trilinos"
    }
  ],
  "concrete_specs": {
    "d4ibosbgfm7536ij2dmdu6nnll5g5zpm": {
      "name": "tcl",
      "version": "8.6.17",
      "arch": {
	"platform": "linux",
	"platform_os": "ubuntu26.04",
	"target": "x86_64_v3"
      },

The full file runs to thousands of lines. A hidden .spack-env directory (not shown by ls) sits alongside these files and holds Spack’s bookkeeping, including the view we used earlier.

Managed environments also appear by name in spack env list, with the active one highlighted:

$ spack env list
==> 2 environments
    myproject  myproject2

We will come back to both files when we reproduce environments later.

Configuring environments

We’ve seen spack.yaml contains the root specs of the environment. It also controls configuration settings that shape how Spack behaves when the environment is used.

Let’s edit spack.yaml to require mpich as our mpi provider using spack config edit (make sure EDITOR is set first). You should now have spack.yaml open in your editor. Change it to include the packages:mpi:require entry below:

# This is a Spack Environment file.
#
# It describes a set of packages to be installed, along with
# configuration settings.
spack:
  packages:
    mpi:
      require: [mpich]

  # add package specs to the `specs` list
  specs:
  - tcl
  - trilinos

The environment is now out of sync: myproject was installed with openmpi, but the configuration now requires mpich. If we run spack concretize, Spack sees the existing concretization is still valid and does nothing:

$ spack concretize
==> No new specs to concretize.

To force Spack to re-concretize from scratch, use spack concretize --force:

$ spack concretize --force
==> Concretized 2 specs:
[+]  d4ibosb  tcl@8.6.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  mmywg7x	  ^compiler-wrapper@1.1.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yjlog5x	  ^gcc@15.2.0+binutils+bootstrap~graphite+libsanitizer~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  xm76mt3	  ^gcc-runtime@15.2.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yc4n2pp	  ^glibc@2.43 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  r4lhaok	  ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  g72d7i3	  ^zlib-ng@2.3.3+compat+new_strategies+opt+pic+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  3sqhxga  trilinos@17.1.1~adelus~adios2+amesos2+anasazi~basker+belos~boost~chaco~complex~cuda~cuda_constexpr~cuda_rdc~cusparse~debug~dtk~exodus+explicit_template_instantiation~float+fortran~gtest+hdf5~hypre+ifpack2~intrepid2~ipo+kokkos~mesquite~minitensor+mpi+muelu~mumps~nox~openmp~pamgen~panzer~phalanx~piro~python~rocm~rocm_rdc~rol+sacado~scorec~shards+shared~shylu~stk~stokhos~stratimikos~strumpack~suite-sparse~superlu-dist~teko~tempus~test~thyra+tpetra~trilinoscouplings~wrapper~x11~zoltan~zoltan2 build_system=cmake build_type=Release cxxstd=20 generator=make gotype=long_long platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  a4wqsr7	  ^cmake@3.31.11~doc+ncurses+ownlibs~qtgui build_system=generic build_type=Release platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  j2fa7xl	      ^curl@8.20.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs:=shared,static tls:=openssl platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  4lyasaz		  ^nghttp2@1.67.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  ao2onuz		      ^diffutils@3.12 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  33yozp5		  ^openssl@3.6.1~docs+shared build_system=generic certs=mozilla platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  axeuqg3		      ^ca-certificates-mozilla@2026-03-19 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  bvphs3b		      ^perl@5.42.0+cpanm+opcode+open+shared+threads build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  27d4iyp			  ^berkeley-db@18.1.40+cxx~docs+stl build_system=autotools patches:=26090f4,b231fcc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  ohmdb2l			  ^less@692 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ekvivpv	      ^ncurses@6.6~symlinks+termlib abi=none build_system=autotools patches:=7a351bc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  jceyzq7	  ^hdf5@1.14.6~cxx~fortran+hl~ipo~java~map+mpi+shared~subfiling~szip~threadsafe+tools api=default build_system=cmake build_type=Release generator=make platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  yvl6jpi	      ^pkgconf@2.5.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ujctyey	  ^hwloc@2.13.0~cairo~cuda~gl~level_zero~libudev+libxml2~nvml~opencl+pci~rocm build_system=autotools libs:=shared,static patches:=b4db98b platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  qzkk5ym	      ^libpciaccess@0.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  o5fy6wf		  ^util-macros@1.20.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  ujlg2ua	      ^libxml2@2.15.3+pic~python+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  vbwvgwx		  ^libiconv@1.18 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  hhjyyqy		  ^xz@5.8.3~pic build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  kpwomw3	  ^kokkos@5.1.1~aggressive_vectorization~cmake_lang~complex_align~cuda~debug~debug_bounds_check+deprecated_code~hip_relocatable_device_code~hpx~hwloc~ipo~openmp+pic~rocm+serial+shared~sycl~tests~threads~tuning~wrapper build_system=cmake build_type=Release cxxstd=20 generator=make intel_gpu_arch=none platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  5zilkuz	  ^kokkos-kernels@5.1.1~blas~cblas~cublas~cuda~cusolver~cusparse~execspace_cuda~execspace_openmp~execspace_serial~execspace_threads~ipo~lapack~lapacke~memspace_cudaspace~memspace_cudauvmspace~mkl~openmp~rocblas~rocsolver~rocsparse~serial+shared~superlu~threads build_system=cmake build_type=Release generator=make layouts=left offsets:=int,size_t ordinals:=int scalars:=double platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  xkilhym	  ^mpich@5.0.1~argobots~cuda+fortran+hwloc+hydra~level_zero+libxml2+pci~rocm+romio~slurm~vci~verbs+wrapperrpath~xpmem build_system=autotools datatype-engine=auto device=ch4 netmod=ofi pmi=default platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  punbqrx	      ^findutils@4.10.0 build_system=autotools patches:=440b954 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  sle3ix4		  ^gettext@1.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  f5xe4px		      ^tar@1.35 build_system=autotools zip=pigz platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  afklka7			  ^pigz@2.8 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  itb4a2s	      ^libfabric@2.5.1~asan~cuda~debug~kdreg~level_zero~lsan~rocm~tsan~ubsan~uring build_system=autotools fabrics:=sockets,tcp,udp platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  derywaq	      ^python@3.14.5+bz2+ctypes+dbm~debug~freethreading+libxml2+lzma~optimizations+pic+pyexpat+pythoncmd+readline+shared+sqlite3+ssl~static~tests~tkinter+uuid+zlib+zstd build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  cbtgjrh		  ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  d462mhw		  ^expat@2.8.1+libbsd build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  7o3mv6c		      ^libbsd@0.12.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  yvvn7mu			  ^libmd@1.1.0 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  cq4dkuc		  ^gdbm@1.26 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  aiceosz		  ^libffi@3.5.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  k25xiih		  ^readline@8.3 build_system=autotools patches:=21f0a03,72dee13,e273643 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  unjd5da		  ^sqlite@3.53.1+column_metadata+fts+rtree build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  clufswx		  ^util-linux-uuid@2.41 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  63aruxk		  ^zstd@1.5.7+programs build_system=makefile compression:=none libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  7kdghmr	  ^openblas@0.3.33~bignuma~consistent_fpcsr+dynamic_dispatch+fortran~ilp64+locking+pic+shared~static build_system=makefile patches:=723ddc1 symbol_suffix=none threads=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0

==> Updating view at /home/spack/spack/var/spack/environments/myproject/.spack-env/view

All the specs are now concrete with mpich as the MPI implementation, ready to be installed. Next you’d run spack install to rebuild the environment with the new MPI provider.

Note

In general, when building an environment it is also possible to add and install specs one at a time, but Spack will then concretize each new spec greedily against the versions already locked in. This can lead to a different (and sometimes less optimal) result than concretizing everything together.

Sharing environments

The spack.yaml and spack.lock files we have been working with are not just a record of the environment: they are also the mechanism for sharing it. You can commit them to version control, hand them to a colleague, or drop them into a CI/CD pipeline. Anyone with a Spack installation can recreate the environment from them.

To demonstrate, we’ll play the role of the recipient of a shared environment. Let’s build a fresh independent environment in a new code/ directory, which stands in for a project a colleague has shared with us:

$ cd
$ mkdir code
$ cd code
$ spack env create -d .
==> Created independent environment in: /home/spack/code
==> Activate with: spack env activate .

Since the environment is independent, it must be activated by path, not by name. Edit the spack.yaml created in the directory to add trilinos and openmpi:

# This is a Spack Environment file.
#
# It describes a set of packages to be installed, along with
# configuration settings.
spack:
  # add package specs to the `specs` list
  specs:
  - trilinos
  - openmpi
  view: true
  concretizer:
    unify: true
$ spack env activate .
$ spack install
==> Concretized 2 specs
[+]  qfut5qq  openmpi@5.0.10+atomics~cuda~debug+fortran~gpfs~internal-hwloc~internal-libevent~internal-pmix~ipv6~java~lustre~memchecker~openshmem~rocm~romio+rsh~static~two_level_namespace+vt+wrapper-rpath build_system=autotools fabrics:=none patches:=646eb1a romio-filesystem:=none schedulers:=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  jo3eg4r	  ^autoconf@2.72 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  y6uqrto	      ^m4@1.4.21+sigsegv build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  ao2onuz		  ^diffutils@3.12 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  phcmfqk		  ^libsigsegv@2.15 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  yhkgfai	  ^automake@1.18.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  mmywg7x	  ^compiler-wrapper@1.1.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yjlog5x	  ^gcc@15.2.0+binutils+bootstrap~graphite+libsanitizer~mold~nvptx~piclibs~profiled~strip build_system=autotools build_type=RelWithDebInfo languages:='c,c++,fortran' platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  xm76mt3	  ^gcc-runtime@15.2.0 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[e]  yc4n2pp	  ^glibc@2.43 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  r4lhaok	  ^gmake@4.4.1~guile build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ujctyey	  ^hwloc@2.13.0~cairo~cuda~gl~level_zero~libudev+libxml2~nvml~opencl+pci~rocm build_system=autotools libs:=shared,static patches:=b4db98b platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  qzkk5ym	      ^libpciaccess@0.17 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  o5fy6wf		  ^util-macros@1.20.2 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3
[+]  ujlg2ua	      ^libxml2@2.15.3+pic~python+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  vbwvgwx		  ^libiconv@1.18 build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  hhjyyqy		  ^xz@5.8.3~pic build_system=autotools libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ekvivpv	      ^ncurses@6.6~symlinks+termlib abi=none build_system=autotools patches:=7a351bc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  oopqoag	  ^libevent@2.1.12+openssl build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  33yozp5	      ^openssl@3.6.1~docs+shared build_system=generic certs=mozilla platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  axeuqg3		  ^ca-certificates-mozilla@2026-03-19 build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3
[b]  3gdq456	  ^libtool@2.5.4 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  mguwetc	      ^file@5.46+static build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  63aruxk		  ^zstd@1.5.7+programs build_system=makefile compression:=none libs:=shared,static platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  punbqrx	      ^findutils@4.10.0 build_system=autotools patches:=440b954 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  sle3ix4		  ^gettext@1.0+bzip2+curses+git~libunistring+libxml2+pic+shared+tar+xz build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  f5xe4px		      ^tar@1.35 build_system=autotools zip=pigz platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  afklka7			  ^pigz@2.8 build_system=makefile platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  2t2useu	  ^numactl@2.0.19 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  m6yx5j3	  ^openssh@10.3p1+gssapi build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  ldqeqfw	      ^krb5@1.22.2+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[b]  lbkegpi		  ^bison@3.8.2~color build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  uwyh3xy	      ^libedit@3.1-20251016 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  bkzcu2s	      ^libxcrypt@4.5.2~obsolete_api build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  bvphs3b	  ^perl@5.42.0+cpanm+opcode+open+shared+threads build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  27d4iyp	      ^berkeley-db@18.1.40+cxx~docs+stl build_system=autotools patches:=26090f4,b231fcc platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  cbtgjrh	      ^bzip2@1.0.8~debug~pic+shared build_system=generic platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  cq4dkuc	      ^gdbm@1.26 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  k25xiih		  ^readline@8.3 build_system=autotools patches:=21f0a03,72dee13,e273643 platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ohmdb2l	      ^less@692 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  yvl6jpi	  ^pkgconf@2.5.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  ycyqykw	  ^pmix@6.1.0~munge~python build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[+]  nldxmxw	  ^prrte@4.1.0 build_system=autotools patches:=64faa1a,91b28f5 schedulers:=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c=gcc@15.2.0
[b]  vwo3ajm	      ^flex@2.6.3+lex~nls build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  g72d7i3	  ^zlib-ng@2.3.3+compat+new_strategies+opt+pic+shared build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  u43pchx  trilinos@17.1.1~adelus~adios2+amesos2+anasazi~basker+belos~boost~chaco~complex~cuda~cuda_constexpr~cuda_rdc~cusparse~debug~dtk~exodus+explicit_template_instantiation~float+fortran~gtest~hdf5~hypre+ifpack2~intrepid2~ipo+kokkos~mesquite~minitensor+mpi+muelu~mumps~nox~openmp~pamgen~panzer~phalanx~piro~python~rocm~rocm_rdc~rol+sacado~scorec~shards+shared~shylu~stk~stokhos~stratimikos~strumpack~suite-sparse~superlu-dist~teko~tempus~test~thyra+tpetra~trilinoscouplings~wrapper~x11~zoltan~zoltan2 build_system=cmake build_type=Release cxxstd=20 generator=make gotype=long_long platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0
[b]  a4wqsr7	  ^cmake@3.31.11~doc+ncurses+ownlibs~qtgui build_system=generic build_type=Release platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  j2fa7xl	      ^curl@8.20.0~gssapi~ldap~libidn2~librtmp~libssh~libssh2+nghttp2 build_system=autotools libs:=shared,static tls:=openssl platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  4lyasaz		  ^nghttp2@1.67.1 build_system=autotools platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx=gcc@15.2.0
[+]  kpwomw3	  ^kokkos@5.1.1~aggressive_vectorization~cmake_lang~complex_align~cuda~debug~debug_bounds_check+deprecated_code~hip_relocatable_device_code~hpx~hwloc~ipo~openmp+pic~rocm+serial+shared~sycl~tests~threads~tuning~wrapper build_system=cmake build_type=Release cxxstd=20 generator=make intel_gpu_arch=none platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  5zilkuz	  ^kokkos-kernels@5.1.1~blas~cblas~cublas~cuda~cusolver~cusparse~execspace_cuda~execspace_openmp~execspace_serial~execspace_threads~ipo~lapack~lapacke~memspace_cudaspace~memspace_cudauvmspace~mkl~openmp~rocblas~rocsolver~rocsparse~serial+shared~superlu~threads build_system=cmake build_type=Release generator=make layouts=left offsets:=int,size_t ordinals:=int scalars:=double platform=linux os=ubuntu26.04 target=x86_64_v3 %cxx=gcc@15.2.0
[+]  7kdghmr	  ^openblas@0.3.33~bignuma~consistent_fpcsr+dynamic_dispatch+fortran~ilp64+locking+pic+shared~static build_system=makefile patches:=723ddc1 symbol_suffix=none threads=none platform=linux os=ubuntu26.04 target=x86_64_v3 %c,cxx,fortran=gcc@15.2.0

[+] qfut5qq openmpi@5.0.10 /home/spack/spack/opt/spack/linux-x86_64_v3/openmpi-5.0.10-qfut5qqwp2fzaq3ymgk7nxvjv3qyrvml (0s)
==> Updating view at /home/spack/code/.spack-env/view

Passing either of these files to spack env create recreates the environment. The spack.yaml file preserves the abstract requirements but allows the concretizer to adapt to a new platform. The spack.lock file fixes every concretization decision and reproduces the build exactly.

Using spack.yaml

Recreating from spack.yaml preserves the root specs but leaves dependency resolution to the concretizer, which may produce different versions on a new platform or as packages are updated:

$ spack env create abstract spack.yaml
==> Created environment abstract in: /home/spack/spack/var/spack/environments/abstract
==> Activate with: spack env activate abstract

The new environment has no installed packages yet, only the root specs from the file are registered:

$ spack env activate abstract
$ spack find
==> In environment abstract (2 root specs)
 -  openmpi   -	 trilinos

==> 0 installed packages
==> 0 concretized packages to be installed (show with `spack find -c`)

Using spack.lock

Recreating from spack.lock reproduces the exact build, and thus requires the same machine architecture. All packages recorded in the lockfile are installed without a separate install step:

$ spack env create concrete spack.lock
==> Created environment concrete in: /home/spack/spack/var/spack/environments/concrete
==> Activate with: spack env activate concrete
==> Updating view at /home/spack/spack/var/spack/environments/concrete/.spack-env/view

Since the environment was created from spack.lock, the root specs and all their dependencies are already installed:

$ spack env activate concrete
$ spack find
==> In environment concrete (2 root specs)
[+] openmpi  [+] trilinos

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx,fortran=gcc@15.2.0 ------
openblas@0.3.33	 openmpi@5.0.10	 trilinos@17.1.1

-- linux-ubuntu26.04-x86_64_v3 / %c,cxx=gcc@15.2.0 --------------
berkeley-db@18.1.40  gettext@1.0   krb5@1.22.2	nghttp2@1.67.1	openssl@3.6.1  zstd@1.5.7
curl@8.20.0	     hwloc@2.13.0  ncurses@6.6	openssh@10.3p1	zlib-ng@2.3.3

-- linux-ubuntu26.04-x86_64_v3 / %c=gcc@15.2.0 ------------------
bzip2@1.0.8	      libevent@2.1.12	 libxml2@2.15.3	 pkgconf@2.5.1	tar@1.35
gdbm@1.26	      libiconv@1.18	 numactl@2.0.19	 pmix@6.1.0	xz@5.8.3
less@692	      libpciaccess@0.17	 perl@5.42.0	 prrte@4.1.0
libedit@3.1-20251016  libxcrypt@4.5.2	 pigz@2.8	 readline@8.3

-- linux-ubuntu26.04-x86_64_v3 / %cxx=gcc@15.2.0 ----------------
kokkos@5.1.1  kokkos-kernels@5.1.1

-- linux-ubuntu26.04-x86_64_v3 / no compilers -------------------
compiler-wrapper@1.1.0	gcc@15.2.0  gcc-runtime@15.2.0	glibc@2.43
==> 38 installed packages
==> 14 concretized packages to be installed (show with `spack find -c`)

Removing environments

Let’s clean up the environments we created during the tutorial. First, deactivate the current environment:

$ spack env deactivate

Then remove all the managed environments at once:

$ spack env rm myproject myproject2 abstract concrete

More information

This tutorial only scratches the surface of environments and what they can do. For more information, take a look at the Spack resources below.

Setting up and building environments

Using environments

Finding examples of environments