基于属性向 stdenv 添加一个 shell 函数

Add a shell function to the stdenv based on attribute

有没有简单的方法可以在stdenv提供的环境中添加一个bash函数?当使用 'nix-shell' 进行开发时,我可以 运行 命令,例如 'unpackPhase' 或 'buildPhase',因为 mkDerivation 将它们放在范围内——它非常有用。我的派生属性也被添加到环境中。但我也希望看到一种在 build/shell 环境中自动添加属性作为函数的方法。

为了解释我的意思,我目前可以通过使用 eval 语句或 toFilesource 将函数添加到环境中。例如,对于 eval,类似于:

{ stdenv, ... } : stdenv.mkDerivation
{ shellHook = ''eval "$myFunctions"'';
  myFunctions = ''
    myFunction1(){
      echo "doing myFunction1"
      }
    myFunction2(){
      echo "doing myFunction2"
      }
    ''
}
当我输入nix-shell时,

会"source"myFunction1myFunction2

但是,我期待像 mkFunction 实用程序这样的东西来补充 mkWrappermkProgram 和其他此类基本实用程序。我希望像下面那样使用它,其中使用 mkFunction 定义的属性会自动 "sourced" 如上所述。

{ stdenv, mkFunction, ... } : stdenv.mkDerivation
{ myFunction1 = mkFunction '' echo "doing myFunction1" '';
  myFunction2 = mkFunction '' echo "doing myFunction2" '';
  shellHook = '' echo "No need to source, myFunctions are already in scope." '';
}

我认为这样的实用程序会很有用。我认为 setup hooks 可能涵盖这种用途,但我不确定如何使用它们。以第一种方式做它并没有那么糟糕(如果我在写这个问题的过程中没有弄明白我就不会费心去问了)。但它似乎是 nix 已经可用的那种实用程序,所以我还是要问。

设置挂钩确实可以做到这一点,这是一个定义函数的简单示例 foo:

with import <nixpkgs> {};
let
  fooHook = stdenv.mkDerivation {
    name = "foo-hook";
    # Setting phases directly is usually discouraged, but in this case we really
    # only need fixupPhase because that's what installs setup hooks
    phases = [ "fixupPhase" ];
    setupHook = writeText "my-setup-hook" ''
      foo() { echo "Foo was called!"; }
    '';
  };
in mkShell {
  buildInputs = [ fooHook ];
  shellHook = "foo";
}

运行 nix-shell 在此产生所需的结果:

$ nix-shell
Foo was called!
[nix-shell:~]$

另一种简单的可能性是使用stdenv提供的runHook函数。

with import <nixpkgs> {};
mkShell rec {
  name = "runs-hook";
  myFun = "echo The name is ${name}";
}

在上面的代码片段中,变量 myFun 在 shell/build 环境中可用。您可以这样称呼它:

> runHook myFun
The name is runs-hook

这与问题中的 eval 方法非常相似。