nixpkgs 的圣杯:用 SAT/ASP 求解器给无版本包管理器加上版本范围
来源: fzakaria.com — 2026-09-01
概述
fzakaria 在 nixpkgs-multiverse(nixpkgs 历史版本的并集,30.9 万个包版本、1541 个 nixos-unstable 修订、几乎全可缓存命中)基础上推出 grail:给「版本号是单一、无版本范围」的 Nixpkgs 加上版本范围求解能力。Nixpkgs 历来每个属性只有一个版本,因而无需、也没有依赖求解器;一旦 multiverse 把所有版本「去删除」回来,选择就成真问题——范围求解是布尔可满足性(SAT,NP-hard)。grail 借鉴 Spack 的 spec 语言:@ 后接范围、^ 串联共存组(须在同一修订解析)、|| 或、逗号逻辑与;支持 >=<=、.x/.* 前缀、.. 闭区间,还支持日期范围与 glibc 时代。底层用 ASP(Answer Set Programming / clingo)编码事实与约束:每个 spec 恰好选一个允许版本、每个共存组停在某个候选修订、并杀掉让成员不在其组修订存活的模型;策略上先最小化修订数、再最大化新版本、再最小化 glibc 时代。grail lock 写出与 mvs 同格式的 lock 文件,甚至可在 derivation 里直接写 specs,让 clingo 在沙箱内求解、经 import-from-derivation 物化 nixpkgs,全程可被 nixpkgs-multiverse 索引的缓存命中。对 libc 兼容用 .gnu.version_r 的 GLIBC_2.x 需求做成事实让求解器回溯混用。
核心要点
nixpkgs 历来每个属性只有一个版本故无需求解器,但 multiverse 把 30.9 万个包版本摊开后,范围求解成为可能且是真 NP-hard 的 SAT 问题
grail 借鉴 Spack spec:@范围、^共存组、||或、,与、.x 前缀、..区间,还支持日期范围与 glibc 时代
求解器用 ASP(clingo):每个 spec 恰选一版、每个共存组停在单修订,并以策略优先最小化修订数、其次最新版本、再最小 glibc 时代
grail lock 写出与 nixpkgs-multiverse 的 mvs 同格式的 lock 文件,可在 derivation 直接写 specs 让沙箱内求解并物化
通过 ELF .gnu.version_r 抽取每条二进制的最大 GLIBC 需求当事实,让求解器能把包安全混到更早的 glibc 时代
clingo 可编译到 WebAssembly,作者已把同一求解器放到浏览器可交互查询
金句
The moment versions became a choice, solving became a real possibility. I get to hand Nix the solver it thought it never needed.(一旦版本成为可选项,求解就成为现实——我把 Nix 自以为永远不需要的那个求解器递到了它手里。)
👍 0
点赞
👎 0
沉底
返回 Lobsters 首页