どうも、こたつやきです。

いつものように nixos-rebuild switch --flake .#example-host --ask-sudo-password を実行したら、使ってもいないContourのビルドに失敗して、NixOSの更新が止まってしまった。

error: Cannot build '/nix/store/<hash>-contour-0.6.3.8249.drv'.
       Reason: builder failed with exit code 2.
       > /build/source/src/vtbackend/Image.cpp:160:29: error: 'rebind_simd_t' in namespace 'simd' does not name a template type
       > /build/source/src/vtbackend/Image.cpp:178:51: error: 'static_simd_cast' is not a member of 'simd'
error: Cannot build '/nix/store/<hash>-system-path.drv'.
       Reason: 1 dependency failed.
error: Cannot build '/nix/store/<hash>-nixos-system-example-host-26.11.drv'.
       Reason: 1 dependency failed.

なぜ system-path にContourが入っているのか、依存関係を追ってみた。

nix build .#nixosConfigurations.example-host.config.system.build.toplevel nixpkgs#contour

でも、nixpkgs#contour はflake registryのnixpkgsを指す。手元のflakeで固定しているnixpkgsとはcommitが違うので、これでは同じContourを調べていることにならない。そこで両方とも同じflakeから参照することにした。

nix why-depends .#nixosConfigurations.example-host.config.system.build.toplevel .#nixosConfigurations.example-host.pkgs.contour

ところが、これだと肝心のシステムをビルドし始めてしまう。今まさにビルドできなくて困っているのに。最後にたどり着いたのが --derivation だった。

$ nix why-depends --derivation .#nixosConfigurations.example-host.config.system.build.toplevel .#nixosConfigurations.example-host.pkgs.contour
/nix/store/<hash>-nixos-system-example-host-26.11.drv
└───/nix/store/<hash>-system-path.drv
    └───/nix/store/<hash>-contour-0.6.3.8249.drv

--derivation を付けるとビルド結果ではなくderivation同士の依存を見られる。確かに system-path がContourに直接依存している。なんで?

nixpkgsを探してみると、nixos/modules/config/terminfo.nix に答えがあった。

    environment.systemPackages = lib.mkIf config.environment.enableAllTerminfo (
      map (x: x.terminfo) (
        with pkgs.pkgsBuildBuild;
        [
          alacritty
          contour
          foot
          ghostty
          kitty
          mtm
          rio
          rxvt-unicode-unwrapped
          rxvt-unicode-unwrapped-emoji
          st
          tmux
          wezterm
          yaft
        ]
      )
    );

environment.enableAllTerminfo を有効にすると、いろいろな端末の terminfo が environment.systemPackages に追加される。Contourを端末として使っていなくても、Contourの terminfo を取り出すためにそのパッケージが依存に入るわけだ。

普段はbinary cacheから取れていたので気にしたことがなかったけど、今回はContourのビルドが失敗する問題に当たってしまった。ひとまず environment.enableAllTerminfo を無効にして、必要なものだけ指定した。

environment.enableAllTerminfo = false;
environment.systemPackages = [ pkgs.wezterm.terminfo ];

全部のterminfoが欲しいわけではないので、僕の環境ではこれで十分。使っていないパッケージのビルドが始まったら、まず nix why-depends --derivation で経路を見てみるとよさそうです。