After quiet some time of contributing packages and fixes to Nixpkgs, I came to the conclusion that multiple outputs are not implemented good enough. I’d like to hear some opinions / experiences around this. Here’s my own:
I once tried to package a library which installs cmake files, headers and shared objects. The cmake files referenced the full paths of the headers and the shared objects. From the library’s Makefile
’s prespective, it installs everything to the prefix ($out
). However, if you set outputs
, after all the files are installed, we move the headers to $dev
and the libraries to $lib
etc at the fixupPhase
.
How could our package know that it actually installs it’s files to different prefixes? I’m just curios what was the expectation out of this idea.
When I tried to use that library with the outputs split, and use it as a dependency for another package, I found out that the package didn’t find the cmake files of the library which are found at $out/share/<lib-name>/cmake
and not as expected by multi-outputs.sh
- in $out/lib/cmake
. Even when I managed to tell the package where exactly to find the library’s cmake files, the build still failed because the cmake files pointed to where the headers were originally installed - to the original $out
and not to ${<lib-name>.dev}
.
Today, I tried to improve a little bit a closure size issue of a package that splits outputs and I got hit by this error which I can’t even explain.
What’s adding to the frustration, is that it’s hard to debug these shell errors because they happen at the end of the build and you have no idea what shell function exactly failed - there’s no context to the errors.
If I were to design this feature for our ecosystem from the ground up, I would do this:
- Set the same value for
$dev
,$out
,$lib
etc for all packages. - Teach Nix itself, to distinguish between outputs - for example:
-
$out/include
should be downloaded only if you want to build something with this library. -
$out/share/man
should be downloaded only if you use this package directly.
-
- Make Nix itself, download only needed files from cache.nixos.org according to the context of the request:
- If it’s
nix-env -iA
ornixos-rebuild
then download only the actually needed outputs. - if it’s
nix build
ornix-shell
, download everything unless told otherwise.
- If it’s
I believe we can reach closure size decreases we have never dreamed of with this approach.
Is there an implementation problem I’m not seeing here?