nix debug broken package build

2023-09-07 ยท 2 min read

This technique will add a breakpointHook to the package so that when a build step fails, it'll preserve the build environment and allow you to enter the sandboxed build container for inspection.

On the builder, install cntr from nixpkgs or use it in an ephemeral shell:

$ nix shell nixpkgs#cntr

In the package, add breakpointHook as a nativeBuildInputs.

{ # ...
, breakpointHook
}:
  nativeBuildInputs = [
    breakpointHook
  ];
}

When the build fails, it'll print out something like:

$ nix build --print-build-logs .#sgx-sdk

sgx-sdk> build failed in buildPhase with exit code 2
sgx-sdk> To attach install cntr and run the following command as root:
sgx-sdk>    cntr attach -t command cntr-/nix/store/5hiwc8m04zd00mb3ghfv9mwjmqv3qajv-ripgrep-1.6

[1/0/1 built] building ripgrep-1.6 (buildPhase)

The build will "hang" while we inspect it. Once we CTRL-C it, everything will get cleaned up, so run the following in another shell instance. To enter the build container, just copy the command (with sudo, since it requires root permissions):

$ sudo cntr attach -t command cntr-/nix/store/5hiwc8m04zd00mb3ghfv9mwjmqv3qajv-ripgrep-1.6

[nixbld@localhost:/var/lib/cntr]$ cd build/source

The initial shell cntr drops you in still has all your system tools available (git, nvim, etc). Use this shell to do all your editing and file munging. Once that's done, test the build in the fully isolated build environment:

[nixbld@localhost:/var/lib/cntr]$ cntr exec
bash-5.2$