at 25.11-pre 4.7 kB view raw
1{ lib }: 2/** 3 Usage: 4 5 You define you custom builder script by adding all build steps to a list. 6 for example: 7 builder = writeScript "fsg-4.4-builder" 8 (textClosure [doUnpack addInputs preBuild doMake installPhase doForceShare]); 9 10 a step is defined by noDepEntry, fullDepEntry or packEntry. 11 To ensure that prerequisite are met those are added before the task itself by 12 textClosureDupList. Duplicated items are removed again. 13 14 See trace/nixpkgs/trunk/pkgs/top-level/builder-defs.nix for some predefined build steps 15 16 Attention: 17 18 let 19 pkgs = (import <nixpkgs>) {}; 20 in let 21 inherit (pkgs.stringsWithDeps) fullDepEntry packEntry noDepEntry textClosureMap; 22 inherit (pkgs.lib) id; 23 24 nameA = noDepEntry "Text a"; 25 nameB = fullDepEntry "Text b" ["nameA"]; 26 nameC = fullDepEntry "Text c" ["nameA"]; 27 28 stages = { 29 nameHeader = noDepEntry "#! /bin/sh \n"; 30 inherit nameA nameB nameC; 31 }; 32 in 33 textClosureMap id stages 34 [ "nameHeader" "nameA" "nameB" "nameC" 35 nameC # <- added twice. add a dep entry if you know that it will be added once only [1] 36 "nameB" # <- this will not be added again because the attr name (reference) is used 37 ] 38 39 # result: Str("#! /bin/sh \n\nText a\nText b\nText c\nText c",[]) 40 41 [1] maybe this behaviour should be removed to keep things simple (?) 42*/ 43 44let 45 inherit (lib) 46 concatStringsSep 47 head 48 isAttrs 49 listToAttrs 50 tail 51 ; 52in 53rec { 54 55 /** 56 Topologically sort a collection of dependent strings. 57 Only the values to keys listed in `arg` and their dependencies will be included in the result. 58 59 ::: {.note} 60 This function doesn't formally fulfill the definition of topological sorting, but it's good enough for our purposes in Nixpkgs. 61 ::: 62 63 # Inputs 64 65 `predefined` (attribute set) 66 67 : strings with annotated dependencies (strings or attribute set) 68 A value can be a simple string if it has no dependencies. 69 Otherwise, is can be an attribute set with the following attributes: 70 - `deps` (list of strings) 71 - `text` (Any 72 73 `arg` (list of strings) 74 75 : Keys for which the values in the dependency closure will be included in the result 76 77 # Type 78 79 ``` 80 textClosureList :: { ${phase} :: { deps :: [String]; text :: String; } | String; } -> [String] -> [String] 81 ``` 82 83 # Examples 84 :::{.example} 85 ## `lib.stringsWithDeps.textClosureList` usage example 86 87 ```nix 88 textClosureList { 89 a = { 90 deps = [ "b" "c" "e" ]; 91 text = "a: depends on b, c and e"; 92 }; 93 b = { 94 deps = [ ]; 95 text = "b: no dependencies"; 96 }; 97 c = { 98 deps = [ "b" ]; 99 text = "c: depends on b"; 100 }; 101 d = { 102 deps = [ "c" ]; 103 text = "d: not being depended on by anything in `arg`"; 104 }; 105 e = { 106 deps = [ "c" ]; 107 text = "e: depends on c, depended on by a, not in `arg`"; 108 }; 109 } [ 110 "a" 111 "b" 112 "c" 113 ] 114 => [ 115 "b: no dependencies" 116 "c: depends on b" 117 "e: depends on c, depended on by a, not in `arg`" 118 "a: depends on b, c and e" 119 ] 120 ``` 121 ::: 122 123 Common real world usages are: 124 - Ordering the dependent phases of `system.activationScripts` 125 - Ordering the dependent phases of `system.userActivationScripts` 126 127 For further examples see: [NixOS activation script](https://nixos.org/manual/nixos/stable/#sec-activation-script) 128 */ 129 textClosureList = 130 predefined: arg: 131 let 132 f = 133 done: todo: 134 if todo == [ ] then 135 { 136 result = [ ]; 137 inherit done; 138 } 139 else 140 let 141 entry = head todo; 142 in 143 if isAttrs entry then 144 let 145 x = f done entry.deps; 146 y = f x.done (tail todo); 147 in 148 { 149 result = x.result ++ [ entry.text ] ++ y.result; 150 done = y.done; 151 } 152 else if done ? ${entry} then 153 f done (tail todo) 154 else 155 f ( 156 done 157 // listToAttrs [ 158 { 159 name = entry; 160 value = 1; 161 } 162 ] 163 ) ([ predefined.${entry} ] ++ tail todo); 164 in 165 (f { } arg).result; 166 167 textClosureMap = 168 f: predefined: names: 169 concatStringsSep "\n" (map f (textClosureList predefined names)); 170 171 noDepEntry = text: { 172 inherit text; 173 deps = [ ]; 174 }; 175 fullDepEntry = text: deps: { inherit text deps; }; 176 packEntry = deps: { 177 inherit deps; 178 text = ""; 179 }; 180 181 stringAfter = deps: text: { inherit text deps; }; 182 183}