nixos - 如何在不抛出 `cannot coerce a set to a string` 的情况下覆盖 Nix 导数?

标签 nixos

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

我是 NixOS 的新手,目前正在尝试安装比默认版本更新的 Consul 0.5.2我的 NixOS 版本(最新稳定版)。我正在尝试通过覆盖我的 /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
];

我在运行 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)

当我查看行 19 时这是哪里name设置为 "consul-${version}" .

为什么这里会发生类型强制?任何提示将不胜感激!

我也想知道是否有更好的方法在不稳定的情况下只运行一个包,但从 configuration.nix 声明性地这样做,而不是命令式?

最佳答案

补充一下 Rok 所说的:

Which should point you that an error actually happens at passthru, line. If you comment it out it will probably build. I'm assuming some recursive calls are at play here and error occurs when it tries to evaluate consul/consul-ui packages.



如果你刚刚开始,你可以放心地忽略接下来的内容,如果/当你对细节感到好奇时,也许可以回到它。

这里的问题是 overrideDerivation是一种覆盖事物的低级方法。后面 stdenv.mkDerivation ,我们有一个更小的原始函数,称为 derivation . derivation function 接受一些属性,并且(或多或少 - 请参阅文档以获得更详细的信息)在构建期间将这些属性作为环境变量传递。 stdenv.mkDerivation另一方面,函数在顶部有一大堆智能分层,在将它们传递给 derivation 之前按摩赋予它的属性。 -- 在某些情况下,就像 passthru 一样,它不会将该属性传递给 derivation根本。

返回 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;
}

(请注意, buildGoPackagestdenv.mkDerivation 的包装器。)

您可能熟悉例如consul.override ,它允许您提供不同的输入(例如可能是 consul-uibuildGoPackage 的不同版本),但它不允许您覆盖不是输入的内容(例如 srcpassthru 、等等)。同时,overrideDerivation允许您修改赋予 derivation 的属性,但不是给 stdenv.mkDerivation 的那些.理想情况下会有一些介于两者之间的东西,这将允许操纵赋予 stdenv.mkDerivation 的属性。 ,而且碰巧有一个公关可以解决这个问题:

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

关于nixos - 如何在不抛出 `cannot coerce a set to a string` 的情况下覆盖 Nix 导数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39581045/

相关文章:

mysql - nix-shell --命令 `stack build` 导致 libpq-fe.h : No such file or directory

swift - 如何在 NixOS 上构建 Swift 项目?

nixos - 在我的存储库中实现覆盖

haskell - 如何将环境变量传递给通过堆栈运行的 Haskell 程序?

php - Nix 可组合派生选项

config - 如何为包编写新的 .nix 配置文件?

linux - Nix/OS 架构概述?

ssh - 在不发送私钥的情况下配置远程 nixos 盒

virtualbox - 在 configuration.nix 中从 nixos-unstable 安装 virtualbox 模块

haskell - 配置堆栈 ghci 提示符