5

Or, the goal: How can I take a single package from Nix unstable in a declarative manner?

I'm new to NixOS and currently trying to install a newer version of Consul than the default 0.5.2 of my NixOS version (latest stable). I'm attempting this by overriding the derivative in my /etc/nix/configuration.nix.

I'd like to keep running stable, but I found unstable had the version of Consul that I wanted (0.7.0) already, and so I decided to use this package's attributes as a starting point to override https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/consul/default.nix

I copied it for most part into my configuration.nix, here are the relevant sections:

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
];

I'm running nix-build (Nix) 1.11.2 which throws:

$ 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)

When I look at line 19 it's where name is set to "consul-${version}".

Why there is type-coercion going on here? Any tips will be greatly appreciated!

I'm also wondering if there is a better way to run just a single package in unstable, yet doing so declaratively from configuration.nix, rather than imperatively?

4

2 回答 2

5

补充一下Rok所说的:

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

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

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

回到overrideDerivation:它采用最终的、调整后的属性,该属性stdenv.mkDerivation将传递给derivation,并且在此之前它允许您使用您给它的函数覆盖这些属性(例如,这意味着此时passthru已被删除)。当您的函数添加 apassthru时,它会进入derivation,然后它希望将值强制passthru转换为字符串,以便它可以passthru在构建期间创建环境变量;但是,因为passthrunow 指向一个属性集,并且不支持这种强制,所以 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;
}

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

您可能熟悉 eg consul.override,它允许您提供不同的输入(例如,可能是不同版本的consul-ui, 或buildGoPackage),但它不允许您覆盖不是输入的内容(例如src,passthru等)。同时,overrideDerivation允许您修改给定的属性derivation,但不能修改给定的属性stdenv.mkDerivation。理想情况下,中间会有一些东西,这将允许操纵给定的属性stdenv.mkDerivation,并且碰巧有一个 PR 可以解决这个问题:

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

于 2016-09-21T14:51:04.030 回答
3

欢迎来到 Nix/NixOS :)

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

error: while evaluating the attribute ‘passthru’ of the derivation ‘consul-0.7.0’ at /home/rok/tmp/consul.nix:6:3:
cannot coerce a set to a string, at /home/rok/tmp/consul.nix:6:3

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

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

let
  unstable_pkgs = import ./path/to/unstabe/nixpkgs {};
  # or
  # unstable_pkgs = import (pkgs.fetchFromGitHub {...}) {};
in {
  ...
  nixpkgs.config.packageOverrides = pkgs: rec {
    consul = unstable_pkgs.consul;
  };
  ...
}

我没有尝试上述方法,但我假设它会起作用。

于 2016-09-20T00:17:08.750 回答