如何在Nix中更优雅高效地使用特定版本的软件包?
优化特定版本Ruby和PostgreSQL的Nix Shell配置
你的当前方案虽然能满足需求,但导入多个独立的nixpkgs实例存在明显弊端:会导致依赖冗余(比如每个实例都包含一套独立的底层库如glibc、OpenSSL),不仅增大Shell环境体积,还可能引发潜在的兼容性冲突。下面是两种更优的实现方式:
方案一:基于单个Nixpkgs实例,覆盖包版本
选择一个基础的nixpkgs版本(比如你原来用的stable-22.05),通过overrideAttrs直接修改Ruby和PostgreSQL的版本与源码哈希,所有包共享同一套依赖链:
let # 基础nixpkgs实例(stable-22.05) pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/040c6d8374d090f46ab0e99f1f7c27a4529ecffd.tar.gz") {}; # 覆盖Ruby为3.0.3版本 ruby_3_0_3 = pkgs.ruby_3_0.overrideAttrs (old: rec { version = "3.0.3"; src = pkgs.fetchurl { url = "https://cache.ruby-lang.org/pub/ruby/3.0/ruby-${version}.tar.gz"; # 执行 `nix-prefetch-url https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.3.tar.gz` 获取哈希 sha256 = "sha256-5qZkGp5Z8fG1X7X9Y0Y1Y2Y3Y4Y5Y6Y7Y8Y9Y0Y1Y2Y3Y4"; }; }); # 覆盖PostgreSQL为14.0.4版本 postgresql_14_0_4 = pkgs.postgresql_14.overrideAttrs (old: rec { version = "14.0.4"; src = pkgs.fetchurl { url = "https://ftp.postgresql.org/pub/source/v${version}/postgresql-${version}.tar.bz2"; # 执行 `nix-prefetch-url https://ftp.postgresql.org/pub/source/v14.0.4/postgresql-14.0.4.tar.bz2` 获取哈希 sha256 = "sha256-6qAkHk5H8fH1X7X9Z0Z1Z2Z3Z4Z5Z6Z7Z8Z9Z0Z1Z2Z3Z4"; }; }); in pkgs.mkShell { buildInputs = [ ruby_3_0_3 postgresql_14_0_4 ]; }
关键说明:
- 用
nix-prefetch-url命令可以快速获取对应源码包的SHA256哈希值,替换示例中的占位符即可。 - 所有包基于同一
nixpkgs实例,依赖共享,环境更简洁、稳定。
方案二:使用版本管理工具(适合多包多版本场景)
如果需要管理更多特定版本的包,可以用niv工具来跟踪不同nixpkgs的提交记录,但仍建议尽量复用同一个基础实例,仅在必要时引入特定版本的nixpkgs:
let # 用niv管理的nixpkgs版本(需先通过niv初始化) sources = import ./sources.nix; pkgs = import sources.nixpkgs {}; # 仅在基础实例无法通过override得到目标版本时,才引入特定nixpkgs rubyPkgs = import sources.ruby303Nixpkgs {}; in pkgs.mkShell { buildInputs = [ pkgs.postgresql_14.overrideAttrs(...) # 优先用override rubyPkgs.ruby_3_0 ]; }
这种方式更适合长期维护的项目,能清晰跟踪各版本的来源。
内容的提问来源于stack exchange,提问作者hasrthur
相关产品推荐
相关产品推荐

