如何用Nix构建Stack/Cabal Haskell包可执行文件及环境配置?
用Nix构建Stack/Cabal Haskell项目可执行文件的方案
首先明确两种核心思路:用Nixpkgs预编译包快速搭环境,或者从源码(GitHub/Hackage/Stackage)自定义构建,下面分别说明:
一、优先用Nixpkgs预编译包(简单高效)
如果你的依赖和工具都已经在Nixpkgs的Haskell包集合里,直接用pkgs.haskellPackages.<package>是最省心的——Nix会帮你搞定预编译二进制包,启动速度快,不用自己编译整个依赖链。
你可以把shell.nix改成这样:
{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell { name = "haskell-dev-env"; buildInputs = with pkgs; [ # Haskell基础开发工具 ghc ghcid cabal-install stack # 性能分析工具:threadscope属于Haskell包,speedscope是独立工具 haskellPackages.threadscope speedscope ]; }
使用起来和你预期的完全一致:
# 进入Nix环境 nix-shell # 直接运行工具 threadscope your-program.eventlog speedscope your-profile.json
二、从源码自定义构建(灵活定制)
如果你的项目依赖未收录到Nixpkgs的包、需要用GitHub分支版本,或者要修改包的源码,就需要手动指定源码构建逻辑。
针对Cabal项目
- 先为你的项目生成专属Nix表达式:
cabal2nix . > my-project.nix
- 在shell.nix里引用这个表达式,还能自定义依赖版本:
{ pkgs ? import <nixpkgs> {} }: let # 引入自己的Cabal项目 myProject = pkgs.callPackage ./my-project.nix {}; # 示例:从GitHub源码构建一个自定义依赖 customDependency = pkgs.haskellPackages.callPackage ({ mkDerivation, base, text }: mkDerivation { pname = "custom-dep"; version = "0.2.0.0"; src = pkgs.fetchFromGitHub { owner = "your-username"; repo = "custom-dep-repo"; rev = "a1b2c3d"; # 你需要的分支/commit哈希 sha256 = "sha256-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; # 运行nix-shell会提示你补全正确哈希 }; buildDepends = [ base text ]; } ) {}; in pkgs.mkShell { name = "my-project-dev-env"; buildInputs = with pkgs; [ ghc ghcid cabal-install threadscope speedscope myProject # 把项目加入环境,直接运行编译好的可执行文件 ]; # 覆盖默认依赖,让项目使用我们自定义的customDependency overrides = pkgs.haskell.lib.override { overrides = self: super: { custom-dep = customDependency; }; }; }
针对Stack项目
用stack-to-nix工具生成Stack项目的Nix配置:
stack-to-nix --output .
然后在shell.nix里引用生成的stack.nix,逻辑和Cabal项目类似,就能基于Stack的依赖锁文件构建一致的环境。
该选哪种方式?
- 用
pkgs.haskellPackages.<package>:适合绝大多数日常场景,速度快、维护成本低,Nixpkgs会帮你处理依赖兼容性问题。 - 从源码构建:仅当需要自定义包版本、修改源码,或者依赖不在Nixpkgs里时使用,灵活性更高,但需要自己处理依赖和哈希校验。
内容的提问来源于stack exchange,提问作者Noel Kwan
相关产品推荐
相关产品推荐

