NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.8k stars 1.52k forks source link

Does nix why-depends really have to build all packages? #5217

Open davidak opened 3 years ago

davidak commented 3 years ago

Describe the bug

I think it should be able to get the dependency information from nixpkgs/channel.

Steps To Reproduce

[davidak@gaming:~]$ NIXPKGS_ALLOW_INSECURE=1 nix why-depends nixpkgs.displaycal nixpkgs.python2.pkgs.pillow
'nixpkgs.displaycal' does not depend on 'nixpkgs.python2.pkgs.pillow'
[6 built, 246 copied (1010.4 MiB), 265.2 MiB DL]

Expected behavior

simple text output instead of needing to build 1 GB of packages

nix-env --version output

nix-env (Nix) 2.3.15

Ericson2314 commented 3 years ago

Nix isn't really set up to allow downloading the metadata without the data. I would like to fix that more generally rather than writing some special cases for this command. It's a lot of work, but CA derivations + the IPFS stuff could help as it becomes quite clear how to "crawl the spine" without downloading the fat leaves from that perspective.

davidak commented 3 years ago

With the shown command i would expect Nix to use my channel and the evaluation to have all the dependency metadata without having to build the packages. Is that too naive? What metadata is needed here?

zimbatm commented 3 years ago
$ nix why-depends /nix/store/bhv855cc7a44yz6r5pm4vga9qx66zw91-hello-2.10 /nix/store/js5xyvpmw5x6n29b2cg6k0gh1nxaw98j-libidn2-2.3.2
/nix/store/bhv855cc7a44yz6r5pm4vga9qx66zw91-hello-2.10
└───bin/hello: …...................../nix/store/9bh3986bpragfjmr32gay8p95k91q4gy-glibc-2.33-47/lib/ld-linux-x86-…
    → /nix/store/9bh3986bpragfjmr32gay8p95k91q4gy-glibc-2.33-47
    └───lib/libc-2.33.so: …l_valid_timeout (tv)./nix/store/js5xyvpmw5x6n29b2cg6k0gh1nxaw98j-libidn2-2.3.2/lib/libidn2.so.>
        → /nix/store/js5xyvpmw5x6n29b2cg6k0gh1nxaw98j-libidn2-2.3.2

The current implementation shows which file in the derivation output contains the reference. Even if the cache has the dependency graph between derivations, it wouldn't be able to show the exact location in the files. That feature is quite useful when trying to prune a dependency tree.

davidak commented 3 years ago

So a task would be to implement it in a way that the dependency graph is used when i input packages instead of paths.

lilyball commented 2 years ago

I believe the problem is why-depends defaults to computing runtime closure, which requires having the actual closure. If you want to check derivation inputs (e.g. why changing package A causes package B to be rebuilt) then pass the --derivation flag.

Ericson2314 commented 2 years ago

https://github.com/NixOS/rfcs/pull/92/files point towards making --derivation less necessary for some things, though those details are admitted TBD.

lilyball commented 2 years ago

That RFC is interesting, but doesn't it just affect build-time dependencies? Surely nix why-depends still needs the runtime closure (or at least, metadata derived from the runtime closure), and cannot function without either actually building the packages or being able to download this information from a binary cache?

Ericson2314 commented 2 years ago

@lilyball see the part about syntax. If we have drvPath!* vs drvPath, we don't need --derivation for these most primitive sorts of arguments. I think this was also the case where the behavior of why-depends was most surprising.

lilyball commented 2 years ago

@Ericson2314 That RFC talks about using e.g. nix build /nix/store/…foo.drv vs nix build /nix/store/…foo.drv!*, where the former means the derivation itself is the goal, and then says this means we can remove --derivation. But surely this isn't proposing that nix build nixpkgs#hello should build the .drv file rather than the output? Not that it's clear to me how --derivation affects this anyway (as nix build today seems to build the output regardless of the --derivation flag), but the flag does clearly affect other tools (e.g. nix path-info nixpkgs#hello and nix why-depends).

We already have ways to reference outputs (e.g. nixpkgs#hello.out), which makes me wonder if the syntax isn't inverted and that we shouldn't instead just have it be <installable> [ "!drv" ] so e.g. nixpkgs#hello!drv means "reference the derivation instead".

Ericson2314 commented 2 years ago

@lilyball the ! syntax is just for store paths. It reflects what those arguments look like internally (see the DerivedPath type) so we have a primitive / low-level way capable of expressing all possible arguments.

For high level I do in fact agree with your sugestion. nixpkgs#hello.drvPath exists, and so nix build nixpkgs#hello.drvPath almost works. We should look into making it actually work! Only after such high level things would we actually be able to get rid of --derivation

lheckemann commented 2 years ago

nix why-depends no longer defaults to showing file contents (this is now guarded behind --precise), so in principle fetching the paths is no longer necessary, since it can be worked out from the narinfos alone. However, it still does fetch the paths for now.