9

Found a lot of sources describing callPackage and some of its internals, but none that refers to it's location. It's like the best kept secret of Nix, and the manuals even seem to be actively avoiding the topic. I could find it given time, but it's a huge repo.

Resources:


The answer actually points to callPackageWith function in customisation.nix, but callPackage itself is defined elsewhere.

toraritte
  • 6,300
  • 3
  • 46
  • 67
  • Just learned that there is also a `callPackages` function (from [Nixpkgs#36354](https://github.com/NixOS/nixpkgs/issues/36354) issue), and basically both are undocumented. – toraritte Oct 28 '19 at 03:52

3 Answers3

14

nix repl can tell you the location where a lambda is defined.

$ nix repl
Welcome to Nix version 2.2.2. Type :? for help.

nix-repl> pkgs = import <nixpkgs> {}

nix-repl> pkgs.callPackage
«lambda @ /nix/store/9hffpjaa2a7djl19ncky7zcvlhyj76dn-nixos-19.03.172396.d740b2ee855/nixos/lib/customisation.nix:108:31»

where the part up to and including nixos is my <nixpkgs>, thus giving you the answer: lib/customisation.nix line 108.

In some cases, it can also report the location of an attribute.

nix-repl> builtins.unsafeGetAttrPos "callPackage" pkgs
{ column = 3; file = "~/src/nixpkgs/pkgs/top-level/splice.nix"; line = 143; }
Robert Hensing
  • 6,708
  • 18
  • 23
  • 2
    Thanks for the added bonus of showing how to find lambda definitions! – toraritte May 14 '19 at 12:28
  • 3
    Just found the `nix repl ''` shortcut to import all Nixpkgs expression on repl startup. – toraritte May 14 '19 at 19:16
  • 1
    one line: `nix repl '' <<< pkgs.callPackage` – milahu Mar 28 '21 at 17:36
  • On the current version of nix (2.12), the path in that lambda actually leads to `callPackagesWith` not `callPackages`. I still can't find anywhere in the nixpkgs source where the top-level `callPackage` attribute is actually assigned (there are many non-top-level definitions). My guess as to the true place is either inside of `makeScope` or `makeScopeWithSplicing` (both inside of lib/customisation.nix) but I'm not sure which is the true source, or how it ends up being added to `pkgs`. So for me this question is still unanswered – Jeff Hykin Feb 04 '23 at 16:11
  • 1
    @JeffHykin, I've updated the answer with a new technique. The `pkgs.callPackage` attribute is defined in `pkgs/top-level/splice.nix` – Robert Hensing Feb 04 '23 at 21:48
2

Despite the lambda output from the other answer, I believe the original value of callPackage is actually defined inside of pkgs/top-level/splice.nix, link here

The reason the path in the lambda doesn't return that^ position is because nixpkgs does some absolutely insane recurisve computation. My understanding is that pkgs is replaced over and over (bootstrapped), and the attributes on pkgs (like callPackages) are replaced multiple times. If you're familiar with fixed point combinators in mathematics, like the Y-Combinator, that is effectively what Nixpkgs is applying until the pkgs stablizes. So pkgs.callPackage is actually some random/dynamic function-argument instead of an attribute that is set directly. And that dynamic function argument is what the lambda-path refers to.

It's like the best kept secret of Nix

I've been reading the source code for 3 years, and it took me at least 5 hours of chopping up a minimized version of nixpkgs (which was a project on its own) in order to figure out that callPackage was actually coming from pkgs/top-level/splice.nix. And finding where it is defined isn't even half the battle for really understanding where it's coming from. So yeah, I'd say its a pretty well kept secret and might still be a secret after this answer since I can still barely claim to understand it myself.

Jeff Hykin
  • 1,846
  • 16
  • 25
1

Before flakes I used nix edit nixpkgs.callPackage and with flakes nix edit nixpkgs\#callPackage.

And it works regardless if it lambda or not. E.g. nix edit nixpkgs\#nix.meta

ony
  • 12,457
  • 1
  • 33
  • 41
  • Never heard of `nix edit`, and just checked out all subcommands with `nix --help`, thanks! It didn't work for `callPackage` however, even though `nix edit nixpkgs.hello` (or any other package) did. (I have version 2.3.10.) – toraritte Apr 18 '21 at 13:34
  • BTW, you don't need the backslash in `nixpkgs#nix.meta` -- `#` is only a comment character in POSIX-family shells when it's at the beginning of a word; in all other positions it's literal. – Charles Duffy Dec 02 '22 at 16:16
  • @CharlesDuffy, I use zsh and it treats `#` for filename globbing. E.g. `echo /bo#t` echoes `/boot`. – ony Dec 07 '22 at 23:15
  • Ah. (Glad I hedged with the "POSIX-family" qualifier; zsh is deliberately noncompliant). – Charles Duffy Dec 11 '22 at 22:36
  • 1
    @ony You should alias `nix` to `noglob nix`! – Diti Feb 18 '23 at 23:22