Nix integration

(since 0.1.10.0)

stack can build automatically inside a nix-shell (the equivalent of a “container” in Docker parlance), provided Nix is already installed on your system. To do so, please visit the Nix download page.

There are two ways to create a nix-shell:

  • providing a list of packages (by “attribute name”) from Nixpkgs, or
  • providing a custom shell.nix file containing a Nix expression that determines a derivation, i.e. a specification of what resources are available inside the shell.

The second requires writing code in Nix’s custom language. So use this option only if you already know Nix and have special requirements, such as using custom Nix packages that override the standard ones or using system libraries with special requirements.

Additions to your stack.yaml

Add a section to your stack.yaml as follows:

nix:
  enable: true
  packages: [glpk, pcre]

This will instruct stack to build inside a nix-shell that will have the glpk and pcre libraries installed and available. Further, the nix-shell will implicitly also include a version of GHC matching the configured resolver. Enabling Nix support means packages will always be built using a GHC available inside the shell, rather than your globally installed one if any.

Note also that this also means that you cannot set your resolver: to something that has not yet been mirrored in the Nixpkgs package repository. In order to check this, the quickest way is to install and launch a nix-repl:

$ nix-channel --update
$ nix-env -i nix-repl
$ nix-repl

Then, inside the nix-repl, do:

nix-repl> :l <nixpkgs>
nix-repl> haskell.packages.lts-3_13.ghc

Replace the resolver version with whatever version you are using. If it outputs a path of a derivation in the Nix store, like

«derivation /nix/store/00xx8y0p3r0dqyq2frq277yr1ldqzzg0-ghc-7.10.2.drv»

then it means that this resolver has been mirrored and exists in your local copy of the nixpkgs. Whereas an error like

error: attribute ‘lts-3_99’ missing, at (string):1:1

means you should use a different resolver. You can also use autocompletion with TAB to know which attributes haskell.packages contains.

In Nixpkgs master branch, you can find the mirrored resolvers in the Haskell modules here on Github.

Note: currently, stack only discovers dynamic and static libraries in the lib/ folder of any nix package, and likewise header files in the include/ folder. If you’re dealing with a package that doesn’t follow this standard layout, you’ll have to deal with that using a custom shell file (see below).

Use stack as normal

With Nix enabled, stack build and stack exec will automatically launch themselves in a nix-shell. Note that for now stack ghci will not work, due to a bug in GHCi when working with external shared libraries.

If enable: is set to false, you can still build in a nix-shell by passing the --nix flag to stack, for instance stack --nix build. Nix just won’t be used by default.

Command-line options

The configuration present in your stack.yaml can be overriden on the command-line. See stack --nix-help for a list of all Nix options.

Configuration

stack.yaml contains a nix: section with Nix settings. Without this section, Nix will not be used.

Here is a commented configuration file, showing the default values:

nix:

  # `true` by default when the nix section is present. Set
  # it to `false` to disable using Nix.
  enable: true

  # Empty by default. The list of packages you want to be
  # available in the nix-shell at build time (with `stack
  # build`) and run time (with `stack exec`).
  packages: []

  # Unset by default. You cannot set this option if `packages:`
  # is already present and not empty, this will result in an
  # exception
  shell-file: shell.nix

  # A list of strings, empty by default. Additional options that
  # will be passed verbatim to the `nix-shell` command.
  nix-shell-options: []

Using a custom shell.nix file

Nix is also a programming language, and as specified here if you know it you can provide to the shell a fully customized derivation as an environment to use. Here is the equivalent of the configuration used in this section, but with an explicit shell.nix file:

with (import <nixpkgs> {});

stdenv.mkDerivation {

  name = "myEnv";
  
  buildInputs = [
    glpk 
    pcre 
    haskell.packages.lts-3_13.ghc
  ];
  
  STACK_IN_NIX_EXTRA_ARGS
      = " --extra-lib-dirs=${glpk}/lib" 
      + " --extra-include-dirs=${glpk}/include" 
      + " --extra-lib-dirs=${pcre}/lib" 
      + " --extra-include-dirs=${pcre}/include"
  ;
}

Note that in this case, you have to include (a version of) GHC in your buildInputs! This potentially allows you to use a GHC which is not the one of your resolver:. Also, you need to tell Stack where to find the new libraries and headers. This is especially necessary on OS X. The special variable STACK_IN_NIX_EXTRA_ARGS will be looked for by the nix-shell when running the inner stack process. --extra-lib-dirs and --extra-include-dirs are regular stack build options. You can repeat these options for each dependency.

Defining manually a shell.nix file gives you the possibility to override some Nix derivations (“packages”), for instance to change some build options of the libraries you use.

And now for the stack.yaml file:

nix:
  enable: true
  shell-file: shell.nix

The stack build command will behave exactly the same as above. Note that specifying both packages: and a shell-file: results in an error. (Comment one out before adding the other.)