Stack cookbookCookbooks
A straight-to-the-point guide to Stack, popular Haskell build tool from FPComplete.
Also see the official guide.
# Build for development (no optimizations; compiles tests but doesn't run them)
stack build --fast --test --no-run-tests
# Build for production (-O -Wall -Werror)
stack build --pedantic
# Build a single subproject
stack build <exe/lib name>
# Build and copy binaries into ~/.local/bin
stack install
# ...or into a directory
stack install --local-bin-path=<dir>
stack build
builds the project. Most common flags that you'll need:
-
--test
,--bench
– compile and run tests/benchmarks. -
--no-run-tests
,--no-run-benchmarks
– don't run tests/benchmarks. -
--fast
– compile without optimizations. -
--file-watch
– automatically rebuild when you change files in the project. Very useful if you're not usingghcid
. -
--pedantic
– compile with all warnings enabled, treating warnings as errors. -
--profile
– build with profiling. -
--ghc-options="..."
– pass extra options to GHC.
# Create a stack.yaml file
stack init --resolver=lts-XX.YY
# Create a stack.yaml file and try to guess what snapshot to use
stack init
# Use cabal-install as a project creation wizard
mkdir <project name> && cd "$_" && cabal init && stack init
stack init
creates a stack.yaml
file for a project with an existing .cabal
file.
It's best to use as few different resolvers as possible to save space on your hard drive. Pick a snapshot you like and then pass it with --resolver=lts-XX.YY
. Existing snapshots and GHC versions are cached in ~/.stack
.
# Run an executable built with 'stack build'
stack exec <executable name>
# Run an executable and pass arguments to it
stack exec -- <executable name> <arguments...>
# Run something (e.g. GHC) from a particular snapshot
stack exec --resolver=lts-12.10 -- ghc --version
# Run something from a particular GHC version distributive
stack exec --resolver=ghc-8.6.3 -- ghc --version
stack exec
runs an executable in the context of the current project. It can be something built as a part of your project, but can also be a tool like ghc
, cabal
, haddock
, or ghc-pkg
.
# Build it, then run an executable
stack run <executable name> <arguments...>
# Build it, then run the first specified executable of the package
stack run
In the latest release, you can also use the new stack run
command to build the package and then run the specified executable. If your package contains an executable, you can just use plain stack run
to build and run this executable.
# Create a directory and a project
stack new <project name> <template name> --resolver=lts-XX.YY
# Create a directory and a project, using the newest snapshot
stack new <project name> <template name>
# Create a project in the current directory
stack new <project name> <template name> --bare
stack new
creates a directory and populates it with a template from GitHub. Some templates: commercialhaskell/stack-templates.
If you don't know what template to use, try simple-hpack
– it creates a BSD-3 licensed executable with a package.yaml
file.
It's best to use as few different resolvers as possible to save space on your hard drive. Pick a snapshot you like and then pass it with --resolver=lts-XX.YY
. Existing snapshots and GHC versions are cached in ~/.stack
.
To use a dependency that is available in the snapshot, add it to your .cabal
or package.yaml
file. Snapshot contents, including the exact package versions, are listed at https://www.stackage.org/lts-XX.YY
.
library -- In a .cabal file
build-depends:
aeson
library: # In a package.yaml file
dependencies:
- aeson
To use a dependency that is not in the snapshot, you also need to add it to extra-deps
in stack.yaml
:
extra-deps:
# From Hackage
- amazonka-core-1.6.0
# From a Git / Mercurial repo (add "subdirs" if you want only certain
# directories from the repo):
- git: https://github.com/brendanhay/amazonka
commit: 9750d3d0bf4a079831c20efeb9ef372759895b48
subdirs:
- core
# From a directory
- ./amazonka/core
# From an archive accessible by a URL (add "subdirs" if you want only
# certain directories from the archive):
- archive: https://github.com/brendanhay/amazonka/archive/1.6.0.tar.gz
subdirs:
- core
(Note: if a package isn't on Stackage, you can add it there, though it works better when you're the actual package maintainer for that package.)
# Run all tests
stack test --fast
# Run only certain tests (hspec)
stack test --fast --ta="-m <test name pattern>"
# Run only certain tests (tasty)
stack test --fast --ta="-p <test name pattern>"
- Tasty pattern documentation: https://documentup.com/feuerbach/tasty#patterns
- Hspec pattern documentation: https://hspec.github.io/match.html
It's also possible to pass any other arguments to the testsuite with --ta
. Try --ta=--help
to see what arguments are supported by the test framework you're using.
If you suspect that an executable is not being rebuilt, or if something is wrong with dependency versions, etc:
# Remove build artifacts for all packages in the project
stack clean
# Remove build artifacts for a specific package
stack clean <package>
# Remove build artifacts and everything from .stack-work
stack clean --full
If a dependency is broken and you're getting weird creepy errors you haven't ever seen before:
# Remove a package from the local package database
stack exec -- ghc-pkg unregister <package>
If you're really, truly desperate and you've tried everything else (including setting your hair on fire):
# An exciting journey of rebuilding hundreds of packages awaits you
rm -rf ~/.stack
# List all dependencies, transitively
stack ls dependencies
# List test/bench dependencies too
stack ls dependencies --test --bench
# List licenses of all dependencies (useful for detecting scary GPL)
stack ls dependencies --license
# List all dependency pairs (useful for figuring out what brings
# a particular dependency in)
stack dot --external
# Build documentation
stack haddock --no-haddock-deps
# Build documentation for all dependencies, too (might take a long time
# if they all need to be recompiled)
stack haddock
# Open generated docs in a browser
stack haddock --open
# Start a custom Hoogle server that knows all your local packages.
# Great for looking up documentation while offline. Server is located
# at http://localhost:8080/
stack hoogle -- serve -p 8080 --local
Nix package manager can be used to install GHC and packages.
Normally, this can speed up the compilation of packages and avoids duplicate installations of identical packages.
To enable nix support, add to your stack.yaml
:
nix:
enable: true
However, this is generally not suggested, because this will automatically use nix on systems that might not have it installed, thus, the build fails.
It is better to add the above lines to your yaml config template: ~/.stack/config.yaml
.
Nix automatically handles system library dependencies. Such dependencies can be added by modifying your local stack.yaml
, for example, if you require zlib
, you do:
nix:
packages:
- zlib
This will allow you to build projects without modifying your global system.
# stack.yaml
docker:
enable: true
# Download the image
stack docker pull
# And then build as usual!
stack build --fast
Stack can automatically download a Docker image with GHC and snapshot libraries installed, and build your project inside of it.
TODO: docs say "FP Complete provides images for use with stack that include GHC, tools, and optionally have all of the Stackage LTS packages pre-installed in the global package database", but the image chosen by Stack doesn't have any LTS packages pre-installed. How come?
When there's no stack.yaml
in the current directory or up the path, the global project will be used.
stack install
installs a library/executable into the global project, and stack repl
can access everything in the global project.
Global project settings can be changed:
# ~/.stack/global-project/stack.yaml
packages: []
resolver: lts-12.10