Skip to content

Commit 9c86155

Browse files
committed
add source caching
- rename sourcecache to sourcemirror (for pre-populated source mirrors) - add sourcecache for read through source caching - after downloading a source, add it to the cache so that it does not have to be downloaded again.
1 parent c60fc53 commit 9c86155

15 files changed

Lines changed: 330 additions & 120 deletions

File tree

docs/build-caches.md

Lines changed: 147 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,189 @@
1-
# Build Caches
1+
# Mirrors and Build Caches
2+
3+
Spack can use *mirrors* and *caches* to speed up image builds and to build on systems with limited or no internet access.
4+
They are configured in a single `mirrors.yaml` file in the [system configuration](cluster-config.md).
5+
6+
A `mirrors.yaml` can describe four kinds of entry, each optional and each documented below:
7+
8+
| Entry | Count | Purpose |
9+
|-------|-------|---------|
10+
| [`buildcache`](#build-cache) | one | binary cache of built packages (the big build-time speed up) |
11+
| [`bootstrap`](#bootstrap-mirror) | one | mirror used to bootstrap Spack itself |
12+
| [`sourcemirror`](#source-mirrors) | many | read-only mirrors that provide package sources |
13+
| [`sourcecache`](#source-cache) | one | writable local cache that fills with sources as you build |
14+
15+
A complete example:
16+
17+
```yaml title="mirrors.yaml"
18+
buildcache:
19+
url: file:///capstor/scratch/team/uenv-cache
20+
private_key: $SCRATCH/.keys/spack-push-key.gpg
21+
mount_specific: true
22+
bootstrap:
23+
url: https://bootstrap.spack.io
24+
sourcemirror:
25+
mirror1:
26+
url: https://example.com/spack-sources
27+
sourcecache:
28+
path: /capstor/scratch/$USER/spack-sources
29+
```
230
3-
Stackinator facilitates using Spack's binary build caches to speed up image builds.
4-
Build caches are essential if you plan to build images regularly, as they generally lead to a roughly 10x speed up.
5-
This is the difference between half an hour or 3 minutes to build a typical image.
31+
To stop using any entry, remove (or comment out) it from `mirrors.yaml`.
632

7-
## Using Build caches
33+
## Build cache
834

9-
To use a build cache, create a simple YAML file:
35+
A build cache is a binary cache of built packages.
36+
Reusing binaries instead of rebuilding from source is roughly a 10x speed up — the difference between a 3 minute and a 30 minute image build — so a build cache is essential if you build images regularly.
1037

11-
```yaml title='cache-config.yaml'
12-
root: $SCRATCH/uenv-cache
13-
key: $SCRATCH/.keys/spack-push-key.gpg
38+
During a build Spack fetches packages from the cache when it can, and signs and pushes any package it has to build itself, so the cache improves over time.
39+
40+
```yaml title="mirrors.yaml"
41+
buildcache:
42+
url: file:///capstor/scratch/team/uenv-cache
43+
private_key: $SCRATCH/.keys/spack-push-key.gpg
1444
```
1545

16-
To use the cache, pass the configuration as an option to `stack-config` via the `-c/--cache` flag:
46+
| Field | Required | Description |
47+
|-------|----------|-------------|
48+
| `url` | yes | location of the cache (a `file://` path, or an `http(s)://`, `s3://` or `oci://` URL) |
49+
| `private_key` | yes | PGP key used to sign and push packages (see [Keys](#keys)) |
50+
| `public_key` | no | PGP key used to verify downloaded packages |
51+
| `name` | no | name Spack registers the mirror under (default `buildcache`) |
52+
| `mount_specific` | no | store the cache in a per-mount-point sub-directory (default `false`) |
53+
54+
### `mount_specific`
55+
56+
Spack binaries embed the install prefix (the image's mount point), so binaries built for `/user-environment` cannot be reused at a different mount point.
57+
Set `mount_specific: true` to append the mount point to the cache URL, giving each mount point its own sub-directory and avoiding relocation issues:
58+
59+
```yaml
60+
buildcache:
61+
url: file:///capstor/scratch/team/uenv-cache
62+
private_key: $SCRATCH/.keys/spack-push-key.gpg
63+
mount_specific: true # packages stored under .../uenv-cache/user-environment
64+
```
65+
66+
### Creating a build cache
67+
68+
A build cache needs an empty directory and a PGP signing key:
1769

1870
```bash
19-
stack-config -b $build_path -r $recipe_path -s $system_config -c cache-config.yaml
71+
# 1. create the cache directory
72+
mkdir -p $SCRATCH/uenv-cache
73+
74+
# 2. generate and export a signing key
75+
spack gpg create <name> <e-mail>
76+
spack gpg export --secret $SCRATCH/.keys/spack-push-key.gpg
2077
```
2178

22-
??? warning "If you using an old binary build cache"
23-
Since v3, Stackinator creates a sub-directory in the build cache for each mount point.
24-
For example, in the above example, the build cache for the `/user-environment` mount point would be `$SCRATCH/uenv-cache/user-environment`.
25-
The rationale for this is so that packages for different mount points are not mixed, to avoid having to relocate binaries.
79+
See [Keys](#keys) for where to store the key.
80+
81+
### Force pushing
82+
83+
Packages are pushed to the cache after each environment builds successfully; nothing is pushed if a build fails.
84+
When iterating on a recipe with failing builds, force-push everything built so far with the `cache-force` target:
2685

27-
To continue using a build caches from before v3, first copy the `build_cache` path to a subdirectory, e.g.:
86+
```bash
87+
env --ignore-environment PATH=/usr/bin:/bin:`pwd -P`/spack/bin make cache-force
88+
```
2889

29-
```bash
30-
mkdir $SCRATCH/uenv-cache/user-environment
31-
mv $SCRATCH/uenv-cache/build_cache $SCRATCH/uenv-cache/user-environment
32-
```
90+
## Bootstrap mirror
3391

34-
### Build-only caches
92+
Spack bootstraps some of its own dependencies (such as the `clingo` concretizer) on first use.
93+
A bootstrap mirror lets it do this without reaching the internet — useful on air-gapped systems.
3594

36-
A build cache can be configured to be read-only by not providing a `key` in the cache configuration file.
95+
```yaml title="mirrors.yaml"
96+
bootstrap:
97+
url: https://bootstrap.spack.io
98+
```
3799
38-
## Creating a Build Cache
100+
| Field | Required | Description |
101+
|-------|----------|-------------|
102+
| `url` | yes | location of the bootstrap mirror |
103+
| `public_key` | no | PGP key used to verify the bootstrap binaries |
39104

40-
To create a build cache we need two things:
105+
## Source mirrors
41106

42-
1. An empty directory where the cache will be populated by Spack.
43-
2. A private PGP key
44-
* Only required for Stackinator to push packages to the cache when it builds a package that was not in the cache.
107+
Source mirrors provide package **source** archives, and are read-only: Spack fetches sources from them but never writes to them.
108+
Use them to build on air-gapped systems — populate a mirror on a connected system, mount it read-only, and Spack will fetch sources from it.
109+
Any number of source mirrors can be listed; Spack searches them in order.
45110

46-
Creating the cache directory is easy! For example, to create a cache on your scratch storage:
47-
```bash
48-
mkdir $SCRATCH/uenv-cache
111+
```yaml title="mirrors.yaml"
112+
sourcemirror:
113+
internal:
114+
url: https://mirror.example.com/spack-sources
115+
scratch:
116+
url: file:///capstor/scratch/team/spack-sources
49117
```
50118

51-
### Generating Keys
119+
| Field | Required | Description |
120+
|-------|----------|-------------|
121+
| `url` | yes | location of the source mirror |
122+
| `public_key` | no | PGP key used to verify sources |
52123

53-
An installation of Spack can be used to generate the key file:
124+
Populate a source mirror on an internet-connected system with Spack:
54125

55126
```bash
56-
# create a key
57-
spack gpg create <name> <e-mail>
127+
spack mirror create --directory /path/to/mirror --all
128+
```
129+
130+
## Source cache
58131

59-
# export key
60-
spack gpg export --secret spack-push-key.gpg
132+
A source cache is a single, **writable** local directory that Spack fills as it downloads sources.
133+
On internet-connected systems Spack checks the cache first; on a miss it downloads the source and stores it, so later builds reuse it and download times shrink over time.
134+
135+
Unlike a source mirror it needs no key, is written to automatically, and is created on demand.
136+
137+
```yaml title="mirrors.yaml"
138+
sourcecache:
139+
path: /capstor/scratch/$USER/spack-sources
61140
```
62141

63-
See the [spack documentation](https://spack.readthedocs.io/en/latest/getting_started.html#gpg-signing) for more information about GPG keys.
142+
| Field | Required | Description |
143+
|-------|----------|-------------|
144+
| `path` | yes | absolute path to a local directory (environment variables are expanded) |
64145

65-
### Managing Keys
146+
## Keys
66147

67-
The key needs to be in a location that is accessible during the build process, and secure.
68-
To keep your PGP key secret, you can generate it then move it to a path with appropriate permissions.
69-
In the example below, we create a path `.keys` for storing the key:
70-
```bash
71-
# create .keys path is visible only to you
72-
mkdir $SCRATCH/.keys
73-
chmod 700 $SCRATCH/.keys
148+
The `private_key` and `public_key` fields accept either:
149+
150+
* a **path** — absolute, or relative to the system configuration directory; or
151+
* a **base64-encoded key** inlined directly in `mirrors.yaml`.
152+
153+
```yaml
154+
buildcache:
155+
url: file:///capstor/scratch/team/uenv-cache
156+
private_key: $SCRATCH/.keys/spack-push-key.gpg # a path
157+
public_key: mQINBGm4GvsBEACTyzQF...== # inline base64
158+
```
159+
160+
Generate a key with Spack, and keep the secret key somewhere private:
74161

75-
# generate the key
162+
```bash
163+
mkdir $SCRATCH/.keys && chmod 700 $SCRATCH/.keys
76164
spack gpg create <name> <e-mail>
77165
spack gpg export --secret $SCRATCH/.keys/spack-push-key.gpg
78166
chmod 600 $SCRATCH/.keys/spack-push-key.gpg
79167
```
80168

81-
The cache-configuration would look like the following, where we assume that the cache is in `$SCRATCH/uenv-cache`:
82-
```yaml
83-
root: $SCRATCH/uenv-cache
84-
key: $SCRATCH/.keys/spack-push-key.gpg
85-
```
86-
!!! warning
87-
Don't blindly copy this documentation's advice on security settings.
169+
See the [Spack documentation](https://spack.readthedocs.io/en/latest/getting_started.html#gpg-signing) for more on GPG keys.
88170

89171
!!! failure "Don't use `$HOME`"
90-
Don't put the keys in `$HOME`, because the build process remounts `~` as a tmpfs, and you will get error messages that Spack can't read the key.
172+
The build remounts `~` as a tmpfs, so keys under `$HOME` are not visible during the build and Spack will fail to read them. Use scratch storage instead.
91173

92-
## Force pushing to build cache
174+
## Legacy `--cache` option
93175

94-
When build caches are enabled, all packages in a each Spack environment are pushed to the build cache after the whole environment has been built successfully -- nothing will be pushed to the cache if there is an error when building one of the packages.
176+
Before `mirrors.yaml`, a build cache was configured with a separate `cache.yaml` file passed to `stack-config` via `-c/--cache`:
95177

96-
When debugging a recipe, where failing builds have to be run multiple times, the overheads of rebuilding all packages from scratch can be wasteful.
97-
To force push all packages that have been built, use the `cache-force` makefile target:
178+
```yaml title="cache.yaml"
179+
root: $SCRATCH/uenv-cache
180+
key: $SCRATCH/.keys/spack-push-key.gpg
181+
```
98182

99183
```bash
100-
env --ignore-environment PATH=/usr/bin:/bin:`pwd -P`/spack/bin make cache-force
184+
stack-config -b $build -r $recipe -s $system -c cache.yaml
101185
```
186+
187+
This is **deprecated** and equivalent to a single `buildcache` entry (with `mount_specific: true`). Prefer configuring the build cache in `mirrors.yaml`.
188+
189+
Setting `key: null` configures a read-only cache that Spack fetches from but never pushes to.

docs/cluster-config.md

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,29 +95,10 @@ packages:
9595

9696
### Configuring Spack mirrors: `mirrors.yaml`
9797

98-
On air-gapped systems, Spack is unable to reach its default mirror to fetch packages. The `mirrors.yaml` configuration can be used to connect Spack to local mirrors for fetching and building packages.
98+
An optional `mirrors.yaml` connects Spack to local mirrors and caches, to speed up builds and to build on air-gapped systems.
99+
It can configure a build cache, a bootstrap mirror, read-only source mirrors, and a writable source cache.
99100

100-
`mirrors.yaml` treats source mirrors, buildcaches, and bootstrap mirrors the same, and they may all be included in this file. Spack will search the topmost mirror first and the bottom-most mirror last, and will append the default Spack mirror to the bottom of the list when the Spack mirror config is generated.
101-
102-
`mirrors.yaml` may include source mirrors, bootstrap mirrors, and buildcaches. Any number of source mirrors can be added, but only one bootstrap mirror and buildcache can be specified. Spack will search the source mirrors in order from first to last, and will append the default Spack mirror to the bottom of the list when the Spack mirror config is generated.
103-
104-
If using a buildcache, a private key must be provided for signing packages. An optional public key may be specified with any type of mirror to verify packages. The buildcache is registered with Spack under the name `buildcache`, which can be overridden with an optional `name` field.
105-
106-
To stop using a mirror, remove (or comment out) its entry from `mirrors.yaml`.
107-
108-
```yaml title="mirrors.yaml"
109-
bootstrap:
110-
url: file:///home/username/spack-mirror-2014-06-24
111-
buildcache:
112-
url: https://example.com/some/buildcache/mirror
113-
private_key: /user-home/.gnupg/private-keys-v1.d/my-private-key.asc
114-
sourcecache:
115-
mirror1:
116-
url: https://example.com/some/web-hosted/directory
117-
public_key: ../buildcache-key.public.gpg
118-
mirror2:
119-
url: https://example.com/some/other-web-hosted/directory
120-
```
101+
See [Mirrors and Build Caches](build-caches.md) for the full reference and examples.
121102

122103
## Site and System Configurations
123104

memory.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
claude --resume 71a36db9-9a83-4261-bad1-855caaca9f7e

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ nav:
88
- 'Recipes': recipes.md
99
- 'Cluster Configuration': cluster-config.md
1010
- 'Interfaces': interfaces.md
11-
- 'Build Caches': build-caches.md
11+
- 'Mirrors & Build Caches': build-caches.md
1212
- 'Spack 1.0': porting.md
1313
- 'Development': development.md
1414
# - Tutorial: tutorial.md

stackinator/builder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ def generate(self, recipe):
246246
spack_meta=spack_meta,
247247
gpg_keys=recipe.mirrors.gpg_key_paths(config_path),
248248
cache=recipe.build_cache_mirror,
249+
buildcache_push=recipe.push_to_build_cache,
249250
exclude_from_cache=["nvhpc", "cuda", "perl"],
250251
verbose=False,
251252
)

0 commit comments

Comments
 (0)