[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