提问人:Tim 提问时间:11/15/2023 最后编辑:Tim 更新时间:11/16/2023 访问量:58
如何使用定点来覆盖 nixpkgs 包?
How is fixed point used for overriding nixpkgs packages?
问:
https://nixos.org/guides/nix-pills/nixpkgs-overriding-packages.html 说
17.3. 固定点
...
nix-repl> fix = f: let result = f result; in result nix-repl> pkgs = self: { a = 3; b = 4; c = self.a+self.b; } nix-repl> fix pkgs { a = 3; b = 4; c = 7; }
...
17.3.1. 用定点覆盖集合
鉴于 self.a 和 self.b 引用传递的集合,而不是 函数中的文字集,我们能够覆盖 a 和 b 并得到 c 的新值:
nix-repl> overrides = { a = 1; b = 2; } nix-repl> let newpkgs = pkgs (newpkgs // overrides); in newpkgs { a = 3; b = 4; c = 3; } nix-repl> let newpkgs = pkgs (newpkgs // overrides); in newpkgs // overrides { a = 1; b = 2; c = 3; }
在第一种情况下,我们计算了带有覆盖的 pkgs,在第二种情况下 案例中,我们还在结果中包含了覆盖的属性。
17.4. 覆盖 nixpkgs 软件包
我们已经了解了如何覆盖集合中的属性,以便它们被依赖属性递归地选取。这种方法可以是 也用于推导,毕竟 nixpkgs 是一个巨大的集合 相互依赖的属性。
为此,nixpkgs 提供了 config.packageOverrides 。所以 nixpkgs 返回包集的固定点,packageOverrides 为 用于注入覆盖。
在某处创建一个 config.nix 文件,如下所示:
{ packageOverrides = pkgs: { graphviz = pkgs.graphviz.override { withXorg = false; }; }; }
现在我们可以构建例如 asciidoc-full,它将自动使用 覆盖的 graphviz:
nix-repl> pkgs = import <nixpkgs> { config = import ./config.nix; } nix-repl> :b pkgs.asciidoc-full
注意我们在导入时如何使用 packageOverrides 传递配置 尼克斯 .那么 pkgs.asciidoc-full 是一个派生,它有 图形可视化输入 ( pkgs.asciidoc 是较轻的版本,而不是 完全使用graphviz)。
由于没有 Graph viz 的 asciidoc 版本没有 X 支持 在二进制缓存中,Nix 会为你重新编译需要的东西。
17.6. 结论
Nix 应用程序将依赖于特定版本的库,因此 我们之所以要重新编译 ASCIIDoc 才能使用新的 graphviz 图书馆。
新建的 asciidoc 将依赖于新的 graphviz,而旧的 asciidoc 将继续不受干扰地使用旧的 graphviz。
“覆盖集合中的属性,以便它们被依赖属性递归选取”是什么意思?您能用 17.3.1 中的示例来解释一下吗?
“nixpkgs 返回包集的固定点”是什么意思?
固定点不是属于函数的东西吗?包是如何设置函数的?
为什么 nixpkgs 返回一个定点?nixpkgs 是否类似于 17.3.1 中的示例?
let newpkgs = pkgs (newpkgs // overrides); in newpkgs
“packageOverrides 用于注入覆盖”是什么意思?
为什么“那么 pkgs.asciidoc-full 是具有图形可视化输入的派生”?
为什么“新建的 asciidoc 将依赖于新的图形可视化”,而“旧的 asciidoc 将继续不受干扰地使用旧的图形可视化”?
答:
第一个问题
术语“从属属性”没有特别严格或标准的定义。在此上下文中,它表示集合中的属性,其值取决于集合中的一个或多个其他值。以下是该文档第 17.3 节中的函数:pkgs
pkgs = self: { a = 3; b = 4; c = self.a + self.b; }
由于该属性被定义为 和 的总和,因此可以说是一个依赖属性。c
a
b
c
当我们得到最终集合时,我们可以覆盖在 Nix 中使用运算符的值,但这只会改变而不改变任何依赖于它的属性,比如 .a
//
a
c
我们想做的是找到一种方法来覆盖,这种方式仍然在最后一集中。此外,任何依赖于的属性都应使用新值 c,依此类推。这就是为什么在你问的那句话中使用了“递归”这个词。我们希望找到一种方法来“覆盖集合中的属性,以便它们被依赖属性递归地选取”。a
c
a + b
c
这是在第 17.3.1 节末尾实现的。请注意,和已成功更改为 1 和 2,并且这些被覆盖的新值用于重新计算 (1+2 = 3)。a
b
c
第二个问题
句子“nixpkgs 返回包集的固定点”是仓促、不准确写作的一个例子。没有集合的“不动点”这样的东西,因为“不动点”是函数的属性,而不是集合。我将改写作者想说的话。nixpkgs 是一个 Nix 函数,您可以通过编写或类似方式获得。当您将一个集合与配置参数一起传递给此函数时,该函数将返回一组包,通常称为 。import <nixpkgs>
pkgs
包集是以一种特殊方式生成的,以帮助您覆盖其中的某些部分。nixpkgs 做了一个非常复杂的函数,它接受一个包集,修改它,然后返回一个新的包集。然后 nixpkgs 找到该函数的固定点,并返回它。在 nixpkgs 的某个地方,应该有一些代码类似于第 17.3.1 节的最后一行 ()。该代码计算一个函数的固定点,该函数采用一组包,然后应用用户指定的重写,并将原始函数应用于该函数。let newpkgs = pkgs (newpkgs // overrides); in newpkgs // overrides
newpkgs
pkgs
第三个问题
我知道被动语态在“packageOverrides 用于注入覆盖”这句话中可能会令人困惑,但你只需要阅读完整的上下文,然后它就有意义了。调用 nixpkgs 时,可以传递一个名为它的参数,该参数应该是一个集合。该集可以包含一个名为的属性,该属性允许您告诉 nixpkgs 您希望如何覆盖包。这里没有什么深奥的东西,文档的这一部分只是定义了一个 API,它允许你告诉 Nixpkgs 你希望它做什么。config
config
packageOverrides
这里的“注入”这个词没有什么特别或有意义的,但也许使用了这个词,因为你的函数将被集成到我上面谈到的大型复杂函数中,nixpkgs 将计算它的不动点。
第四个问题
你问为什么“pkgs.asciidoc-full 是具有图形可视化输入的派生”。
好吧,派生是 Nix 构建的软件。派生可以依赖于其他派生。例如,应用程序可以依赖库来执行一些计算或生成一些图形。显然 asciidoc-full 取决于 graphviz。您可以在此处查看 asciidoc 包的定义:
https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/typesetting/asciidoc/default.nix
请注意,它是一个很大的函数,并且是它的参数之一。graphviz
第五个问题
假设您之前使用 Nix 构建了 asciidoc。也许您将其安装在用户环境中,或者您刚刚使用 启动了一个 shell。我们称之为旧的 asciidoc。nix-shell -p asciidoc
然后,稍后创建一个新的 Nix 表达式,其中将覆盖包集中的定义。您可以使用这个新的 Nix 表达式构建 asciidoc,您将获得一个新软件,我们可以称之为新 asciidoc。这个新的 asciidoc 使用您修改后的 graphviz 版本,旧的 asciidoc 将继续使用普通版本的 graphviz。您制作的每个版本的 graphviz 在 Nix store 中都有一个唯一的路径,并且您制作的每个 asciidoc 版本都有对该路径的引用,确保它加载的 graphviz 版本与构建时使用的相同版本。与许多其他软件包管理系统相比,这是 Nix 的重要部分之一:同时安装多个版本的库,由不同的软件使用是简单而自然的。graphviz
评论
import <nixpkgs>
评论