如何正确使用nix-shell,避免"dumping very large path"?

How to use nix-shell properly and avoid "dumping very large path"?

根据我的阅读(特别是 the wiki and this blog post),我想出了以下 default.nix 我用 nix-shell 加载:

with import <nixpkgs> {};

let emacs =
  emacsWithPackages (p : [ p.tuareg ]);
in

stdenv.mkDerivation rec {
    name = "env";

    src = ./.;

    # Customizable development requirements
    buildInputs = [
        pkgconfig
        ocaml
        ocamlPackages.merlin
        ocamlPackages.findlib
        ocamlPackages.lablgtk
        ocamlPackages.camlp5_transitional
        ncurses
        emacs
    ];

    # Customizable development shell setup
    shellHook = ''
        export PATH=`pwd`/bin:$PATH
    '';
}

但它总是打印警告:

warning: dumping very large path (> 256 MiB); this may run out of memory

加载时间很长(启动后我第一次调用 nix-shell 大约需要 45 秒,后续调用大约需要 2 秒)。

这条消息是什么意思?当我在 Google 上寻找它时,我发现了一些 GitHub 问题,但没有以一种外行人容易理解的方式表达。

我可以加快加载速度并删除这条消息吗?在我看来,我做错了什么。

是否有关于编写我可能不知道的此类开发环境的一般建议?

可能src属性(当前目录)很大。 nix-shell 会在每次调用时将其复制到 Nix 存储,这可能不是您 want/need。解决方法是写:

src = if lib.inNixShell then null else ./.;

(其中 lib 来自 Nixpkgs)。

这样,当您调用 nix-build 时,./. 将被复制,但当您 运行 nix-shell.

时则不会

聚会迟到了,但是(因为我不能对 niksnut's 发表评论)如果您想将 src 的一些子集添加到 Nix,我想提一下处理这个问题的方法存储,过滤掉 large/unneeded 个文件。

此方法使用 lib.cleanSource and friends 来自 nixpkgs:

# shell.nix
{ pkgs ? import <nixpkgs> {} }:

with pkgs;

let
  cleanVendorFilter = name: type: 
    type == "directory" && baseNameOf (toString name) == "vendor";
  cleanVendor = src: lib.cleanSourceWith { filter = cleanVendorFilter; inherit src; };
  shellSrc = lib.cleanSource (cleanVendor ./.);
in mkShell {
  name = "my-shell";
  shellHook = ''
    printf 1>&2 '# Hello from store path %s!\n' ${shellSrc}
  '';
}

在上面的代码片段中,shellSrc 指的是表示存储路径的属性集,其中包含 ./.,但没有 vendor 子目录 (cleanVendor) 并且没有.git.svn、以 ~ 结尾的文件和其他 editor/VCS-related 内容 (cleanSource)。

查看 lib/sources.nix 以了解更多过滤路径的方法。