21

我刚刚开始掌握 Nix,如果我错过了文档中问题的答案,我深表歉意。

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

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

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

所以,我的问题如下:

  1. Nix 包在构建和运行时依赖项之间有什么区别吗?
  2. 为什么有些包似乎依赖于构建工具,而另一些只需要运行时?这一切都取决于包作者如何包装应用程序吗?
  3. 如果一个包包含我不想要的构建依赖项,作为操作员,除了为同一个应用程序设计我自己的替代包之外,我能做些什么吗?

非常感谢。

4

1 回答 1

32
  1. The runtime dependencies are a subset of the build-time dependencies that Nix determines automatically by scanning the generated output for the hash part of each build-time dependencies' store path. For example, if you build a package using the compiler /nix/store/abcdef...-foo-1.20, then Nix will scan all files in the generated output for the hash bit abcdef.... If that hash is found, then the output is assumed to reference the compiler in some way, so it's kepts as a runtime dependency. If that hash does not occur, however, then the generated output has no reference to the compiler and therefore cannot access it at runtime, so foo-1.20 is treated as a build-time-only dependency.

  2. Some packages record large parts of their build environment for informational/debugging purposes. Perl, for example, stores every little detail about the tools used to compile it, so all those store paths end up being treated as runtime dependencies despite the fact that Perl doesn't actually need them at runtime, but Nix can't know: it just knows that the Perl store path references those tools. Now, Nixpkgs maintainers usually make an effort to clean that up, i.e. by pruning the logfile that contains all those store paths from the installation, etc., but for sure there are plenty of packages in the database still that haven't been optimized to that end yet.

  3. Let's assume that you'd like to compile a version of openssh that does not depend on PAM. Then you can remove the build input from the expression by means of an override, i.e. you replace the pam argument that's normally passed to the openssh build function with null. To do that, store the following file in ~/.nixpkgs/config.nix

    {
      packageOverrides = super: let self = super.pkgs; in {
        openssh-without-pam = super.openssh.override {
          pam = null;
        };
      };
    }
    

    and now install that package by running:

    $ nix-env -f "<nixpkgs>" -iA openssh-without-pam
    
于 2016-01-17T11:02:56.537 回答