Cachix无法命中,导致需要本地编译

背景是我想安装yazi(https://github.com/sxyazi/yazi),由于主分支和正式版相差过大, 想通过overlay安装。
我按照文档加入了

  1. yazi.url = “github:sxyazi/yazi”;
  2. nixpkgs.overlays = [ yazi.overlays.default ];
  3. cachix :
    extra-substituters = [ “https://yazi.cachix.org” ];
    extra-trusted-public-keys = [ “yazi.cachix.org-1:Dcdz63NZKfvUCbDGngQDAZq6kOroIrFoyO064uvLh8k=” ];

然后在homemanager里直接填入yazi,但这在我的linux虚拟机上无法命中缓存,每次都要编译,我应该怎么办?
我的commit记录:test · rick-yao/dotfiles@9e9a2b8 · GitHub

substituters和keys我都信任了

因为你的flake里面有一个nixpkgs的checkout,然后你把yazi的包overlay到这个checkout上面,也就意味着依赖都是用的你的nixpkgs里的版本,而不是上游(yazi的flake.nix里的inputs.nixpkgs)的。这种用法在多数情况下是不能cache hit的。

如果你要用上游的cache,那么就直接写packages = with inputs.yazi.packages; [ yazi ];,这样得到的就是用yazi的nixpkgs构建出来的,它的derivation就与上游cache过的一致。但是相应的你的系统closure也会增大,因为你用了和目前系统的nixpkgs不同的依赖。

多谢回复,我大概懂你的意思了,另外我还有一个问题,我的overlay不能够覆盖nixpkgs里的yazi么?

说实话它这个写法确实有点迷惑了。看起来确实是应该使用它自己的pkgs的。它的callPackage是这一部分:

(
  system:
  let
    pkgs = import nixpkgs { inherit system overlays; };

    # 定义版本,略

    yazi-unwrapped = pkgs.callPackage ./nix/yazi-unwrapped.nix { inherit version; };
    yazi = pkgs.callPackage ./nix/yazi.nix { inherit yazi-unwrapped; };
  in
  {
    packages = {
      inherit yazi-unwrapped yazi;
      default = yazi;
    };

    # 略
  }
)

说明在callPackage这个function的时候,输入是yazi的inputs.nixpkgs,因为callPackage来自这个nixpkgs。而在后文中定义overlay,这个过程并没有用final或者prev覆盖它(final和prev是应用overlay后和应用overlay前的pkgs,一般来说调包会从prev里面调,避免infinite recursion,但是也有因为别的overlay,或者不用rec从顶层引用overlay里的其他包,而必须从final里调的情况。)

rec {
  default = yazi;
  yazi = final: prev: {
    yazi-unwrapped = self.packages."${final.system}".yazi-unwrapped;
    yazi = self.packages."${final.system}".yazi;
  };
}

看到yazi的overlay里面其实就直接引用了上文中的yazi,那么确实应该是可以被cache的。

overlay是可以覆盖的。不仅是覆盖最终的top-level package(也就是你在自己的配置中使用的pkgs.foo),也可以覆盖其他包依赖的那个yazi。它的作用相当于在一开始这个包就作为nixpkgs的一部分存在了。

看你的说法,我写的应该是没有错误的?还是没太明白应该怎么写,按我的理解overlay覆盖之后,homemanager里的yazi就还是写yazi就好了,不需要指明inputs.yazi了

对的,你的写法看起来确实没有错,我也有点不明白,可能比如它其实并没有cache上

cache应该是有的,我在我的ubuntu上照着yazi官网demo试了下,发现我拿一个空的flake,hm就能命中cache,然后再运行我的flake,就不用编译了

发现把substituter注释掉就能触发cache,请问怎么才能让yazi单独走cache呢?
nixConfig = {
42 │ experimental-features = [“nix-command” “flakes”];
43 │
44 │ # substituters = [
45 │ # “https://mirrors.tuna.tsinghua.edu.cn/nix-channels/store
46 │ # “https://mirrors.ustc.edu.cn/nix-channels/store
47 │ # “https://cache.nixos.org
48 │ # ];
49 │ extra-substituters = [ “https://yazi.cachix.org” ];
50 │ extra-trusted-public-keys = [ “yazi.cachix.org-1:Dcdz63NZKfvUCbDGngQDAZq6kOroIrFoyO064uvLh8k=” ];
51 │
52 │ auto-optimise-store = true;
53 │ };

你的这个注释掉也挺奇怪的,man nix.conf说:

       For instance,

       substituters = a b
       extra-substituters = c d

       defines the substituters setting to be a b c d.

所以看起来应该是没什么影响才对…

如果你的意思是“仅对这个derivation的output使用substituter下载”的话,我好像在哪儿提过,但是我们目前暂时还做不到。这就是为小项目添加substituter的一个痛点。

我也查到了,按理来说extra就是在非extra的后面的,我试了下,就算是substituters里面只留下 “https://cache.nixos.org”这一默认项,也不会触发cache,必须把substituters完全注释才行