【问题标题】:nixos: overlays calling overlaysnixos:覆盖调用覆盖
【发布时间】:2018-11-28 20:49:29
【问题描述】:

我在我的 ~/.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,但这显示了同样的问题。

【问题讨论】:

  • 我现在发现它在其他一些情况下也有效——它看起来很可疑,就像这里发生了一个评估顺序的事情,这样你就可以引用在词汇表之前的覆盖中定义的东西一个试图做参考。任何人都可以确认/否认这一点,如果这是真的,是否有共同的模式来处理?根据评估顺序重命名事物似乎并不是特别具有可扩展性。
  • 不,没有那么简单——我尝试将 tfmt.nix 重命名为 00-tfmt.nix,以便在词法顺序中更早地强制它;无济于事。

标签: overlay nix nixos


【解决方案1】:

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

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


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

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

这是一个example

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

【讨论】:

    猜你喜欢
    • 2010-10-25
    • 2011-06-11
    • 2012-01-28
    • 2016-12-10
    • 2018-10-07
    • 2016-06-30
    • 2012-02-16
    • 1970-01-01
    • 2010-09-29
    相关资源
    最近更新 更多