Naively, builtins.break is not very easy to use. Because of laziness, writing break a often will not expose the value of a, or any of the things you might want to look at that are in scope where you put the call to break. This happens because break a gets triggered only when when it actually needs to be evaluated, which often times is inside the body of some function, not in the scope you actually wanted to inspect. Recently, I have discovered a trick that makes debugging so much nicer:
Instead of using
break <expr>
use
(_: break _) <expr>
(the _ is an arbitrary argument name and can be replaced with whatever you like)
Because Nix uses closures, this little lambda exposes everything that was in scope in the place it was defined, no matter where it’s being evaluated, and _ will give you the value of <expr>.
{ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
outputs = { nixpkgs, ... }@inputs:
with builtins;
let pkgs = nixpkgs.legacyPackages.x86_64-linux; in
{ packages.x86_64-linux.a =
let a = 1; in
pkgs.writeText "foo" (break "bar");
packages.x86_64-linux.b =
let a = 1; in
pkgs.writeText "foo" ((_: break _) "bar");
};
}
$ nix build .#a --debugger
info: breakpoint reached
at /nix/store/9669y1hx4b5c7678fkyjghlns14pd7x5-source/flake.nix:8:31:
7| let a = 1; in
8| pkgs.writeText "foo" (break "bar");
| ^
9|
Starting REPL to allow you to inspect the current state of the evaluator.
Welcome to Nix 2.11.0. Type :? for help.
nix-repl> :env
Env level 0
static: outputs commonAttrs outputsList outputToAttrListElement
Env level 1
static: drv
Env level 2
static: passthru
Env level 3
static: condition
Env level 4
static: overrideDerivation makeOverridable callPackageWith callPackagesWith extendDerivation hydraJob makeScope makeScopeWithSplicing
Env level 5
static: lib
Env level 6
builtins true false null fromTOML fetchTree fetchTarball fetchGit fetchMercurial scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString derivation
nix-repl> error: quit the debugger
(use '--show-trace' to show detailed location information)
$ nix build .#b --debugger
info: breakpoint reached
at /nix/store/9669y1hx4b5c7678fkyjghlns14pd7x5-source/flake.nix:12:35:
11| let a = 1; in
12| pkgs.writeText "foo" ((_: break _) "bar");
| ^
13| };
Starting REPL to allow you to inspect the current state of the evaluator.
Welcome to Nix 2.11.0. Type :? for help.
nix-repl> :env
Env level 0
static: _
Env level 1
static: a
Env level 2
static: pkgs
Env level 3
static:
Env level 4
static: inputs nixpkgs
Env level 5
builtins true false null fromTOML fetchTree fetchTarball fetchGit fetchMercurial scopedImport import isNull break abort throw derivationStrict placeholder baseNameOf dirOf removeAttrs map toString derivation