[Nix-dev] Another way to configure packages using flags ..

Marc Weber marco-oweber at gmx.de
Wed Aug 15 05:03:17 CEST 2007


Thanks Michael Raskins for your inspiring work..

However some things seemed to be complicated to me..

So I've worked out another design similar to yours:

The key function is
getArgs which simply is some kind of map replacing all occurences of
attribute names with the attribute values.
Thus [ "dep1" "dep2" ] becomes [ <derivation dep1> <derivation dep2> ]
If a dependency (requirement) hasn't been supplied an exception is
thrown. Thus you no longer need an extra call checkArgs ..
The second advantage is that you can no only pass a set of args but also
a set of configure args (see confArgsReqs).. Then you won't get a set of
derivations taken from args but a set of configure argument strings..
flatten the set and you are done..

Any comments?

I haven't tested it yet so it may still contain many bugs..
But I'll test it within the following hours when adding fltk..

Marc Weber

  # much shorter but perhaps slower?
  #uniqList = xs :  
    #if xs == [] then []
    #else  let 
        #h = __head xs;
        #t = __tail xs;
        #in [h] ++ uniqList ( filter ( x : x != h ) t );


  # flattenListAndSet {a=x; b=[1 2];} -> [ x 1 2]
  # flattenListAndSet x -> [x]
  flattenListAndSet = x :
    if (__isAttributeSet x) then
      flattenListAndSet ( map ( attr : __getAttr attr x) (__attrNames x) )
    else if (__isList x) then fold (x: y: (flattenListAndSet x) ++ y) [] x
         else [ x ];

  # returns true if all list elements are true
  all = fold (x: y : x && y) true;

  # replaces the names of args by the arguments
  # throws exception if arguments are missing.
  getArgs = flags:  # the flags to be used ["opengl" "de" "us" ]
            reqs:   # an attribute set like the one given in the example below
            args:   # the dependencies passed as recordset as sugessted by Michael Raskin
    let attrsFromArgs = msg : attrs :
          map ( attr : if (__hasAttr attr args) 
                       then (__getAttr attr args)
                       else throw (msg attr) 
              ) attrs;
    in { mandatory = attrsFromArgs 
                ( attr: "mandatory argument ${attr} not in argument list!" ) 
                ( getAttr ["mandatory"] [] reqs);
         # only added if flag is set
         conditional = map 
          ( flag: if (__hasAttr flag reqs.flags) 
                  then attrsFromArgs 
                        ( attr: "argument ${attr} needed by flag ${flag} missing!" ) 
                        (__getAttr flag reqs.flags)
                  else throw "unkown given flag ${flag}!"
          ) (uniqList flags);
       };

  
#      # alternative proposal (Marc Weber), example:
#      # advantages: attribute sets are used, 
#      #             list iterations to check flags are avoided (might be faster ?)
#      $             should be self-explanatory
#      # its easy to get configure flags depending on the given flags as well
#
#      # default.nix:
#        args: let
#          reqsDeps = 
#            { # have to be passed if the flag exists
#              flags : { opengl = [ "opengl" "otherlib" ]; 
#                        directx = [ "directx" "winlib" ];
#                        de = [ "spellde" ];
#                        us = [ "spellus" ];
#                      };
#             # these deps have to be passed in any case
#             mandatory : [ "gnused" ]; 
#             # these deps will be recognized by the builder automatically when passed
#           };
#          confArgsReqs =
#           { flags : { opengl = [ "--with-opengl" ]
#                       directx = [ "--with-directx"];
#                       de = []; us = [];
#                     } };
#          in args.stdenv.mkDerivation {
#            [...]
#            buildInputs = flattenListAndSet ( getArgs args.flags reqsDeps args );
#            configureFlags = intersperse " " ( flattenListAndSet args.flags confArgsReqs args );
#            [...]
#          }
#
#      # all-packages.nix:
#        foo = (import [..]) {
#          inherit opengl otherlib directx winlib spellde spellus gnused;
#          flags = ["opengl" "spellde"];
#        }

#     you can realize optional dependencies ( you don't want to create/ add a flag for each) by
#     adding them to the mandatory list only if they are passed
#     mandatory : [ "gnused" ] ++ filter ( flag: __hasAttr flag args ) [ "optional1" "optional2" ];



More information about the nix-dev mailing list