如何覆盖Nix派生类而不会抛出“不能将集合强制转换为字符串”?

kvz*_*kvz 4 nixos

或者,目标是:如何以声明方式从Nix不稳定的组件中获取单个软件包?

我是NixOS的新手,当前正在尝试安装比0.5.2我的NixOS版本的默认版本(最新稳定版本)更高的Consul 版本。我正在尝试通过覆盖/etc/nix/configuration.nix

我想保持稳定运行,但是发现不稳定的Consul 0.7.0已经有了我想要的(),因此我决定以该包的属性为起点来覆盖https://github.com/NixOS/ nixpkgs / blob / master / pkgs / servers / consul / default.nix

我将其大部分复制到了configuration.nix,这是相关的部分:

nixpkgs.config.packageOverrides = pkgs: rec {
  consul = pkgs.lib.overrideDerivation pkgs.consul (attrs: rec {
    version = "0.7.0";
    name = "consul-${version}";
    rev = "v${version}";

    goPackagePath = "github.com/hashicorp/consul";

    src = pkgs.fetchFromGitHub {
      owner = "hashicorp";
      repo = "consul";
      inherit rev;
      sha256 = "04h5y5vixjh9np9lsrk02ypbqwcq855h7l1jlnl1vmfq3sfqjds7";
    };

    # Keep consul.ui for backward compatability
    passthru.ui = pkgs.consul-ui;
  });
};

environment.systemPackages = with pkgs; [
  vim
  which
  telnet
  consul-ui
  consul-alerts
  consul-template
  consul
];
Run Code Online (Sandbox Code Playgroud)

我在跑步时nix-build (Nix) 1.11.2抛出:

$ nixos-rebuild switch
building Nix...
building the system configuration...
error: cannot coerce a set to a string, at /etc/nixos/configuration.nix:19:7
(use ‘--show-trace’ to show detailed location information)
Run Code Online (Sandbox Code Playgroud)

当我查看line 19时,name将其设置为"consul-${version}"

为什么这里要进行类型强制?任何提示将不胜感激!

我还想知道是否有更好的方法在不稳定的环境中仅运行单个程序包configuration.nix,而从而不是强制性地以声明方式进行?

Cha*_*les 5

除了Rok所说的之外:

应该指出,错误实际上发生在通过行。如果您将其注释掉,它可能会生成。我假设这里有一些递归调用,当它尝试评估consul / consul-ui软件包时会发生错误。

如果您刚刚起步,可以放心地忽略接下来发生的事情,如果/如果您对实质问题感到好奇的话,也许可以重新考虑。

这里的问题是,这overrideDerivation是一种低级的方法来覆盖事物。在后面stdenv.mkDerivation,我们有一个更小的原始函数称为derivation。该derivation函数具有一些属性,并且(或多或少-有关详细信息,请参阅文档)只是在构建过程中将这些属性作为环境变量传递。stdenv.mkDerivation另一方面,该函数具有大量智能,它们在传递给它的属性之前先按摩赋予它的属性derivation-在某些情况下,例如passthru,它不会将该属性传递给derivationat所有。

返回至overrideDerivation:它需要stdenv.mkDerivation传递给的最终的,经过调整的属性derivation,并且在此之前,它允许您使用提供的功能覆盖这些属性(例如,这意味着此时passthru已被删除)。当您的函数添加passthru时,将其插入derivation,然后希望将的值强制passthru转换为字符串,以便可以passthru在构建期间使环境变量;但是,由于passthru现在指向一个属性集,并且不支持这种强制,因此Nix会抱怨。

因此,这使我们处于一种奇怪的情况。为了说明,我将在此处复制consul包的源代码:

{ stdenv, lib, buildGoPackage, consul-ui, fetchFromGitHub }:

buildGoPackage rec {
  name = "consul-${version}";
  version = "0.6.4";
  rev = "v${version}";

  goPackagePath = "github.com/hashicorp/consul";

  src = fetchFromGitHub {
    owner = "hashicorp";
    repo = "consul";
    inherit rev;
    sha256 = "0p6m2rl0d30w418n4fzc4vymqs3vzfa468czmy4znkjmxdl5vp5a";
  };

  # Keep consul.ui for backward compatability
  passthru.ui = consul-ui;
}
Run Code Online (Sandbox Code Playgroud)

(请注意,这buildGoPackage是一个包装器stdenv.mkDerivation。)

您可能熟悉例如consul.override,它允许你提供不同的输入(例如可能是不同的版本consul-ui,或buildGoPackage),但它不会让你忽略的东西,是不是输入(例如srcpassthru等)。同时,overrideDerivation允许修改赋予的attrs derivation,而不是给予者stdenv.mkDerivation。理想情况下,两者之间应该有某种关系,这允许操纵给的attrs stdenv.mkDerivation,因此碰巧有一个PR公开来解决此问题:

https://github.com/NixOS/nixpkgs/pull/18660


小智 3

欢迎来到 Nix/NixOS :)

\n\n

每当您需要了解更多有关错误的信息时,您都可以使用它--show-trace,这会给您带来更详细的错误。在你的情况下,你会看到类似的东西

\n\n
error: while evaluating the attribute \xe2\x80\x98passthru\xe2\x80\x99 of the derivation \xe2\x80\x98consul-0.7.0\xe2\x80\x99 at /home/rok/tmp/consul.nix:6:3:\ncannot coerce a set to a string, at /home/rok/tmp/consul.nix:6:3\n
Run Code Online (Sandbox Code Playgroud)\n\n

这应该指出错误实际上发生在 passthru 线路上。如果您将其注释掉,它可能会构建。我假设这里有一些递归调用,并且当它尝试评估 consul/consul-ui 包时会发生错误。

\n\n

至于仅覆盖不稳定通道中的一个包,需要这样的东西

\n\n
let\n  unstable_pkgs = import ./path/to/unstabe/nixpkgs {};\n  # or\n  # unstable_pkgs = import (pkgs.fetchFromGitHub {...}) {};\nin {\n  ...\n  nixpkgs.config.packageOverrides = pkgs: rec {\n    consul = unstable_pkgs.consul;\n  };\n  ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还没有尝试过上面的方法,但我假设它会起作用。

\n