[Nix-dev] Overriding packages (was Re: Kernel headers)

Eelco Dolstra e.dolstra at tudelft.nl
Thu Aug 14 16:48:15 CEST 2008


Hi,

Michael Raskin wrote:

> Pjotr Prins wrote:
> | I have a basic question. I have created a Kernel_headers expression for
> | 2.6.18. How do I override the NIX build without changing:
> |
> |    kernelHeaders = kernelHeaders_2_6_23;
> |
> | to:
> |
> |    kernelHeaders = kernelHeaders_2_6_18;
> |
> | In other words, what switch to I pass nix-build/nix-env -i to
> | ascertain headers 2.6.18 without changing the default line in
> | all-packages.nix? I would like to keep the SVN tree generic.
> 
> Write something like
> 
> kernelHeaders =
> ~  let kernelHeadersVersion = getConfig
> ~                               ["kernelHeaders" "version"]
> ~                               "2.6.23";
> ~  in
> ~    if kernelHeadersVersion == "2.6.23" then
> ~      kernelHeaders_2_6_23 else
> ~    if kernelHeadersVersion == "2.6.22" then
> ~      kernelHeaders_2_6_22 else
> ~    if kernelHeadersVersion == "2.6.18" then
> ~      kernelHeaders_2_6_18 else
> ~    abort "Unknown kernelHeaders version.";

I brainstormed with Andres a while ago about how to make Nixpkgs more 
configurable without polluting it with zillions of options, which is related to 
this.

Rather than having messy options like this (which would have to grow to include 
each version), it would be much cleaner if you could override packages globally 
in ~/.nixpkgs/config.nix, e.g. something like

   {
     overrides = pkgs: {
       kernelHeaders = pkgs.kernelHeaders_2_6_18;
     }
   }

where "pkgs" is the original set of packages.  (As an added benefit, we wouldn't 
have to have config options for every obscure feature, since you could always 
define your own override, like

   {
     overrides = pkgs: {
       subversion = import .../subversion {
         stdenv = pkgs.overrideGCC pkgs.stdenv pkgs.gcc34;
         bdbSupport = true;
         httpServer = true;
         sslSupport = false;
         ... more silly options ...
       };
     };
   }

if for some strange reason you want Subversion compiled with a non-standard GCC 
and non-standard options).

The problem is that this isn't currently possible, since all the references to 
"kernelHeaders" in all-packages.nix would continue to reference the original 
value.  That is, even if all-packages.nix looked like this:

   let

     pkgs =
       rec {
         kernelHeaders = kernelHeaders_2_6_23;
         kernelHeaders_2_6_18 = ...;
         kernelHeaders_2_6_23 = ...;
         somePackage = ... {
           inherit kernelHeaders;
         };
       } // (getConfig "overrides" {}) pkgs;

   in pkgs

it wouldn't work because the "rec" causes the value of kernelHeaders_2_6_23 to 
be substituted in somePackage, even though the "//" then replaces the 
kernelHeaders attribute by kernelHeaders_2_6_18.  OTOH, if we didn't use a rec 
but wrote all-packages.nix like this:

   let

     pkgsFun = pkgs:
       { # <-- no rec
         kernelHeaders = pkgs.kernelHeaders_2_6_23;
         kernelHeaders_2_6_18 = ...;
         kernelHeaders_2_6_23 = ...;
         somePackage = ... {
           inherit (pkgs) kernelHeaders;
         };
       } // (getConfig "overrides" {}) pkgs;

     # Tie the knot.  This works thanks to laziness.
     pkgs = pkgsFun pkgs;

   in pkgs

it would work.  But this has the downside that you have to write "pkgs" 
everywhere (so it would make all-packages.nix more verbose).  It might seem that 
writing pkgsFun as "pkgsFun = pkgs: with pkgs; {...}" would solve this, but then 
you get an infinite recursion as "with" isn't lazy enough.

Maybe we need some language extension to allow attributes in recs to be 
overriden properly...

-- 
Eelco Dolstra | http://www.st.ewi.tudelft.nl/~dolstra/



More information about the nix-dev mailing list