2022-12-20
This is the second post in a series about stacklock2nix. The previous post is about building PureScript with stacklock2nix. The next post is about building Pandoc with stacklock2nix.
This post uses stacklock2nix to build Dhall and all its tools with Nix. The Dhall project is a good example for stacklock2nix, since it is comprised of quite a few different Haskell packages.
The following commit adds some Nix code to the Dhall repo that can be used to build with Nix1:
https://github.com/cdepillabout/dhall-haskell/commit/e1a7c31d68ad2da9c748dddcca01668da0ca53d6
The most interesting file in this commit is nix/overlay.nix. This is the file I recommend taking a look at to get a feel for using stacklock2nix. This newly-added Nix code is based on the advanced example of stacklock2nix. This post explains how to use this newly-added Nix code.
What can you do with this?
First, clone the above repo locally with the following commands:
$ git clone git@github.com:cdepillabout/dhall-haskell.git
$ cd dhall-haskell/
$ git checkout build-with-stacklock2nix
$ git submodule update --init
From here, you can use the flake.nix file to build the Dhall tools:
$ nix build -L
After building, all the Dhall tools should be available:
$ ls result/bin/
csv-to-dhall
dhall
dhall-docs
dhall-lsp-server
dhall-to-bash
dhall-to-csv
dhall-to-json
dhall-to-nix
...
You can also use the default.nix file with nix-build:
$ nix-build
You can use nix develop to jump into a development shell that has tools like cabal-install and HLS available:
$ nix develop -L
Or you could do the same thing with nix-shell:
$ nix-shell
From here, you can build all the Dhall tools with cabal:
$ cabal build all
...
$ cabal run dhall -- --version
1.41.2
You can also use other normal commands like cabal test, cabal repl, etc.
The repo is also setup to be able to build with stack2:
$ stack --nix build
And run tests:
$ stack --nix test
Conclusion
Dhall is a non-trivial, multi-package Haskell project. Building it with stacklock2nix is relatively straight-forward. A few Nix overrides are necessary for getting everything to build. As long as you have a stack.yaml and stack.yaml.lock file, stacklock2nix makes it easy to build a Haskell project with Nix. Even a large, multi-package Haskell project.
The Haskell dependency versions are controlled by the stack.yaml file. Bumping the Stackage resolver in stack.yaml is all that is needed to build with newer Haskell dependencies. This is much easier than manually keeping dependencies in sync between Haskell and Nix.
Footnotes
Dhall actually already has a nice infrastructure for building with Nix. In practice, this existing infrastructure should be used instead of
stacklock2nix. The commit from this blog post is purely to show howstacklock2nixcould be used on a non-trivial Haskell project. (There is also a parent commit that deletes all the existing Nix infrastructure in the Dhall repo, just to make everything a little easier to understand.)↩︎Note that
stackinternally runsnix-shell, so you can runstackoutside ofnix-shell. That is to say, you don't have to be insidenix-shellbefore you run any of thestackcommands.↩︎