或者,目标:如何以声明方式从Nix中获取单个包?
我是NixOS的新用户,目前正在尝试安装较新版本的Consul而不是我的NixOS版本的默认0.5.2
(最新稳定版)。我试图通过覆盖/etc/nix/configuration.nix
中的衍生物来尝试这一点。
我想保持稳定运行,但我发现不稳定的Consul版本我已经想要(0.7.0
),所以我决定使用这个包的属性作为覆盖{{的起点3}}
我将其大部分复制到我的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
以声明方式执行,而不是强制执行?
答案 0 :(得分:4)
添加Rok所说的内容:
哪个应该指出错误实际发生在passthru,line。如果你评论它可能会建立。我假设有一些递归调用在这里发挥作用,当它试图评估consul / consul-ui包时会发生错误。
如果你刚刚开始,你可以放心地忽略下面的内容,如果你对这个细节很好奇,可能会回过头来。
这里的问题是overrideDerivation
是一种覆盖事物的低级方法。在stdenv.mkDerivation
后面,我们有一个更小的原始函数,叫做derivation
。 derivation
函数需要一些属性,(或多或少 - 请参阅文档以获取更精细的细节)在构建期间将这些属性作为环境变量传递。另一方面,stdenv.mkDerivation
函数在顶部分层设置了一大堆智能,在将它们传递到derivation
之前按摩给它的属性 - 在某些情况下,如同passthru
,它根本不会将该属性传递给derivation
。
返回overrideDerivation
:它需要stdenv.mkDerivation
传递给derivation
的最终调整属性,在此之前,它允许您使用您提供的函数覆盖这些属性它(例如,这意味着,此时passthru
已被删除)。当您的函数添加passthru
时,它会进入derivation
,然后它会将passthru
的值强制转换为字符串,以便它可以使passthru
成为一个环境变量在建设期间;但是,因为passthru
现在指向属性集,并且不支持这样的强制,Nix然后抱怨。
所以这种情况让我们处于一种奇怪的境地。为了说明,我将在这里复制领事包的来源:
{ 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
的包装。)
你可能熟悉例如consul.override
,它允许您提供不同的输入(例如,可能是consul-ui
或buildGoPackage
的不同版本),但它不允许您覆盖 aren'的内容t 输入(例如src
,passthru
等)。同时,overrideDerivation
允许您修改授予derivation
的attrs,但不赋予stdenv.mkDerivation
的attrs。理想情况下,介于两者之间会有一些东西可以操纵给予stdenv.mkDerivation
的attrs,而恰好有一个PR可以解决这个问题:
答案 1 :(得分: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,line。如果你评论它可能会建立。我假设有一些递归调用在这里发挥作用,当它试图评估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;
};
...
}
我没有尝试过上述内容,但我认为它会起作用。