能否让Haskell的stack工具使用nix提供的Haskell软件包?
问题原因与解决方案
1. 找不到alex等工具的原因
你当前自定义的shell.nix使用了普通的stdenv.mkDerivation,但你写的libraryHaskellDepends、libraryToolDepends这类字段是Nix的Haskell生态专属的haskellPackages.mkDerivation才会识别的参数,普通的stdenv构建会直接忽略这些字段,因此你声明的构建工具根本没有被加入到shell环境中,stack调用自然找不到。
2. 直接使用nixpkgs提供的Haskell依赖的配置方法
stack的nix集成原生支持直接拉取nixpkgs里的Haskell库,不需要你手动在shell.nix里逐个声明所有依赖,两种常用配置方案如下:
方式一:不自定义shell.nix,直接通过stack.yaml配置(最简便)
直接修改你的stack.yaml的nix配置块即可:
nix: enable: true # 启用nixpkgs作为依赖源 use-nixpkgs: true # 可替换为具体的nixpkgs commit哈希锁定版本,保证构建可复现 path: <nixpkgs> # 额外需要的构建工具、非Haskell依赖直接在此处声明 packages: - haskellPackages.alex - haskellPackages.happy - haskellPackages.BNFC - haskellPackages.hpack
配置完成后执行stack build,stack会自动从nixpkgs拉取所有符合版本要求的Haskell依赖,不会额外从stackage下载编译,同时你需要的构建工具也会被自动加入环境。
方式二:保留自定义shell.nix的修正方案
如果你确实需要自定义shell.nix(比如后续要添加复杂的非Haskell依赖),可以把shell.nix改成使用mkShell的简化版本,不需要写无效的Haskell专属字段:
with (import <nixpkgs> {}); mkShell { name = "simple-dev-env"; buildInputs = [ ghc haskellPackages.alex haskellPackages.happy haskellPackages.BNFC haskellPackages.hpack ]; }
然后保持你的stack.yaml原有nix配置不变,同时新增use-nixpkgs: true字段即可,stack会自动识别nixpkgs中的Haskell库版本,优先使用nix提供的依赖。
补充说明
如果nixpkgs中的某个依赖版本不满足你的项目要求,stack会自动回退到从stackage下载对应版本编译,不会影响正常构建流程,完全符合「优先使用nixpkgs依赖」的需求。
内容的提问来源于stack exchange,提问作者Jonathan Gallagher

