[Nix-dev] [***SPAM***] Dynamic Dependency Management by Calling External Programs from Nix

Shea Levy shea at shealevy.com
Tue Oct 25 01:35:16 CEST 2011


Hi all,

For the most part, the nix expression language is extremely good at 
expressing the dependency relationship between derivations. 
Unfortunately, there are some cases where the requirement that the 
information required to resolve dependencies can only come from 
pre-existing text files (either through importing other nix expressions 
or builtins.readFile) leads to some real problems.

The obvious example is the language-specific package managers. The fact 
that a tool like cabal2nix can be used to do nearly all of the 
maintenance of Haskell packages means that we suddenly have a set of nix 
expressions that are more like "object files" than source code: They can 
be completely automatically generated, and if they need to be edited 
manually, it's considered a bug in cabal2nix and any changes will be 
overwritten on the next autogeneration (I believe Peter's policy is that 
if people need to change the generated files they should and then he 
will review and modify cabal2nix accordingly, but that is a VERY brittle 
maintenance procedure). There's a reason development repositories 
include configure.ac and Makefile.in but have configure and Makefile in 
their ignores, and it's the same reason they include .c files but have 
.o files in their ignores: The former can automatically generate the 
latter and will overwrite any changes when that occurs, and if there is 
something wrong with the latter the solution is to modify the former and 
regenerate, not change the latter.

There are some problems that are even more cumbersome to solve with 
today's limitations. For example, right now I'm working modularizing the 
kernel derivations by making separate derivations for the bzImage and 
each module. Most users will want to build the bzImage and all of the 
modules, which is easy enough, but some users might want to just build 
the modules they need to have a smaller system and shorter build for 
kernels that aren't available through substitutors. Suppose I want to 
build just ext4 for my kernel. How do I know which other modules I need 
on my system for ext4's dependencies to be satisfied? It's not too 
difficult to write a tool that, given a kernel build tree, generates a 
dependency tree for all of the in-tree modules that can be built, but 
that's a lot of bloat to add for each kernel version currently in 
nixpkgs, and of course anyone wanting to compile a custom kernel with 
different features built-in or as modules will need to generate the 
dependency tree themselves before they build their modules, which puts 
an explicit dependency on an external tool for end-users who are not nix 
devs to use nixpkgs, which is IMO a big problem.

So I'd really like to see one of two solutions implemented (I'll do the 
implementation myself if Eelco is willing to consider accepting these 
solutions) in nix (possibly with an explicit command-line flag or 
nix.config setting to enable them, like we have with enableParallelBuilds):

 1. builtins.exec. This builtin would take a string and would evaluate
    to a string. It would essentially call system() on its argument and
    evaluate to the output put to stdout by that command.
 2. Expand builtins.readFile to be able to read files in another
    output's path. Right now you can't do builtins.readFile
    "${derivation}/file", since that would require doing a nix-store
    realisation while instantiating. The advantage to this approach is
    that, unlike with builtins.exec, the nix-* commands would still be
    limited to affecting only files in the store. The disadvantage
    relative to exec is that dynamic downloads wouldn't (or shouldn't)
    be possible: you shouldn't need network access for non fixed-output
    derivations, so you need to know the hash ahead of time. Still, I
    think that disadvantage might actually be a good thing, and would
    turn the maintenance of, e.g., the Haskell packages into maintaining
    a single manifest file that contains only the info that cabal2nix
    would have pulled from the network (hashes+urls of .cabal files, and
    hashes of the sources if .cabal files don't contain that, most
    likely), then updating the set of Haskell packages would mean
    updating the url+hash of the manifest file, instead of every single
    nix expression that corresponds to an updated package.

Thoughts?

Cheers,
Shea Levy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.science.uu.nl/pipermail/nix-dev/attachments/20111024/862d331c/attachment.html 


More information about the nix-dev mailing list