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

Michael Raskin 7c6f434c at mail.ru
Wed Aug 15 13:27:20 CEST 2007


Marc Weber wrote:
> 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 ..
And what about flags depending on flags? It may be wort its price sometimes.

> 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..
Yes, it is a nice feature, it can be merged into any design though.

>   # 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 );
Slower in case of frequent repetitions; also I'd like to have isInList
anyway.

>   # returns true if all list elements are true
>   all = fold (x: y : x && y) true;
Isn't having just one declaration of logicalAND theoretically cleaner as
we'll have a guarantee that Nix doesn't create repeating functions?

>   # 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);
>        };

Also it looks that you cannot make a dependency "optional, but also
required by this flag".

> #      # 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" ];
Well, adding purely optional arguments to mandatory list is a bit
counter-intuitive. And also it blocks going from calculations to
declarations where we can do it. Maybe it is better to have a list
'optional' and remove non-supplied arguments  from it.




More information about the nix-dev mailing list