When I build by stack project under nixos, it re-downloads GHC every time I do garbage collection.
$ git clone [email protected]:turion/rhine.git
[...]
$ cd rhine/rhine
$ git checkout stack_nix_gc_roots_bug
[...]
$ cat stack.yaml
resolver: lts-12.26
nix:
enable: true
add-gc-roots: true
$ stack build
[...]
$ find . -name "*gc*"
$ nix-collect-garbage
finding garbage collector roots...
deleting garbage...
deleting '/nix/store/d9syi687jirk386a9hgr96yqhw6mx243-ghc-8.4.4'
deleting '/nix/store/s7p0wfbdfbq307zgifhnh6w8sfjvy64y-patchelf-0.9'
deleting '/nix/store/4r7rxlb5ingbcwr57aziswmyscpbgjj7-ghc-8.4.4-doc'
deleting '/nix/store/9z1b1ldrhxh7brsi6fxnyjm7gk8kiynv-bash-interactive-4.4-p23-dev'
deleting '/nix/store/c3kwd2jyv11ng84lrxgs3pfascl9bwr2-ghc-8.4.4-src.tar.xz.drv'
deleting '/nix/store/trash'
deleting unused links...
note: currently hard linking saves -0.00 MiB
5 store paths deleted, 1549.44 MiB freed
$ stack build
these paths will be fetched (114.69 MiB download, 1535.52 MiB unpacked):
/nix/store/4r7rxlb5ingbcwr57aziswmyscpbgjj7-ghc-8.4.4-doc
/nix/store/9z1b1ldrhxh7brsi6fxnyjm7gk8kiynv-bash-interactive-4.4-p23-dev
/nix/store/d9syi687jirk386a9hgr96yqhw6mx243-ghc-8.4.4
/nix/store/s7p0wfbdfbq307zgifhnh6w8sfjvy64y-patchelf-0.9
/nix/store/y83grpq99ssdd3n53q9zfid8slxrankg-stdenv-linux
copying path '/nix/store/9z1b1ldrhxh7brsi6fxnyjm7gk8kiynv-bash-interactive-4.4-p23-dev' from 'https://cache.nixos.org'...
copying path '/nix/store/s7p0wfbdfbq307zgifhnh6w8sfjvy64y-patchelf-0.9' from 'https://cache.nixos.org'...
copying path '/nix/store/4r7rxlb5ingbcwr57aziswmyscpbgjj7-ghc-8.4.4-doc' from 'https://cache.nixos.org'...
copying path '/nix/store/y83grpq99ssdd3n53q9zfid8slxrankg-stdenv-linux' from 'https://cache.nixos.org'...
copying path '/nix/store/d9syi687jirk386a9hgr96yqhw6mx243-ghc-8.4.4' from 'https://cache.nixos.org'...
I use nixos-unstable.
$ stack --version
1.9.3 x86_64 hpack-0.31.2
I also tried adding the option in the global ~/.stack/config.yaml, but that didn't help either.
stack build --nix-add-gc-roots doesn't work either.
At first I thought this might've been a case of confusing documentation since we specify "packages" as being nix-add-gc-roots's target:
$ stack --nix-help
Usage: stack [--[no-]nix] [--[no-]nix-pure] [--nix-packages NAMES]
[--nix-shell-file FILE] [--nix-shell-options OPTIONS]
[--nix-path PATH_OPTIONS] [--[no-]nix-add-gc-roots] OTHER ARGUMENTS
Only showing --nix* options.
Available options:
--[no-]nix Enable/disable use of a Nix-shell. Implies
'system-ghc: true'
--[no-]nix-pure Enable/disable use of a pure Nix-shell. Implies
'--nix' and 'system-ghc: true'
--nix-packages NAMES List of packages that should be available in the
nix-shell (space separated)
--nix-shell-file FILE Nix file to be used to launch a nix-shell (for
regular Nix users)
--nix-shell-options OPTIONS
Additional options passed to nix-shell
--nix-path PATH_OPTIONS Additional options to override NIX_PATH parts
(notably 'nixpkgs')
--[no-]nix-add-gc-roots Enable/disable addition of packages to the nix GC
roots so nix-collect-garbage doesn't remove them
So I expected transformers to survive garbage collection (since that's listed in your build-depends stanza) and not ghc, but when I tried it looked like neither were spared.
$ stack --version
Version 1.9.3, Git revision 40cf7b37526b86d1676da82167ea8758a854953b (6211 commits) x86_64 hpack-0.31.1
$ nix --version
nix (Nix) 2.1.3
(On Debian testing)
I'm by no-means a nix expert so it could be I've missed something, but this seems like a bug to me too.
Thanks for the detailed steps to reproduce and well-spotted @turion!
It seems to happen in NixOS 19.09 as well. Anyone any idea why/how?
I get the same behavior on Ubuntu Linux with Stack 2.1.3.1. I set add-gc-roots: true but no nix-gc-symlinks directory is created.
Poked around a bit: stack is passing --add-root to nix-shell correctly, but the option is ignored. This is being tracked as nixos/nix#1982.
In this comment @lheckemann mentions that a possible workaround is to run a command like nix-store -r /nix/store/$hash-$name --add-root ./root-name --indirect to manually create a Nix GC root. In Stack鈥檚 case, I鈥檓 not sure how you鈥檇 figure out which $hash-$name to use. When I run Stack with --verbose, I can see that its nix-shell invocation looks like
Run process: /Users/bdesham/.nix-profile/bin/nix-shell --pure --indirect --add-root .stack-work/nix-gc-symlinks/gc-root -E "with (import <nixpkgs> {}); let inputs = [pcre pkg-config zlib haskell.compiler.ghc865 git gcc gmp]; libPath = lib.makeLibraryPath inputs; stackExtraArgs = lib.concatMap (pkg: [ ''--extra-lib-dirs=${lib.getLib pkg}/lib'' ''--extra-include-dirs=${lib.getDev pkg}/include'' ]) inputs; in runCommand ''myEnv'' { buildInputs = lib.optional stdenv.isLinux glibcLocales ++ inputs; STACK_PLATFORM_VARIANT=''nix''; STACK_IN_NIX_SHELL=1; LD_LIBRARY_PATH = libPath;STACK_IN_NIX_EXTRA_ARGS = stackExtraArgs; LANG=\"en_US.UTF-8\";} \"\"" --run "'/nix/store/hs881lhlv0c86a7bvvx8r04yv7a9jkh7-stack-2.1.3.1/bin/stack' $STACK_IN_NIX_EXTRA_ARGS '--internal-re-exec-version=2.1.3.1' '--verbose' 'build'"
This nixpkgs issue suggests that it should be possible to create a GC root by moving the shell creation information into a shell.nix file, calling nix-instantiate on that file (and asking that tool to create a GC root), and then calling nix-shell on the file to actually run the shell. This might be a workaround for Stack, although (1) I鈥檓 not sure whether this technique will create a GC root either; (2) it seems like it would require nontrivial changes to Stack鈥檚 Nix integration; and (3) there is some problem with doing this, as evidenced by the fact that that nixpkgs issue is still open.
Maybe a lighter-weight workaround would be for Stack to call nix-shell in such a way that the shell鈥檚 store path is displayed. Then it should be possible to feed that path to nix-store -r.
Note that this is due to https://github.com/NixOS/nix/issues/2208
Stack could do something like:
nix-instantiate shell.nix --show-trace --indirect --add-root "$(pwd)/"shell.drv
nix-shell $(readlink $(pwd)/shell.drv)