Custom Snapshots¶
Custom snapshots allow you to create your own snapshots, which provide a list of specific hackage packages to use, along with flags and ghc-options. The definition of a basic snapshot looks like the following:
resolver: ghc-8.0
packages:
- unordered-containers-0.2.7.1
- hashable-1.2.4.0
- text-1.2.2.1
flags:
unordered-containers:
debug: true
If you put this in a snapshot.yaml
file in the same directory as your project,
you can now use the custom snapshot like this:
resolver:
name: simple-snapshot # Human readable name for the snapshot
location: simple-snapshot.yaml
This is an example of a custom snapshot stored in the filesystem. They are assumed to be mutable, so you are free to modify it. We detect that the snapshot has changed by hashing the contents of the involved files, and using it to identify the snapshot internally. It is often reasonably efficient to modify a custom snapshot, due to stack sharing snapshot packages whenever possible.
Using a URL instead of a filepath¶
For efficiency, URLs are treated differently. If I uploaded the snapshot to
https://domain.org/snapshot-1.yaml
, it is expected to be immutable. If you
change that file, then you lose any reproducibility guarantees.
Extending snapshots¶
The example custom snapshot above uses a compiler resolver, and so has few packages. We can also extend existing snapshots, by using the usual resolver setting found in stack configurations. All possible resolver choices are valid, so this means that custom snapshots can even extend other custom snapshots.
Lets say that we want to use lts-7.1
, but use a different version of text
than the one it comes with, 1.2.2.1
. To downgrade it to 1.2.2.0
, we need a
custom snapshot file with the following:
resolver: lts-7.1
packages:
- text-1.2.2.0
Overriding the compiler¶
The following snapshot specification will be identical to lts-7.1
, but instead
use ghc-7.10.3
instead of ghc-8.0.1
:
resolver: lts-7.1
compiler: ghc-7.10.3
Dropping packages¶
The following snapshot specification will be identical to lts-7.1
, but without
the text
package in our snapshot. Removing this package will cause all the
packages that depend on text
to be unbuildable, but they will still be present
in the snapshot.
resolver: lts-7.1
drop-packages:
- text
Specifying ghc-options¶
In order to specify ghc-options for a package, you use the same syntax as the
ghc-options field for build configuration.
The following snapshot specification will be identical to lts-7.1
, but
provides -O1
as a ghc-option for text
:
resolver: lts-7.1
packages:
- text-1.2.2.1
ghc-options:
text: -O1
This works somewhat differently than the stack.yaml ghc-options
field, in that
options can only be specified for packages that are mentioned in the custom
snapshot's packages
list. It sets the ghc-options, rather than extending those
specified in the snapshot being extended.
Another difference is that the *
entry for ghc-options
applies to all
packages in the packages
list, rather than all packages in the snapshot.
Specifying flags¶
In order to specify flags for a package, you use the same syntax as the
flags field for build configuration. The
following snapshot specification will be identical to lts-7.1
, but
it enables the developer
cabal flag:
resolver: lts-7.1
packages:
- text-1.2.2.1
ghc-options:
text:
developer: true
YAML format¶
In summary, the YAML format of custom snapshots has the following fields which are directly related to the same fields in the build configuration format:
-
resolver
, which specifies which snapshot to extend. It takes the same values as theresolver
field in stack.yaml. -
compiler
, which specifies or overrides the selection of compiler. Ifresolver
is absent, then a specification ofcompiler
is required. Its semantics are the same as thecompiler
field in stack.yaml.
Some fields look similar, but behave differently:
-
flags
specifies which cabal flags to use with each package. In order to specify a flag for a package, it must be listed in thepackages
list. -
ghc-options
, which specifies which cabal flags to use with each package. In order to specify ghc-options for a package, it must be listed in thepackages
list. The*
member of the map specifies flags that apply to every package in thepackages
list.
There are two fields which work differently than in the build configuration format:
-
packages
, which specifies a list of hackage package versions. Note that when a package version is overridden, noflags
orghc-options
are taken from the snapshot that is being extended. If you want the same options as the snapshot being extended, they must be re-specified. -
drop-packages
, which specifies a list of packages to drop from the snapshot being overridden.
Future enhancements¶
We plan to enhance extensible snapshots in several ways in the future. See issue #1265, about "implicit snapshots". In summary, in the future:
1) It will be possible to use a specific git repository + commit hash in the
packages
list, like in regular stack.yaml configuration. Currently, custom
snapshots only work with packages on hackage.
2) stack.yaml
configurations will implicitly create a snapshot. This means
that the non-local packages will get shared between your projects, so there is
less redundant compilation!
3) flags
and ghc-options
for packages which are not listed in packages
are
silently ignored. See
#2654 for the current
status of this.