Install build dependencies just like normal installation

Hey all,

Customary note: Discovered and started playing with nix since a few days - noob alert!

What is the fundamental difference between building of a “buildInputs” vs building of a package directly? More specifically, why can’t I see man entries for buildInputs but I can see them if I installed them directly?

E.g (assume I’ve man-db installed in the system already)

nix profile install nixpkgs#feh
man feh # Works, the man pages for feh are brought in by the installation above

however:

# flake.nix
{
  outputs = { self, nixpkgs }:
  let
    n = nixpkgs.legacyPackages."aarch64-linux";
  in
  {
    packages."aarch64-linux".default = n.stdenv.mkDerivation {
      buildInputs = [ p.feh ];
      ...
    };
  };
}

# Now run:
nix profile install .

# I can see /nix/store/<hash>-feh/bin/feh just like before but this time
# it's minimalistic and there are no man pages for it for e.g. in nix store anywhere.

Is there something I can do to ensure the installation of dependencies (or buildInputs) is as complete as if it were being directly installed (with man pages and all the glitters)?

FWIW, this too compiles in the man pages:

# flake.nix
{
  outputs = { self, nixpkgs }:
  let
    n = nixpkgs.legacyPackages."aarch64-linux";
  in
  {
    packages."aarch64-linux".default = n.feh;
  };
}

# Now run:
nix profile install .

# I can see the man pages brought in too in /nix/store/

How can I get this behaviour for dependencies specified in the buildInputs too?

Eh after staring at and comparing the derivations of various packages, I think I understand what’s happening.

So some packages like nixpkgs#maim for e.g don’t have outputs attribute supplied to their mkDerivation function and dump everything in just one place in the nix store /nix/store/<hash>-maim/{bin,share,...etc} and for those the man pages are indeed built even if maim was in buildInputs for some other package.

However some others like nixpkgs#feh for e.g. have outputs = [ "out" "man" "doc" ]; etc and for those the only thing that gets generated due to them being present in buildInputs of some other flake is whatever is in their out output, whereas if you did nix profile install then all the outputs get dumped into /nix/store/... under various paths suffixed with the corresponding output (except for out which doesn’t have a suffix).

That’s why the man pages for feh as a value in buildInputs of some other flake’s mkDerivation was not being put in /nix/store/<hash>-feh-man.

OK now that I’ve spent an hour getting to the bottom of this, I suppose my next step will be to find out how to make a nixpkgs#foo given as buildInputs of some other flake.nix’s mkDerivation dump all its outputs and not just its out path in the nix-store. Probably a new question but I’ll leave it here before creating a new post in-case someone knows this off the top of their head.

I think your problem is that while nix downloads buildInputs, it usually doesn’t expose them. They will be there, but without set changing the PATH. (that is not true for all packages).

Like:

  1. interpret your nix file
  2. download the source of your package (sometimes is in the same dir)
  3. download the nix files of your dependencies (usually nixpkgs or other inputs)
  4. build the dependencies
  5. copy your dependencies to /nix/store/
  6. build your package (hard coding the /nix/store/ of dependencies)
  7. copy your package build outputs¹ to /nix/store/
  8. configure your profile (environment) to know the path of your package (not of dependencies).

Sometimes it only requires the bin output so it doesn’t keep the others (man, docs, dev).

¹ That is confusing, flakes has “outputs” (packages, nixos configs, etc) but they aren’t your package ‘outputs’ (out, bin, dev, doc, etc).

Flakes outputs ~ collection of packages
Package outputs ~ subpackages of our package.
Flakes ~ collection of Inputs (other flakes) and Outputs (packages or configs)
Derivation ~ “Package” (mkDerivation ~ “make package”).

Anyway, there are two-way to configure your system, or profile, or dev environment with nix, Imperative or Declarative:

  • imperative: nix profile install nixpkgs#somePackage (for every package you wanted)
  • declarative: have a .nix file with your packages list and run a single “install”

There are utility functions in nixpkgs lib to do it declaratively, but usually people here just use:

  • DevEnv - Very Easy: for dev projects (won’t mess with your system or user)
  • HomeManager - Easy: for your user profile (won’t mess with your system)
  • System Manager - Medium: for your distro (at least you can resort to your distro packages)
  • NixOS - Hard: for new distro (the brave new world)
  • etc - Asian: for emotional damage (“stop it, get some help”).

Check this diagram