Nix中的构建与运行时依赖关系

Nei*_*ett 18 nixos nix nixpkgs

我刚刚开始接触Nix,如果我在文档中错过了我的问题的答案,那么道歉.

我想使用Nix来设置一个安全的生产机器,其中包含最少的库和可执行文件.我不希望出现任何编译器或其他构建工具,因为这些可能存在安全风险.

当我安装一些软件包时,它们似乎只依赖于最小的运行时依赖项集.例如,如果我安装,apache-tomcat-8.0.23那么我得到一个Java运行时(JRE)和包含Tomcat的预构建JAR文件.

另一方面,一些软件包似乎包含一个完整的构建工具链作为依赖项.以另一个基于Java的示例为例,当我安装spark-1.4.0Nix 时,请下载包含编译器的Java开发工具包(JDK),它还会提取Maven构建工具等.

所以,我的问题如下:

  1. Nix包是否在构建和运行时依赖关系之间做出了区分?
  2. 为什么有些软件包似乎依赖于构建工具而其他软件包只需要运行时?这完全取决于包作者如何包装应用程序?
  3. 如果一个软件包包含我不想要的构建依赖项,除了为同一个应用程序设计我自己的替代包装之外,我作为运营商可以做些什么吗?

非常感谢.

Pet*_*ons 25

  1. 运行时依赖项是Nix通过扫描生成的输出为每个构建时依赖项的存储路径的哈希部分自动确定的构建时依赖项的子集.例如,如果使用编译器构建包/nix/store/abcdef...-foo-1.20,则Nix将扫描生成的输出中的所有文件以获取哈希位abcdef....如果找到该哈希值,则假定输出以某种方式引用编译器,因此它将kepts作为运行时依赖项.但是,如果未发生该哈希,则生成的输出不会引用编译器,因此无法在运行时访问它,因此foo-1.20将其视为仅构建时依赖项.

  2. 一些软件包记录其构建环境的大部分内容,以用于信息/调试目的.例如,Perl存储了用于编译它的工具的每一个细节,所以所有这些存储路径最终都被视为运行时依赖,尽管Perl在运行时实际上并不需要它们,但是Nix不知道:它只知道Perl存储路径引用了那些工具.现在,Nixpkgs维护者通常会努力清理它,即通过修剪包含安装中所有这些存储路径的日志文件等,但是可以肯定的是,数据库中还有很多尚未优化的软件包.那个结束了.

  3. 让我们假设你想要编译一个openssh不依赖于PAM的版本.然后,您可以通过覆盖从表达式中删除构建输入,即替换pam通常传递给openssh构建函数的参数null.为此,请将以下文件存储在~/.nixpkgs/config.nix

    {
      packageOverrides = super: let self = super.pkgs; in {
        openssh-without-pam = super.openssh.override {
          pam = null;
        };
      };
    }
    
    Run Code Online (Sandbox Code Playgroud)

    现在通过运行安装该包:

    $ nix-env -f "<nixpkgs>" -iA openssh-without-pam
    
    Run Code Online (Sandbox Code Playgroud)

  • [来源参考](https://github.com/NixOS/nix/blob/84f112b1c8d3c5181b7a9b11d309f14f1709480d/src/libstore/references.cc#L83-L119):) (2认同)