nix-env如何提前知道存储路径



如果我查询Go的可用包:

nix-env -qa go -b --put-path --json

我得到:

{
"nixpkgs.go_1_16": {
"name": "go-1.16.15",
"pname": "go",
"version": "1.16.15",
"system": "x86_64-linux",
"outputs": {
"out": "/nix/store/nqi39ksavkfrxkrz3d0797n5wmzi9r30-go-1.16.15"
}
},
"nixpkgs.go": {
"name": "go-1.17.7",
"pname": "go",
"version": "1.17.7",
"system": "x86_64-linux",
"outputs": {
"out": "/nix/store/3v2l94h7pllq6za9km3388cyd5agrln7-go-1.17.7"
}
},
"nixpkgs.go_1_18": {
"name": "go-1.18",
"pname": "go",
"version": "1.18",
"system": "x86_64-linux",
"outputs": {
"out": "/nix/store/7jyfpb96xv3hr8dpfhnbb0f7zscwm7sr-go-1.18"
}
}
}

我是curios,nix-env如何提前知道存储路径?据我所知,存储路径是由nix在构建时生成的,但nix-env在没有构建的情况下就已经知道了(例如,我看不到任何从网络下载的东西(。

构建过程不直接采用.nix代码(从以下渠道下载https://nixos.org/channels/nixos-21.11)作为输入。相反,它将派生作为输入;这些派生是通过评估用Nix语言编写的代码生成的,然后作为.drv文件写入Nix存储中(可以很容易地解码为JSON进行读取;请参阅nix show-derivation(。这些.drv文件是实际构建过程(由nixbld沙盒用户帐户运行(用作输入的文件。

这些派生完全指定了构建过程要做什么——所有的输入和输出。因为输出(固定输出派生的输出除外(是由生成它们的构建过程的哈希来寻址的,所以在知道哈希之前没有必要实际运行构建。

我上面提到的例外是固定输出派生;这些用于从网络下载将由构建过程使用的资源。对于允许网络访问的Nix构建步骤,它需要提前断言该构建步骤的输出——如果该步骤产生的任何输出与所声明的不匹配,则该步骤被视为失败。在这些情况下,内容本身的哈希用于存储位置,因此对下载过程的更改不需要重新下载内容。

预构建时预测输出位置的能力至关重要,因为包是通过其哈希从Hydra二进制缓存中提取的。如果我们在构建包之前不知道散列,那么缓存将毫无用处:除非我们的任务中已经有了二进制文件,否则我们不知道该在哪个名称下查找二进制文件!(同样,如果我们不知道输入的名称和散列,而不实际构建它们,我们就无法提前一步计划(。


让我们举一个实际的例子。假设在我写这篇文章的时候,我还没有通过Nix安装GCC。

$ nix repl
Welcome to Nix version 2.3.16. Type :? for help.
nix-repl> :l <nixpkgs>
Added 15472 variables.
nix-repl> gcc8
«derivation /nix/store/9fpas3flqf424g46b8ldkbz7sgd9r7qk-gcc-wrapper-8.5.0.drv»
nix-repl> :b gcc8
...and either a download or a long build process runs here.

请注意评估gcc8如何为我们提供/nix/store/*-gcc*.drv文件。该文件包含一个计划,描述如果我们愿意,Nix将如何构建gcc8。

我们可以证明该计划包括输出位置:

$ nix show-derivation /nix/store/9fpas3flqf424g46b8ldkbz7sgd9r7qk-gcc-wrapper-8.5.0.drv | jq '.[].outputs'
{
"info": {
"path": "/nix/store/znasm5jz3pp57ivspw5ahgn7rzfk791w-gcc-wrapper-8.5.0-info"
},
"man": {
"path": "/nix/store/j46y5mrppjw7nw9g8ckd3h438k8jjvkr-gcc-wrapper-8.5.0-man"
},
"out": {
"path": "/nix/store/v9pv2w7qiw1cpbjn4wjdkxkzld7pfki4-gcc-wrapper-8.5.0"
}
}

最新更新