commercialhaskell / stack

The Haskell Tool Stack
http://haskellstack.org
BSD 3-Clause "New" or "Revised" License
3.95k stars 842 forks source link

Project builds using Nix with `add-gc-roots: true` fail due to removal of nix-shell `--add-root` option #6329

Open traleig1 opened 8 months ago

traleig1 commented 8 months ago

General summary

Attempting to build projects using Nix on NixOS while add-gc-roots is enabled produces the following, as also described in https://github.com/haskell/cabal/issues/9146:

> stack build --copy-bins
error: unrecognised flag '--add-root'

Workaround is to add add-gc-roots: false to stack.yaml.

Steps to reproduce

flake.lock:

{
  "nodes": {
    "flake-utils": {
      "inputs": { "systems": "systems" },
      "locked": {
        "lastModified": 1694529238,
        "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
        "owner": "numtide",
        "repo": "flake-utils",
        "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
        "type": "github"
      },
      "original": { "owner": "numtide", "repo": "flake-utils", "type": "github" }
    },
    "nixpkgs": {
      "locked": {
        "lastModified": 1699078251,
        "narHash": "sha256-IjYIDgNC5PWWWTxRiE+DXw+B18+q4iBzuRkcflBMSFU=",
        "owner": "NixOS",
        "repo": "nixpkgs",
        "rev": "880c206efc49f624b12270564a2c9f041c0af3c7",
        "type": "github"
      },
      "original": { "owner": "NixOS", "repo": "nixpkgs", "type": "github" }
    },
    "root": { "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } },
    "systems": {
      "locked": {
        "lastModified": 1681028828,
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
        "owner": "nix-systems",
        "repo": "default",
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
        "type": "github"
      },
      "original": { "owner": "nix-systems", "repo": "default", "type": "github" }
    }
  },
  "root": "root",
  "version": 7
}

flake.nix:

{
  description = "";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };
  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        packageName = "xmonad-x86_64-linux";
        pkgs = nixpkgs.legacyPackages.${system};
        haskellPackages = pkgs.haskell.packages.ghc924;
      in {
        packages.${packageName} = haskellPackages.callCabal2nix packageName self { };
        defaultPackage = self.packages.${system}.${packageName};
        devShell = pkgs.mkShell {
          buildInputs = with pkgs; [ haskellPackages.ghcid haskellPackages.cabal-install haskellPackages.hpack ];
          inputsFrom = builtins.attrValues self.packages.${system};
        };
      });
}

~/.stack/config.yaml:

templates:
  params:

nix:
  enable: true
  pure: true
  add-gc-roots: true

stack.yaml

resolver: lts-19.33

packages:
- .

flags: {}

extra-package-dbs: []

local-bin-path: .

nix:
  pure: true

Expected

Stack should begin attempting to build.

Actual

Stack immediately fails. Running with --verbose:

> stack build --copy-bins --verbose
2.13.1 x86_64 hpack-0.36.0
2023-11-04 21:56:59.724929: [debug] Checking for project config at: ~/.xmonad/stack.yaml
2023-11-04 21:56:59.725236: [debug] Loading project config file stack.yaml
2023-11-04 21:56:59.726274: [debug] Use of Casa server enabled: (CasaRepoPrefix "https://casa.stackage.org", 1280).
2023-11-04 21:56:59.727539: [debug] (SQL) SELECT COUNT(*) FROM "last_performed" WHERE ("action"=?) AND ("timestamp">=?); [PersistInt64 1,PersistUTCTime 2023-11-04 04:56:59.727511518 UTC]
2023-11-04 21:56:59.727758: [debug] Using package location completions from a lock file
2023-11-04 21:56:59.728866: [debug] Loaded snapshot from Pantry database.
2023-11-04 21:56:59.843789: [debug] Running Hpack on ~/.xmonad/package.yaml
2023-11-04 21:56:59.844605: [debug] Hpack output unchanged in ~/.xmonad/my-xmonad.cabal
2023-11-04 21:56:59.844762: [debug] Prefetching git repos: []
2023-11-04 21:56:59.844790: [debug] []
2023-11-04 21:56:59.846384: [debug] PATH is: Just "/run/wrappers/bin:~/.nix-profile/bin:/nix/profile/bin:~/.local/state/nix/profile/bin:/etc/profiles/per-user/<username>/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin"
2023-11-04 21:56:59.846434: [debug] Using a nix-shell environment with nix packages: zlib, haskell.compiler.ghc902, git, gcc, gmp
2023-11-04 21:56:59.846533: [debug] Run process: /run/current-system/sw/bin/nix-shell --pure --indirect --add-root .stack-work/nix-gc-symlinks/gc-root -E "with (import <nixpkgs> {}); let inputs = [zlib haskell.compiler.ghc902 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/piivb1xmf2jnsd90zrb37z40ypf84mvw-stack-2.13.1/bin/stack' $STACK_IN_NIX_EXTRA_ARGS '--internal-re-exec-version=2.13.1' 'build' '--copy-bins' '--verbose'"
error: unrecognised flag '--add-root'
Try '/run/current-system/sw/bin/nix-shell --help' for more information.

Running via nix develop produces roughly the same, just with a much longer $PATH.

Stack version

> stack --version
2.13.1 x86_64 hpack-0.36.0

Method of installation

Platform

> nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.5.9, NixOS, 23.11 (Tapir), 23.11.20231026.63678e9`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.17.1`
 - channels(root): `"nixos"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
mpilgrem commented 8 months ago

@traleig1, thanks for reporting. While I try to work out what is going on, I note that the default value for add-gc-roots is false (https://docs.haskellstack.org/en/stable/yaml_configuration/#nix), so this will only affect people who have expressly set add-gc-roots: true. There is also some documentation at: https://docs.haskellstack.org/en/stable/nix_integration/#non-project-specific-configuration.

Its effect is at Stack.Nix.runShellAndExit:

        fullArgs = concat
          [ [ "--pure" | pureShell ]
          , if addGCRoots -- <<<< True if add-gc-roots is true
              then [ "--indirect"
                   , "--add-root"
                   , toFilePath
                             (configWorkDir config)
                       F.</> "nix-gc-symlinks"
                       F.</> "gc-root"
                   ]
              else []
          , map T.unpack (nixShellOptions (configNix config))
          , nixopts
          , ["--run", unwords (cmnd:"$STACK_IN_NIX_EXTRA_ARGS":args')]
            -- Using --run instead of --command so we cannot end up in the
            -- nix-shell if stack build is Ctrl-C'd
          ]
...
    exec "nix-shell" fullArgs
mpilgrem commented 8 months ago

Re --add-root:

@traleig1, I am not a Nix user. Should I understand from the above links that it is nix-store (and not nix-shell) that should be run with the --add-root option?

traleig1 commented 8 months ago

I note that the default value for add-gc-roots is false

Yes - I initially hadn't realized that I had it set in my ~/.stack/config.yaml, so went back and edited the issue to clarify that.

Should I understand from the above links that it is nix-store (and not nix-shell) that should be run with the --add-root option?

I'm not sure; I've never had a need to work with the nix-store command directly - the usual workflow is to just use nix-build to package things up, and that handles copying to the nix store via nix-store/nix-instantiate under the hood. Here it looks like stack already has the .stack-work/nix-gc-symlinks/gc-root directory ready, and it's adding the gc roots when it creates the environment it runs in via nix-shell. Seems to me like it could probably be done by calling nix-store separately/explicitly, but I'm definitely out of my league here.

Judging from the documentation for nix-shell it looks like the intention is for nix-shell to pass extra flags down to nix-store itself, which would imply that it should work as-is. I'm struggling to find evidence of support for the flag being explicitly removed, so unless the documentation is out of date, it's possible this is a bug on their end.

mpilgrem commented 8 months ago

@traleig1, 'bug at their end' is also my current hypothesis. I'll raise an issue there.