I am on NixOS but I think this question should apply to any platform that use nix.
I found by trial that stack can be used with couple options to build a project but I don't fully understand difference among them,
stackstack --system-ghcstack --nix
Question :
- If I am using nix (NixOS in my case), is there any reason I will want to not use
--nixargument? - What is the
nixway to deal with haskell project, shouldcabal(cabal2nix) be used in stead ofstack? - I found that stack is rebuilding lots of libraries that already installed by
nix, what is the reason of that?
As I understand it, the
--nixoption to stack uses anix-shellto manage non-Haskell dependencies (instead of requiring them to be in the "global" environment that stack is run from). This is probably a good idea if you want to use thestacktool on nix. Stack also usually installs its own GHC: the--system-ghcoption prevents this, and asks it to use the GHC in the "global" environment from which it is run. I believe that with--nix,stackwill ask Nix to handle GHC versioning as well, so on a Nix system, I would recommend building with--nixand without--system-ghcAt least in my opinion, it is better to avoid the stack tooling when working with Nix. This is because stack, even when run with
--nix, does not inform Nix about the Haskell packages that it wants to build: it builds them all itself inside~/.stack, and doesn't share them with the Nix store. If your project builds with the latestnixpkgsversions of Haskell packages, or with relatively few simple overrides on those,cabal2nixis a great solution that will make sure that Haskell libraries only get built once (by Nix). If you want to make sure that you are building your project with the same package versions asstackwould, I would recommend stackage2nix or stack2nix. I personally have been using the nixpkgs-stackage overlay, which is related tostackage2nix: this gives you both LTS package sets in nixpkgs, andnixpkgs.haskell.packages.stackage.lib.callStackage2nix, which you can use in yourdefault.nix/shell.nixlike so:callStackage2nix (baseNameOf ./.) (cleanSource ./.).${(baseNameOf ./.)}, with whatever definition ofcleanSourcefits your project (this can usefilterSourceto remove some files which shouldn't really be considered part of the project, like autosaves, build directories, etc.).With this setup, instead of using the
stacktooling, for interactive work on the project you should usenix-shellto set up an environment where Nix has built all of the dependencies of your project and "installed" them. Then you can just usecabal-installto build just your project, without any dependency issues or (re)building dependencies.As mentioned above,
stackdoes not coordinate with Nix, and tries to build every Haskell dependency itself in~/.stack. If you want to keep all of your Haskell packages in the Nix store (which I would recommend) while following the same build plans as Stack, you will need to use one of the linked tools, or something similar.