我无法理解 Nix 覆盖和覆盖模式。我想要做的是在不复制/粘贴整个派生的情况下向 gdb 的“补丁”添加一些内容。
从Nix Pills我有点看到覆盖只是模仿 OOP,实际上它只是集合的另一个属性。但它是如何工作的呢?覆盖是从原始属性集到转换后的又具有预定义覆盖功能的函数吗?
由于 Nix 是一种函数式语言,因此您也没有只能在不同范围内隐藏的变量绑定。但这仍然无法解释叠加层如何实现其“魔力”。
通过 ~/.config/nixpkgs 我配置了一个测试覆盖大约是这样的:
self: super:
{
test1 = super.gdb // { name = "test1"; buildInputs = [ super.curl ]; };
test2 = super.gdb // { name = "test2"; buildInputs = [ super.coreutils ]; };
test3 = super.gdb.override { pythonSupport = false; };
};
Run Code Online (Sandbox Code Playgroud)
我得到:
nix-repl> "${test1}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test2}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test3}"
"/nix/store/vqlrphs3a2jfw69v8kwk60vhdsadv3k5-gdb-8.3"
Run Code Online (Sandbox Code Playgroud)
但是之后
$ nix-env -iA nixpkgs.test1
replacing old 'test1'
installing 'test1'
Run Code Online (Sandbox Code Playgroud)
你能解释一下这些结果吗?我是否正确覆盖只能改变“定义的接口”——这是函数的所有参数,因为“补丁”不是 gdb 的参数,我将无法更改它?那么最好的选择是什么?
fic*_*ion 10
我会写一个答案,以防其他人偶然发现。
21.8.2019 编辑:
我真正想要的在https://nixos.org/nixpkgs/manual/#sec-overrides 中有描述
overrideDerivation和overrideAttrs
overrideDerivation 基本上是“派生 (drv.drvAttrs // (f drv))”,并且 overrideAttrs 在https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/make- 中被定义为 mkDerivation 的一部分派生.nix
然后我的代码看起来像:
gdb = super.gdb.overrideAttrs (oldAttrs: rec {
patches = oldAttrs.patches ++ [
(super.fetchpatch {
name = "...";
url = "...";
sha256 = "...";
})
];
});
Run Code Online (Sandbox Code Playgroud)
问题标题具有误导性,来自我对推导的根本误解。叠加层完全按照宣传的方式工作。他们可能也没有那么神奇。只是一些递归,其中 endresult 是上一步的结果 // 最后一个叠加函数的输出。
nix-instantiate 的目的是什么?什么是商店派生?
请在我错的地方纠正我。
但基本上,当您评估 Nix 代码时,“派生函数”会将描述性属性集(名称、系统、构建器)转换为“实际派生”。“实际派生”同样是一个属性集,但诀窍在于它由商店中的 .drv 文件支持。所以在某种意义上,推导有副作用。drv 对构建应该如何进行以及需要哪些依赖项进行编码。该文件的哈希值还决定了人工制品的目录名称(尽管尚未构建任何内容)。因此,nix 存储中的名称也隐含地取决于所有构建输入。
当我基于将现有的派生联系在一起创建一个类似于 Frankenstein 的新派生时,我所做的只是创建对同一个 .drv 文件的多个引用。好像我正在复制一个指针,结果是得到两个指向堆上相同值的指针。我能够更改一些元数据,但最终构建过程仍然相同。事实上,因为 Nix 是纯粹的,我敢打赌,甚至没有办法写入文件系统(以更改 .drv 文件)——除非再次使用包装推导函数的东西。
另一方面,覆盖允许您创建“新实例”。由于“输入模式”,Nix 中的每个包都是从依赖属性设置到最终调用“派生函数”的实际代码的函数。通过覆盖,您可以再次调用该函数,这使得“派生函数”获得不同的参数。
| 归档时间: |
|
| 查看次数: |
2885 次 |
| 最近记录: |