【问题标题】:How to use nix-shell properly and avoid "dumping very large path"?如何正确使用 nix-shell 并避免“转储非常大的路径”?
【发布时间】:2016-09-07 14:08:06
【问题描述】:

根据我的阅读(特别是 the wiki 和 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 问题,但没有以外行人易于理解的方式表达。

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

对于编写这种我可能不知道的开发环境,是否有一般性建议?

【问题讨论】:

    标签: ocaml nix


    【解决方案1】:

    可能src 属性(当前目录)非常大。 nix-shell 将在每次调用时将其复制到 Nix 存储区,这可能不是您想要/需要的。解决方法是这样写:

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

    (其中lib 来自 Nixpkgs)。

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

    【讨论】:

    • 这很有帮助。但是,它不应该是 "then null else './.';" 而不是 "then null else nix;"?
    • 在运行nix-build时不会导致同样的警告吗?这就是我在不使用lib.inNixShell 的情况下遇到的问题,nix-shell 很高兴,但nix-build 会发出警告(但仍然有效)。
    【解决方案2】:

    聚会迟到了,但是(因为我无法评论 niksnut 的 correct answer)如果您想将 src 的一些子集添加到 Nix 商店,我想提一下处理此问题的方法,过滤掉大/不需要的文件。

    这种方法使用来自nixpkgs的lib.cleanSource and friends:

    # 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}
      '';
    }
    

    在上面的sn-p中,shellSrc是指一个属性集,代表一个包含./.的存储路径,但是没有vendor子目录(cleanVendor),也没有.git,.svn,以~ 结尾的文件,以及其他与编辑器/VCS 相关的内容 (cleanSource)。

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

    【讨论】:

    • 这是正确的方法,但这个答案看起来过于复杂,因为它处理的是 OP 未提及的 vendor 目录。最好先显示src = lib.cleanSource ./.;,然后再显示如何完成更复杂的事情。
    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2015-03-15
    • 2022-09-28
    • 2016-08-13
    • 2023-03-30
    相关资源
    最近更新 更多