Using stack on NixOS

I’ve got myself a new laptop recently and decided to try NixOS. It’s
been a great experience so far, but there are some rough edges. One
of them is stack not completely working out of the box for my
projects.

The reason is that some Haskell packages depend on system C libraries,
but neither stack nor Cabal-the-library are able to find them on
NixOS. As an example, you won’t find /usr/lib/libz.so on my system.
Instead, right now it’s at
/nix/store/2zmlykvqx69q5bh1l3jqyhrj2493vqdx-zlib-1.2.8/lib/libz.so.

Being a NixOS newbie, I’ve tried some solutions but none of them
worked. I’ve then asked for Peter Simon’s help, which he gladly and
swiftly provided (thanks, Peter!). For my use case, I’ve adapted his
suggestions into the following script:

#!/usr/bin/env bash
ZLIB="$(nix-build --no-out-link "<nixpkgs>" -A zlib)"
PSQL="$(nix-build --no-out-link "<nixpkgs>" -A postgresql)"
exec stack                                                             \
     --extra-lib-dirs=${ZLIB}/lib --extra-include-dirs=${ZLIB}/include \
     --extra-lib-dirs=${PSQL}/lib --extra-include-dirs=${PSQL}/include \
     $*

My transitive dependencies need zlib and postgresql libraries, so I
use nix-build to find out where these packages are and pass their
directories to stack explicitly.

This solution is not without drawbacks. The biggest one is that your
built Haskell libraries will be hardcoded to these C libraries, but
NixOS doesn’t know anything about this dependency. If you upgrade
your system and garbage collect the old C libraries, you’ll have to
recompile the Haskell libraries (probably with rm -R
~/.stack/snapshots). However, I quite like its conciseness, and one
doesn’t need to understand much about NixOS’s internals to use it.

At the moment this hack is serving me well. If you’re reading this
blog post more than a couple of months after I wrote it, take a look
around to see if a better solution has been developed in the mean time :).

5 thoughts on “Using stack on NixOS”

  1. Instead of –no-out-link you can –out-link zlib and –out-link postgresql, and they will not be garbage collected until you delete the symlinks.

    1. Luca, what would happen if the system’s zlib was upgraded and the nix-build command was executed again? Wouldn’t it return the new zlib’s path and overwrite the zlib symlink created by the previous –out-link?

    1. Hmmm… Well, I guess I prefer just having to be careful about Nix garbage collections (which don’t have to be frequent anyway, thanks to nix-store –optimize) and not having to worry about when nix-build was safe to be used again. But thanks a lot for your suggestion! 🙂

Leave a Reply to Dwi Bayu Ramadhan Cancel reply

Your email address will not be published. Required fields are marked *