Nix覆盖和覆盖图案

时间:2019-08-11 10:13:13

标签: nix

我在理解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; };
  };

我得到:

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"

但是然后

$ nix-env -iA nixpkgs.test1
replacing old 'test1'
installing 'test1'

您能解释一下这些结果吗?我是否正确,重写只能更改“已定义的接口”,即函数的所有参数,并且由于“补丁”不是gdb的参数,因此我无法更改它?那么最好的选择是什么?

1 个答案:

答案 0 :(得分:3)

我会写一个答案,以防其他人偶然发现。


编辑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-derivation.nix中被定义为mkDerivation的一部分

然后我的代码如下:

gdb = super.gdb.overrideAttrs (oldAttrs: rec {
  patches = oldAttrs.patches ++ [
     (super.fetchpatch {
       name = "...";
       url = "...";
       sha256 = "...";
     })
 ];
});

问题标题具有误导性,源于我对派生词的基本误解。叠加层的工作方式与广告宣传完全相同。而且它们可能也不是魔术。只是一些递归,其中endresult是上一步的结果// //最后一个覆盖函数的输出。

What is the purpose of nix-instantiate? What is a store-derivation?

请在错误之处纠正我。

但是,基本上,当您评估Nix代码时,“推导函数”会将描述性属性集(名称,系统,构建器)转换为“实际推导”。该“实际派生”还是一个属性集,但诀窍在于它由存储中的.drv文件支持。因此,从某种意义上说,派生有副作用。 drv编码建筑物应该如何进行以及需要哪些依赖项。该文件的哈希值还确定了工件的目录名称(尽管尚未构建任何东西)。因此,nix存储中的名称隐式还取决于所有构建输入。

当我基于现有的衍生关系创建新的类似于Frankenstein的衍生关系时,我所做的就是创建对同一个.drv文件的多个引用。好像我正在复制一个指针,结果是获得两个指向堆上相同值的指针。我可以更改一些元数据,但最终构建过程仍然相同。实际上,由于Nix纯粹是我敢打赌,甚至无法写入文件系统(更改.drv文件)-除非再次使用一些包装了衍生功能的东西。

另一方面,覆盖允许您创建“新实例”。由于具有“输入模式”,Nix中的每个包都是从依赖项属性集到最终调用“派生函数”的实际代码的函数。使用override,您可以再次调用该函数,这会使“派生函数”获得不同的参数。