首页 > 解决方案 > nixos:覆盖调用覆盖

问题描述

我在我的 ~/.config/nixpkgs/overlays/tmft.nix 中定义了一个覆盖,如下所示:

self: super: {
  tfmt = import ../dists/tfmt/default.nix {};
}

没关系,我可以安装它。它是一个 haskell 包,我想将它作为我的 ghc 安装的一部分进行安装。所以我在 myHaskellEnv.nix 中有另一个覆盖,看起来像这样:

self: super: {
  myHaskellEnv = super.haskellPackages.ghcWithHoogle
                   (haskellPackages: with haskellPackages;
                   [ tfmt ]);
}

只是,它抱怨它看不到 tfmt ( error: undefined variable 'tfmt')。

我可以通过直接导入包来解决这个问题:

let tfmt = import ../dists/tfmt/default.nix {};
 in self: super: {
  myHaskellEnv = super.haskellPackages.ghcWithHoogle
                   (haskellPackages: with haskellPackages;
                   [ tfmt ]);
}

但这会破坏重用。

如何使用另一个叠加层?我尝试参考 super.tfmt,但这显示了同样的问题。

标签: overlaynixnixos

解决方案


叠加层只是属性集(通常是包)self的函数。super与任何 Nix 函数定义相同的范围规则适用。因此,当您想使用先前叠加层中的某些内容时,它并没有神奇地出现在范围内。您必须从selfsuper仅代表早期覆盖的最终包集和定义中获取它。

通过更改[ tfmt ]为,[ self.tfmt ]您应该能够插入 - 的最终定义,tfmt因为它可能会在后续覆盖中被覆盖。或者,您可以tfmt从获取super,不推荐这样做,因为它不太灵活,但有时您需要super避免创建导致评估期间无限递归的循环定义。


编写覆盖时,应避免直接或间接重新导入 Nixpkgs。这很重要,因为<nixpkgs>可能是错误的 Nixpkgs 版本供某人使用,如果您做对了,您将重新评估 Nixpkgs 固定点,这需要时间,您将丢失原始 Nixpkgs 中的任何配置,例如configoverlays交叉编译参数。

相反,您应该使用selfandsuper属性。特别是,super.callPackage它派上用场,但对于 Haskell 包,您最好覆盖一个 haskell 包集,用您自己的包扩展它,以保持一致性。

这是一个例子

另外,我建议您将叠加层的数量保持在最低限度。仅在从软件分发的角度来看有意义的情况下才拆分它们——这就是它们的目的。


推荐阅读