OFFSET偏移
← 文章目录OFFSET / FIELD NOTESNO. 083

Overlays、override 与 overrideAttrs

在现有包定义上调整参数、添加补丁,并让系统实际消费 overlay。

所在专题Nix 开发环境与二进制兼容 ↗
约 4 分钟阅读开始阅读

️ 什么是 Overlays?#

Overlays 是 Nixpkgs 的一个核心机制。你可以把它想象成在官方的 pkgs 上覆盖一层你自己的定义。

1. 基础语法

self: super: {
  # 把 hello 包换成我的版本
  hello = super.hello.override {
    # 修改参数
  };
}

️ 常见的 Overlays 场景#

1. 修改编译选项 (Override)

有些包在编译时默认关闭了某些功能。

(self: super: {
  mpv = super.mpv.override {
    scripts = [ self.mpvScripts.mpris ];
  };
})

2. 打补丁 (overrideAttrs)

如果你手里有一个 .patch 文件:

(self: super: {
  sl = super.sl.overrideAttrs (oldAttrs: {
    patches = (oldAttrs.patches or []) ++ [ ./my-patch.patch ];
  });
})

3. 添加新包

你可以把自己的包定义在 Overlay 里,然后像 pkgs.my-app 这样引用它。

在 Flake 中集成 Overlays#

在 outputs 部分定义你的 Overlays。

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  outputs = { self, nixpkgs, ... }: {
    overlays.default = final: prev: {
      sl = prev.sl.overrideAttrs (old: {
        patches = (old.patches or []) ++ [ ./my-patch.patch ];
      });
    };
    nixosConfigurations.workstation = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        ./configuration.nix
        { nixpkgs.overlays = [ self.overlays.default ]; }
      ];
    };
  };
}

为什么要这样做?#

作为 Arch 用户,你可能习惯了去 AUR 找 PKGBUILD。在 NixOS,Overlays 就是你的“全能补丁”。你不需要重新打包,只需在现有包的基础上微调即可。

总结#

  • override:修改包函数的参数(通常是 callPackage 调用的函数参数)。
  • overrideAttrs:修改传给 mkDerivation 的 derivation 属性(比如 patches、postInstall),再产生新的 derivation。

final / prev 与实际构建

self: super: 是旧的变量命名习惯;更直观的是 final: prev:,分别表示叠加后的最终包集合与上一层包集合。导入 overlay 后仍需让消费者真正使用这个包集合;原始示例只定义局部 pkgs,没有接入 nixosSystem,这里已改成模块里的 nixpkgs.overlays。补丁修改要实际构建受影响的软件包,求值通过不代表 patch 可以应用。包函数的参数与版本由锁定 Nixpkgs 决定。

参考与延伸

  1. Nixpkgs Overlays ↗
  2. Nixpkgs Overrides ↗

根据技术笔记重新整理,示例使用通用名称。

沿专题继续阅读

Nix 开发环境与二进制兼容

  1. 01Nix-shell、devShell 与 direnv 的递进用法
  2. 02Nix 开发环境:多语言、数据库与全栈示例
  3. 03Python、uv 与 Matplotlib/Qt 的依赖边界
  4. 04nix-ld:预编译 ELF、加载器与库路径
  5. 05Overlays、override 与 overrideAttrs
CONTINUE READING / 下一篇垃圾回收、存储优化与回滚世代

区分删除世代引用、回收 store 对象和切换旧系统配置。