# Build with Spack

CP2K can be built and installed with [Spack]. [Spack] is a package manager designed to support
multiple versions and configurations on a wide variety of platforms and environments, with focus on
HPC.

To install CP2K with [Spack], you need to [install Spack].

```{note}
If it is the first time you use [Spack], you might have to run `spack compiler find` to setup the
compilers. See [Spack Compiler Configuration](https://spack.readthedocs.io/en/latest/getting_started.html#compiler-configuration)
for more information.
```

## Install CP2K with Spack

A barebone version of CP2K can be installed with [Spack] as follows:

```bash
spack install cp2k
```

This command will build CP2K, as well as all the necessary dependencies. If it is the first time you
run this command, building all the dependencies might take a while.

In order to use CP2K installed with [Spack], you can simply type

```bash
spack load cp2k
```

This command will add the appropriate directories to `PATH` and `MANPATH`. See
[using installed Spack packages] for more information.

### Customizing Installation

#### Variants

[Spack] allows to fully customize an installation. The [CP2K Spack package] has several options for
customization (called "variants", see [Spack package variants]). For example, to install CP2K with
`libint` and `libxc`, one can type

```bash
spack install cp2k +libint +libxc
```

`+VARIANT` will enable a boolean variant, while `~VARIANT` will disable a boolean variant. Non
boolean variants can be specified with the `VARIANT=VALUE` syntax (see [Spack package variants] for
more details). The previous installation command takes care of building CP2K with `libint` and
`libxc` support. More importantly, it takes care of building the appropriate versions of `libint`
and `libxc` to work with CP2K (Fortran support, ...).

#### Versions

Versions in [Spack] can be specified with `@` following the package name (see \[version
specifier\]). The following installs version `2023.2` of CP2K:

```bash
spack install cp2k@2023.2
```

A more complete installation of CP2K can be installed with the following:

```bash
spack install cp2k@2023.2 +libint +libxc +dlaf +sirius +cosma +spglib lmax=6 
```

The `cp2k@2023.2 +libint +libxc +dlaf +sirius +cosma +spglib lmax=6` string is called a [spec] in
[Spack] lingo.

#### CUDA and ROCm Support

The `cuda` and `rocm` variants are available for CP2K. Therefore, CUDA support can be enabled with
`+cuda` and ROCm support can be enabled with `+rocm`. `cuda_arch` and `amdgpu_target` allow
specifying the GPU architecture:

```bash
spack install cp2k +cuda cuda_arch=80
spack install cp2k +rocm amdgpu_target=gfx90a
```

[Spack] is designed to support the installation of different versions of the same software,
therefore there is no problem with running _both_ commands above. However, `spack load cp2k` will no
longer work, you will need to be a bit more specific:

```bash
spack load cp2k +cuda
```

### Managing Dependencies

Sometimes you need to control dependencies too. Dependencies are also [Spack] packages, and their
installation can be configured in the same way as for CP2K. A dependency spec is defined by `^`.

For example, if you want to install CP2K with CUDA support but [DBCSR] without CUDA support you can
do

```bash
spack install cp2k +cuda cuda_arch=80 ^dbcsr ~cuda
```

Another example, is the choice of vendor libraries. In order to use Intel oneAPI MKL, it can be
specified as a dependency:

```bash
spack install cp2k ^intel-oneapi-mkl +cluster
```

This command will build CP2K with Intel oneAPI MKL. `+cluster` is a variant of the
[Intel oneAPI Spack package] enabling cluster support (ScaLAPACK, BLACS, ...).

## Developer Workflow

[Spack] has support for developer workflows. One way to use [Spack] to develop CP2K, is to use
[Spack] to install all the necessary dependencies and then build CP2K manually.

To install only the dependencies of CP2K (and not CP2K itself) you can use

```bash
spack install --only=dependencies CP2K_SPEC
```

Once all dependencies are installed, you can get a shell with all the dependencies set up:

```bash
spack build-env CP2K_SPEC -- bash
```

From here, you can iterate CP2K development using the native build system as Spack would use it.

### Spack and CP2K Docker Containers

Some CP2K Docker containers install all the necessary dependencies with Spack. Building with Spack
can be time-consuming, because all dependencies are built from source. In order to speed-up
development and testing with the Spack-based Docker containers, you should enable a [Spack cache]
locally:

```bash
./tools/docker/spack_cache_start.sh
```

This command starts a local [MinIO] server that can be used as cache for the Spack packages. The
`spack_cache_stop.sh` script stops the server.

You can then build the Docker container (here the `test_spack` container, as an example) with the
following command:

```bash
docker build -f tools/docker/Dockerfile.test_spack -t cp2k_test_spack --shm-size=1Gb --network=host . 
```

The first build after enabling the cache will be as slow as usual, but all subsequent builds will be
much faster.

The cache is expected, as it dramatically improves build times. Should you need to build without
using the Spack cache, you can set it to an empty string as follows:

```bash
docker build -f tools/docker/Dockerfile.test_spack -t cp2k_test_spack --shm-size=1Gb --build-arg SPACK_CACHE="" .
```

[cp2k spack package]: https://packages.spack.io/package.html?name=cp2k
[dbcsr]: https://cp2k.github.io/dbcsr/develop/
[install spack]: https://spack.readthedocs.io/en/latest/getting_started.html#installation
[intel oneapi spack package]: https://packages.spack.io/package.html?name=intel-oneapi-mkl
[minio]: https://min.io/
[spack]: https://spack.readthedocs.io/en/latest/
[spack cache]: https://spack-tutorial.readthedocs.io/en/latest/tutorial_binary_cache.html
[spack package variants]: https://spack.readthedocs.io/en/latest/basic_usage.html#variants
[spec]: https://spack.readthedocs.io/en/latest/basic_usage.html#specs-dependencies
[using installed spack packages]: https://spack.readthedocs.io/en/latest/basic_usage.html#using-installed-packages
