Nix:推导如何在不调用构建器的情况下在 nix-shell 中设置 PATH?

Nix: How a derivation sets up PATH in nix-shell without calling builder?

一个推导需要很多参数,但只有其中一个,builder,是可执行的吗?

nix-shell并没有真正执行builder,也就是说没有办法运行ning 命令,例如 export PATH=....

但我发现其他一些派生提供了它们的虚拟 shell 环境,其中 PATH 是任意设置的,例如 haskell 包派生的 .env 属性。

我还发现 mkDerivation 添加 buildInput 包的子 /bin 目录到 PATH(如果存在)。

他们是怎么做到的?内置 derivation 函数是否有一些特殊参数,使您能够在评估时 运行 自定义命令?

我上次检查时,nix-shell 在启动时尝试 运行 此命令:

source $stdenv/setup

所以当你调用derivation函数时,你应该定义一个名为$stdenv的环境变量,它指向一个包含名为setup的文件的目录,并且该文件应该是一个有效 Bash 脚本。然后该脚本可以定义您需要的 shell 函数和环境变量。

在我的 nixcrpkgs project 中,我的 setup 脚本只有一行:

export PATH=$_PATH

所以我将 _PATH 作为参数传递给 derivation,然后我的 setup 脚本将其复制到 PATH 环境变量中。

我们不能只在推导中设置 PATH,因为 nix-shell 会使推导的 PATH 覆盖系统 PATH,这意味着我们不能使用像“git”或“which”这样的实用程序来自主机系统。

这里有一些伪代码显示了您需要做什么:

derivation {
  stdenv = ./my_pretened_stdenv;  # directory that has setup script in it
  _PATH = "/stuff/bin:/more_stuff/bin";
  # other attributes
}

另一种方法是在推导阶段导出特定路径 - 尽管我不确定这是否是正确的方法。

假设您在构建某些东西时需要一个包 cowsay 在您的路径中,然后您可以通过添加它来使其可用:

# ... 
<nixpkgs>.stdenv.mkDerivation{
# ...
  buildPhase = '' 
    export PATH="${<nixpkgs>.cowsay}/bin:$PATH"
  '';
# ... 
}

这将使构建器在 buildPhase 期间执行该命令,并构建包并将其添加到构建阶段的路径中。您可以使用 shellHook

对 shell 的 mkDerivation 执行相同的操作
# ... 
<nixpkgs>.stdenv.mkDerivation{
# ...
  shellHook = '' 
    export PATH="${<nixpkgs>.cowsay}/bin:$PATH"
  '';
# ... 
}

然后该路径将在您的 shell 环境中可用。

值得注意的是,默认情况下,如果构建派生(在 buildInputs 或其他任何地方,如果它有一个 ./bin/ 目录,则它对环境可用。