Nixpkgs存储库中`callPackage`的定义在哪里(或如何查找Nix lambda定义)?

9
我发现了很多关于callPackage及其内部结构的资料,但没有一个提到它的位置。这就像Nix的最佳保密一样,甚至手册似乎都在积极回避这个话题。我可以在巨大的仓库中找到它,但需要时间。

资源:


实际上,答案指向了customisation.nix中的callPackageWith函数,但callPackage本身是在别处定义的


刚刚了解到还有一个callPackages函数(来自Nixpkgs#36354问题),而且基本上都没有文件记录。 - toraritte
3个回答

15

nix repl 可以告诉你 lambda 定义的位置。

$ nix repl
Welcome to Nix version 2.2.2. Type :? for help.

nix-repl> pkgs = import <nixpkgs> {}

nix-repl> pkgs.callPackage
«lambda @ /nix/store/9hffpjaa2a7djl19ncky7zcvlhyj76dn-nixos-19.03.172396.d740b2ee855/nixos/lib/customisation.nix:108:31»

其中直到nixos的部分是我的<nixpkgs>,因此给出了答案:lib/customisation.nix第108行

在某些情况下,它还可以报告属性的位置。

nix-repl> builtins.unsafeGetAttrPos "callPackage" pkgs
{ column = 3; file = "~/src/nixpkgs/pkgs/top-level/splice.nix"; line = 143; }

2
感谢您额外提供了如何查找lambda定义的奖励! - toraritte
3
在 REPL 启动时导入所有 Nixpkgs 表达式的 nix repl '<nixpkgs>' 快捷方式被发现。 - toraritte
1
nix repl '<nixpkgs>' <<< pkgs.callPackage - milahu
在当前版本的nix(2.12)中,该lambda中的路径实际上指向callPackagesWith而不是callPackages。我仍然找不到nixpkgs源代码中分配顶级callPackage属性的任何位置(有许多非顶级定义)。我猜测真正的位置要么在makeScope内部,要么在makeScopeWithSplicing内部(两者都在lib/customisation.nix中),但我不确定哪一个是真正的来源,或者它最终如何被添加到pkgs中。因此,对我来说,这个问题仍未得到解答。 - Jeff Hykin
1
@JeffHykin,我使用了一种新技术更新了答案。 pkgs.callPackage 属性在 pkgs/top-level/splice.nix 中定义。 - Robert Hensing

2

尽管另一个答案中的lambda输出,我相信callPackage的原始值实际上是在pkgs/top-level/splice.nix中定义的,链接在这里

lambda中路径不返回那个^位置的原因是因为nixpkgs进行了一些绝对疯狂的递归计算。我的理解是pkgs会被反复替换(引导),而pkgs上的属性(如callPackages)会被多次替换。如果你对数学中的不动点组合子(如Y-Combinator)有所了解,那就是Nixpkgs在pkgs稳定之前所应用的方法。所以pkgs.callPackage实际上是一些随机/动态的函数参数,而不是直接设置的属性。而lambda路径就是指向这个动态函数参数。

这就像是Nix的最好保密秘密。
我已经阅读了3年的源代码,花了至少5个小时来剖析一个nixpkgs的最小化版本(这本身就是一个项目),才弄清楚callPackage实际上是来自pkgs/top-level/splice.nix。而找到它的定义甚至还不到真正理解它来自哪里的一半。所以,是的,我可以说这是一个相当好的保密秘密,即使在回答完这个问题之后,它可能仍然是一个秘密,因为我自己也几乎不能声称完全理解它。

1

在使用 flakes 之前,我使用的是 nix edit nixpkgs.callPackage,而使用了 flakes 后则是 nix edit nixpkgs\#callPackage

无论是否为 lambda,都可以正常工作。例如:nix edit nixpkgs\#nix.meta


之前从未听说过 nix edit,刚刚通过 nix --help 查看了所有子命令,谢谢!不过对于 callPackage 并没有起作用,即使使用 nix edit nixpkgs.hello(或任何其他包)也是如此。(我的版本是2.3.10。) - toraritte
顺便提一下,在 nixpkgs#nix.meta 中不需要反斜杠 -- 当 # 在单词的开头时,它只是 POSIX 家族 shell 中的注释字符;在其他所有位置上,它都是字面意义。 - Charles Duffy
@CharlesDuffy,我使用zsh,它将#视为文件名通配符。例如,echo /bo#t会输出/boot - ony
啊。 (很高兴我用“POSIX家族”限定词;zsh是故意不兼容的)。 - Charles Duffy
1
@ony 你应该将 nix 别名为 noglob nix - Diti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接