at 18.03-beta 4.3 kB view raw
1{lib, pkgs}: 2let inherit (lib) nv nvs; in 3{ 4 5 # composableDerivation basically mixes these features: 6 # - fix function 7 # - mergeAttrBy 8 # - provides shortcuts for "options" such as "--enable-foo" and adding 9 # buildInputs, see php example 10 # 11 # It predates styles which are common today, such as 12 # * the config attr 13 # * mkDerivation.override feature 14 # * overrideDerivation (lib/customization.nix) 15 # 16 # Some of the most more important usage examples (which could be rewritten if it was important): 17 # * php 18 # * postgis 19 # * vim_configurable 20 # 21 # A minimal example illustrating most features would look like this: 22 # let base = composableDerivation { (fixed: let inherit (fixed.fixed) name in { 23 # src = fetchurl { 24 # } 25 # buildInputs = [A]; 26 # preConfigre = "echo ${name}"; 27 # # attention, "name" attr is missing, thus you cannot instantiate "base". 28 # } 29 # in { 30 # # These all add name attribute, thus you can instantiate those: 31 # v1 = base.merge ({ name = "foo-add-B"; buildInputs = [B]; }); // B gets merged into buildInputs 32 # v2 = base.merge ({ name = "mix-in-pre-configure-lines" preConfigre = ""; }); 33 # v3 = base.replace ({ name = "foo-no-A-only-B;" buildInputs = [B]; }); 34 # } 35 # 36 # So yes, you can think about it being something like nixos modules, and 37 # you'd be merging "features" in one at a time using .merge or .replace 38 # Thanks Shea for telling me that I rethink the documentation .. 39 # 40 # issues: 41 # * its complicated to understand 42 # * some "features" such as exact merge behaviour are buried in mergeAttrBy 43 # and defaultOverridableDelayableArgs assuming the default behaviour does 44 # the right thing in the common case 45 # * Eelco once said using such fix style functions are slow to evaluate 46 # * Too quick & dirty. Hard to understand for others. The benefit was that 47 # you were able to create a kernel builder like base derivation and replace 48 # / add patches the way you want without having to declare function arguments 49 # 50 # nice features: 51 # declaring "optional features" is modular. For instance: 52 # flags.curl = { 53 # configureFlags = ["--with-curl=${curl.dev}" "--with-curlwrappers"]; 54 # buildInputs = [curl openssl]; 55 # }; 56 # flags.other = { .. } 57 # (Example taken from PHP) 58 # 59 # alternative styles / related features: 60 # * Eg see function supporting building the kernel 61 # * versionedDerivation (discussion about this is still going on - or ended) 62 # * composedArgsAndFun 63 # * mkDerivation.override 64 # * overrideDerivation 65 # * using { .., *Support ? false }: like configurable options. 66 # To find those examples use grep 67 # 68 # To sum up: It exists for historical reasons - and for most commonly used 69 # tasks the alternatives should be used 70 # 71 # If you have questions about this code ping Marc Weber. 72 composableDerivation = { 73 mkDerivation ? pkgs.stdenv.mkDerivation, 74 75 # list of functions to be applied before defaultOverridableDelayableArgs removes removeAttrs names 76 # prepareDerivationArgs handles derivation configurations 77 applyPreTidy ? [ lib.prepareDerivationArgs ], 78 79 # consider adding addtional elements by derivation.merge { removeAttrs = ["elem"]; }; 80 removeAttrs ? ["cfg" "flags"] 81 82 }: (lib.defaultOverridableDelayableArgs ( a: mkDerivation a) 83 { 84 inherit applyPreTidy removeAttrs; 85 }).merge; 86 87 # some utility functions 88 # use this function to generate flag attrs for prepareDerivationArgs 89 # E nable D isable F eature 90 edf = {name, feat ? name, enable ? {}, disable ? {} , value ? ""}: 91 nvs name { 92 set = { 93 configureFlags = ["--enable-${feat}${if value == "" then "" else "="}${value}"]; 94 } // enable; 95 unset = { 96 configureFlags = ["--disable-${feat}"]; 97 } // disable; 98 }; 99 100 # same for --with and --without- 101 # W ith or W ithout F eature 102 wwf = {name, feat ? name, enable ? {}, disable ? {}, value ? ""}: 103 nvs name { 104 set = enable // { 105 configureFlags = ["--with-${feat}${if value == "" then "" else "="}${value}"] 106 ++ lib.maybeAttr "configureFlags" [] enable; 107 }; 108 unset = disable // { 109 configureFlags = ["--without-${feat}"] 110 ++ lib.maybeAttr "configureFlags" [] disable; 111 }; 112 }; 113}