在nixpkgs中如何无需重新编译即可覆盖包的相关文件?
nixpkgs大包简单修改免全量重建方法
核心思路是通过overrideAttrs重写包的构建钩子,仅修改你需要调整的步骤,不会变更上游源码哈希,因此前面的依赖下载、解压、甚至编译步骤都可以直接复用已有缓存,无需全量重建。
适用场景
- 新增/删除部分文件
- 修改部分shell脚本
- 添加缺失的
pkgconfig.pc文件
具体操作方法
方法1:临时单包修改(无需改动全局配置)
写一个独立的nix表达式即可,例如要修改hello包,新建modified-pkg.nix:
let pkgs = import <nixpkgs> {}; in pkgs.hello.overrideAttrs (oldAttrs: { # 如果只需要修改源码/补丁阶段的内容,重写postPatch钩子 postPatch = (oldAttrs.postPatch or "") + '' # 示例1:修改源码内容 sed -i 's/Hello, world!/自定义输出/g' src/hello.c # 示例2:新增pkgconfig的.pc文件 cat > custom.pc << EOF prefix=$out exec_prefix=''${prefix} libdir=''${exec_prefix}/lib includedir=''${prefix}/include Name: custom Description: Custom pkgconfig file Version: ${oldAttrs.version} Libs: -L''${libdir} Cflags: -I''${includedir} EOF ''; # 如果修改不需要动源码,只需在安装后调整,重写postInstall钩子效率更高 postInstall = (oldAttrs.postInstall or "") + '' # 示例:安装刚才新增的pc文件 install -Dm644 custom.pc $out/lib/pkgconfig/custom.pc # 示例:删除不需要的文件 rm -rf $out/share/doc ''; })
执行nix-build modified-pkg.nix即可完成构建,仅会运行你新增的修改步骤,其余步骤全部复用缓存。
方法2:全局持久化修改
如果需要修改后的包全局生效,可以把规则加到overlay里,以NixOS为例,在configuration.nix中添加:
nixpkgs.overlays = [ (final: prev: { hello = prev.hello.overrideAttrs (old: { # 和上面一样写你要修改的钩子内容 postInstall = (old.postInstall or "") + '' install -Dm644 ${./custom.pc} $out/lib/pkgconfig/custom.pc ''; }); }) ];
执行nixos-rebuild switch即可生效,同样不会触发全量重建。
方法3:临时调试修改
如果还在测试修改内容,不想反复写nix表达式,可以直接进入包的构建环境调试:
- 运行
nix-shell '<nixpkgs>' -A 你要修改的包名进入构建环境 - 执行
unpackPhase解压源码,进入解压后的目录 - 直接修改文件后,依次执行
configurePhase、buildPhase、installPhase验证效果,所有依赖都无需重新构建。
注意事项
如果修改涉及编译参数、依赖变更,会触发编译阶段重跑,但仍然只会重跑当前包,不会影响整个nixpkgs的其他包。
内容的提问来源于stack exchange,提问作者nh2
相关产品推荐
相关产品推荐

