使用 nix 时不使用 stack --nix 的原因是什么?

What is reason not to use stack --nix when I using nix?

我在 NixOS 但我认为这个问题应该适用于任何使用 nix.

的平台

我通过试验发现stack可以与几个选项一起使用来构建一个项目,但我不完全理解它们之间的区别,

  1. stack
  2. stack --system-ghc
  3. stack --nix

问题

  1. 如果我使用的是 nix(在我的例子中是 NixOS),我有什么理由不想使用 --nix 参数吗?
  2. 处理haskell项目的nix方法是什么,应该用cabal(cabal2nix)代替stack吗?
  3. 我发现堆栈正在重建许多 nix 已经安装的库,这是什么原因?
  1. 据我了解,堆栈的--nix选项使用nix-shell来管理非Haskell依赖项(而不是要求它们处于堆栈 运行 来自的“全局”环境中)。如果您想在 nix 上使用 stack 工具,这可能是个好主意。 Stack 通常还会安装自己的 GHC:--system-ghc 选项会阻止这种情况,并要求它在 运行 所在的“全局”环境中使用 GHC。我相信使用 --nixstack 也会要求 Nix 处理 GHC 版本控制,所以在 Nix 系统上,我建议使用 --nix 构建而不使用 --system-ghc

  2. 至少在我看来,在使用 Nix 时最好避免堆栈工具。这是因为堆栈,即使 运行 和 --nix,也不会通知 Nix 它想要构建的 Haskell 包:它在 ~/.stack 中自行构建它们,并且不与 Nix 商店共享它们。如果您的项目使用 Haskell 包的最新 nixpkgs 版本构建,或者对这些包进行相对较少的简单覆盖,cabal2nix 是一个很好的解决方案,可以确保 Haskell 库只构建一次(由 Nix)。如果你想确保你正在使用与 stack 相同的包版本构建你的项目,我会推荐 stackage2nix or stack2nix. I personally have been using the nixpkgs-stackage overlay,它与 stackage2nix 相关:这为你提供了 LTS nixpkgs 和 nixpkgs.haskell.packages.stackage.lib.callStackage2nix 中的软件包集,您可以像这样在 default.nix/shell.nix 中使用它们:callStackage2nix (baseNameOf ./.) (cleanSource ./.).${(baseNameOf ./.)},无论 cleanSource 的定义是否适合您的项目(这可以使用 filterSource 删除一些不应该真正被视为项目一部分的文件,如自动保存、构建目录等)。

    使用此设置,而不是使用 stack 工具,对于项目的交互式工作,您应该使用 nix-shell 来设置一个环境,Nix 已经在其中构建了项目的所有依赖项并“安装”它们。然后你可以只使用 cabal-install 来构建你的项目,没有任何依赖性问题或(重新)构建依赖性。

  3. 如上所述,stack 不与 Nix 协调,并试图在 ~/.stack 中构建每个 Haskell 依赖本身。如果您想将所有 Haskell 包保留在 Nix 商店(我会推荐),同时遵循与 Stack 相同的构建计划,您将需要使用其中一种链接工具或类似工具。