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/
目录,则它对环境可用。
一个推导需要很多参数,但只有其中一个,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
mkDerivation
执行相同的操作
# ...
<nixpkgs>.stdenv.mkDerivation{
# ...
shellHook = ''
export PATH="${<nixpkgs>.cowsay}/bin:$PATH"
'';
# ...
}
然后该路径将在您的 shell 环境中可用。
值得注意的是,默认情况下,如果构建派生(在 buildInputs
或其他任何地方,如果它有一个 ./bin/
目录,则它对环境可用。