Building/fetching only some outputs

When linking into a profile, only some outputs of a derivation are installed. For example, of the nix derivation’s outputs, only “out” and “man” are linked:

$ nix-env --query --installed --out-path nix
nix-2.3  man=/nix/store/xk6lyzlsc76yi3n7m6j2f9kycb9yd0l9-nix-2.3-man;/nix/store/8cm9jd8mvh0z8f0z93zm4ln76bab8hfg-nix-2.3

…but this derivation has more outputs than that, and they’re all installed when I run nix-env -i:

$ nix-env -iA nixpkgs.nix
installing 'nix-2.3'
these paths will be fetched (0.29 MiB download, 1.20 MiB unpacked):
  /nix/store/g733d0f6x7x86lba3qslmi2z9lbqnlw6-nix-2.3-doc
  /nix/store/mjcakd87hyh2j22nv8kdq5bmr2fhq1ga-boehm-gc-8.0.4-dev
  /nix/store/psgidfpja44z2xsb0wylag8kgwdcm8v4-nix-2.3-dev
...

If I immediately run nix collect-garbage and then re-run the same nix-env -iA nixpkgs.nix command, those three paths will be fetched again. I’d like to find a way to only fetch the paths specified by meta.outputsToInstall. I tried nix-env -iA nix.man -A nix.out, but it still fetches all outputs.

I tried this too:

$ nix-instantiate '<nixpkgs>' -A nix
/nix/store/fi3lzds3xaqcld5vwzry0rxzjwzvxxsp-nix-2.3.drv
$ drv=/nix/store/fi3lzds3xaqcld5vwzry0rxzjwzvxxsp-nix-2.3.drv
$ nix eval '(import <nixpkgs> {}).nix.meta.outputsToInstall'
[ "out" "man" ]
$ nix-store --realise "$drv\!out" "$drv\!man"
/nix/store/8cm9jd8mvh0z8f0z93zm4ln76bab8hfg-nix-2.3
/nix/store/xk6lyzlsc76yi3n7m6j2f9kycb9yd0l9-nix-2.3-man
$ nix-env -i /nix/store/8cm9jd8mvh0z8f0z93zm4ln76bab8hfg-nix-2.3 /nix/store/xk6lyzlsc76yi3n7m6j2f9kycb9yd0l9-nix-2.3-man
(success)

This kind of works, but the problem is that Nix doesn’t really seem to cart around all of the important metadata when I get out of expression-land and into derivation-file-land. Notably, meta.priority vaporizes, so I can’t create a profile all in one shot if any paths have conflicting entries (because I have to install one first, then use --set-flag, then install the other).

So basically:

I can’t find a way to install only the meta.outputsToInstall of a derivation (without realising all of the outputs) in a way that preserves meta.priority when I ultimately construct my profile. Am I missing something?

I guess there are two main things that are really surprising to me:

  1. Instantiating an expression as a derivation seems to be lossy, discaring most?/all? of meta.*.
  2. When provided an expression attr, nix-env will realise all outputs, and link only those selected by meta.outputsToInstall, with neither of these being configurable via nix-env.
1 Like

In the end, buildEnv is close enough to what I want that I’ll just use it, but it’s too bad that nix-env isn’t just a hair more configurable.