Confusion about dependencies for a package in a flake

Hello all,

I have a fairly simple package which is defined (alongside many other packages) within a flake. If I run, say, nix build .#simple_package, then it builds fine, but (if from scratch) also takes a good long time to build python310 as well. As far as I can see, none of the inputs of this flake have a dependency on python, so I’m not quite sure where this dependency is coming from.

If I try nix why-depends .#simple_package github:nixos/nixpkgs#python310 then it tells me that python is not a dependency of simple_package.

However, if I do nix show-derivation --recursive .#simple_package, then I get a JSON which has its keys not just simple_package, but lots of other stuff as well (including a python dependency).

So I’m theorizing that
a) simple_package does indeed not have a python dependency, but
b) some other package within the flake does have a python dependency, and
c) nix show-derivation shows output for the whole flake, even if told to show output for only a single package within the flake, and (more speculatively)
d) my nix build .#simple_package command somehow requires that other packages in the flake be evaluated - though this doesn’t fit with my existing understanding of flakes, which is that the outputs are lazily evaluated.

If I anyone can cast some light on this then I’d be grateful.

1 Like

This will check for a dependency between the flake’s simple_package and the build of python currently on nixpkgs master branch. There’s no reason to believe that’s the version of nixpkgs your flake is building simple_package against.

Yes, this was not clear from that example, but I am aligning the nixpkgs flake here with what I use in the flake.nix for simple_package - ie the flake.nix for simple_package starts with:

inputs = {
    nixpkgs.url = github:NixOS/nixpkgs/nixos-21.11;
...

then in the body of the flake, pkgs = nixpkgs.legacyPackages.${system};

And just to be sure, by “aligning” you don’t mean that you’re simply using github:NixOS/nixpkgs/nixos-21.11#python310 on the command line, right? Because that also doesn’t necessarily refer to the same version of nixpkgs, if the channel has updated since your lock file was made.

I did mean that, but even when aligning the revs between the simple_package flake and the nixpkgs flake on github, I still get the same result, ie that python310 is not a dependency of simple_package.

NB if your first reaction to this is “that shouldn’t happen”, then feel free to say so, I only have a tentative understanding of the expected behaviour here so that’s still a useful data point for me.

Even aligning revs may not work since the python derivation may be overriden somehow. The most reliable way to find out would be to query the package until you can find the exact python output in question. Does nix path-info -r .#simple_package show the python output in the list?

That’s a useful command, I wasn’t aware of it at all. When I run this, it gives me two bits of output:

  • the paths of all the derivations in the flake, and
  • the paths of all the dependencies.
    I do see python in the list of dependencies, which implies that something in that flake has python as a dependency, but it doesn’t unfortunately tell me which package(s) are the ones that need python.
    It slightly surprises me that it’s showing everything, because I did ask for only .#simple_package (like in your example).

You probably need to share your flake.nix for us to be able to help much more. It sounds like your expression for simple_package is doing a lot more than you think it is.

I will attempt to do so but it’s for work, so it needs a little redacting. For my own understanding, could I ask what leads you to believe that the simple_package expression is at fault?

Because you said you were surprised that nix path-info -r .#simple_package is listing all the derivations in the flake. It doesn’t do that on its own; they must in fact be dependencies that you are not expecting.

  1. As you already have been told, github:…#python310 might not be the same python as is seen by your derivation, often but not always, you can use --inputs-from to mitigate, though that only works if the derivations get used as they are and not altered by any of the known mechanisms like override or overrideAttrs
  2. show-derivation tells you about build inputs, why-depends only considers runtime dependencies.
  3. As path-info told you that there is a runtime dependency to python somehow, you can use exactly that path for why-depends.

Thank you, this is helpful. Using this approach, I’ve done some further investigation. On a fresh setup (within a docker container, specifically), I run nix path-info -r .#simple_package. This gives me output of the form:

these 3 derivations will be built:
  /nix/store/04g4dm5y481avrs3wb82cl1nwndha4id-package1.drv
  /nix/store/fdnmsazfa2kymcd6pin2hihvrs9kh5cx-package2.drv
  /nix/store/y0ldhxvbj9rix2wwdbx9dgk5bgma8fn6-simple-package.drv
these 86 paths will be fetched (157.19 MiB download, 650.25 MiB unpacked):
  /nix/store/0dqrzslb583fg9djf9hyjxxcx7vfmqhd-ed-1.18
  /nix/store/7wpr947w9a5wsy6bfddw8vrg3vcw8qd6-python3-3.10.5-env

… with python appearing in the second list here, of paths to be fetched.
Both package1 and package2 are real dependencies of simple_package, so the derivations-to-be-built list here looks correct.

If I then investigate using why-depends, I can see that eg package1 is a dependency of simple_package, which makes sense:

$ nix why-depends /nix/store/y0ldhxvbj9rix2wwdbx9dgk5bgma8fn6-simple-package.drv
/nix/store/04g4dm5y481avrs3wb82cl1nwndha4id-package1.drv
/nix/store/y0ldhxvbj9rix2wwdbx9dgk5bgma8fn6-simple-package.drv
└───/nix/store/04g4dm5y481avrs3wb82cl1nwndha4id-package1.drv

Python is not a dependency of simple_package:

$ nix why-depends /nix/store/y0ldhxvbj9rix2wwdbx9dgk5bgma8fn6-simple-package.drv /nix/store/7wpr947w9a5wsy6bfddw8vrg3vcw8qd6-python3-3.10.5-env
'/nix/store/y0ldhxvbj9rix2wwdbx9dgk5bgma8fn6-simple-package.drv' does not depend on '/nix/store/7wpr947w9a5wsy6bfddw8vrg3vcw8qd6-python3-3.10.5-env'

but neither is it a dependency of any of the other direct dependencies, eg

$ nix why-depends /nix/store/04g4dm5y481avrs3wb82cl1nwndha4id-package1.drv /nix/store/7wpr947w9a5wsy6bfddw8vrg3vcw8qd6-python3-3.10.5-env
'/nix/store/04g4dm5y481avrs3wb82cl1nwndha4id-package1.drv' does not depend on '/nix/store/7wpr947w9a5wsy6bfddw8vrg3vcw8qd6-python3-3.10.5-env'

So it is still unclear to me why python is being fetched here.

Note that why-depends only describes runtime dependencies. Which makes it sound like python is a build time dependency. You can use why-depends --derivation to investigate build time dependencies

OK, this gets me straight to the answer. auto-patchelf-hook is a dependency that itself depends upon python. Which is a shame, because it’s slowing things down quite a lot, but it’s good to know how to diagnose this, so thank for your help.

This is not the relevant output of path-info!

You need to make sure that you have built the path first, or path-info will error out:

$ nix path-info -r nixpkgs#hello
this path will be fetched (0.04 MiB download, 0.17 MiB unpacked):
  /nix/store/i9p5qqw7mbs9jhv871v3fzqw6s97npm5-hello-2.12
error: path '/nix/store/i9p5qqw7mbs9jhv871v3fzqw6s97npm5-hello-2.12' is not valid

After a build you get a more meaningful and appropriate information:

$ nix build nixpkgs#hello
$ nix path-info -r nixpkgs#hello
/nix/store/gi4zwjfcyqqwzzj6d76a1adfdzlrscjc-libunistring-1.0
/nix/store/fsxbvxgyycq9qh5bzkij573mj75hq7wp-libidn2-2.3.2
/nix/store/k56d9sk88pvrqhvwpa6msdf8gpwnimf6-glibc-2.34-210
/nix/store/i9p5qqw7mbs9jhv871v3fzqw6s97npm5-hello-2.12

When built, I still do not see python among the list of paths for simple_package reveaeld by nix path-info (nor do I see auto-patchelf-hook), but I presume that this is because python is a build-time rather than run-time dependency. So far the only way to have nix acknowledge python as a dependency is by nix why-depends --derivation ... .