diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 1b54fd00ea8..137d5dee501 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -676,6 +676,45 @@ rec {
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
else __getAttr n attrs2 # add attribute not existing in attr1
)) attrs1 (__attrNames attrs2);
+
+
+ # example usage:
+ # mergeAttrByFunc {
+ # inherit mergeAttrBy; # defined below
+ # buildInputs = [ a b ];
+ # } {
+ # buildInputs = [ c d ];
+ # };
+ # will result in
+ # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
+ # is used by prepareDerivationArgs and can be used when composing using
+ # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
+ mergeAttrByFunc = x : y :
+ let
+ mergeAttrBy2 = { mergeAttrBy=mergeAttr; }
+ // (maybeAttr "mergeAttrBy" {} x)
+ // (maybeAttr "mergeAttrBy" {} y); in
+ mergeAttrs [
+ x y
+ (mapAttrs ( a : v : # merge special names using given functions
+ if (__hasAttr a x)
+ then if (__hasAttr a y)
+ then v (__getAttr a x) (__getAttr a y) # both have attr, use merge func
+ else (__getAttr a x) # only x has attr
+ else (__getAttr a y) # only y has attr)
+ ) (removeAttrs mergeAttrBy2
+ # don't merge attrs which are neither in x nor y
+ (filter (a : (! __hasAttr a x) && (! __hasAttr a y) )
+ (__attrNames mergeAttrBy2))
+ )
+ )
+ ];
+ mergeAttrsByFunc = fold mergeAttrByFunc {};
+ # sane defaults (same name as attr name so that inherit can be used)
+ mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
+ listToAttrs (map (n : nv n concatList) [ "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ])
+ // listToAttrs (map (n : nv n mergeAttr) [ "passthru" "meta" ]);
+
# returns atribute values as a list
flattenAttrs = set : map ( attr : builtins.getAttr attr set) (attrNames set);
mapIf = cond : f : fold ( x : l : if (cond x) then [(f x)] ++ l else l) [];