Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{
2 supportedSystems,
3 system ? builtins.currentSystem,
4 packageSet ? (import ../..),
5 scrubJobs ? true,
6 # Attributes passed to nixpkgs. Don't build packages marked as unfree.
7 nixpkgsArgs ? {
8 config = {
9 allowAliases = false;
10 allowUnfree = false;
11 inHydra = true;
12 };
13 __allowFileset = false;
14 },
15}:
16
17let
18 lib = import ../../lib;
19
20 inherit (lib)
21 addMetaAttrs
22 any
23 derivations
24 filter
25 flip
26 genAttrs
27 getAttrFromPath
28 hydraJob
29 id
30 isDerivation
31 lists
32 maintainers
33 mapAttrs
34 mapAttrs'
35 mapAttrsRecursive
36 matchAttrs
37 meta
38 nameValuePair
39 platforms
40 recursiveUpdate
41 subtractLists
42 systems
43 ;
44
45 pkgs = packageSet (
46 recursiveUpdate {
47 inherit system;
48 config.allowUnsupportedSystem = true;
49 } nixpkgsArgs
50 );
51
52 hydraJob' = if scrubJobs then hydraJob else id;
53
54 /*
55 !!! Hack: poor man's memoisation function. Necessary to prevent
56 Nixpkgs from being evaluated again and again for every
57 job/platform pair.
58 */
59 mkPkgsFor =
60 crossSystem:
61 let
62 packageSet' = args: packageSet (args // { inherit crossSystem; } // nixpkgsArgs);
63
64 pkgs_x86_64_linux = packageSet' { system = "x86_64-linux"; };
65 pkgs_i686_linux = packageSet' { system = "i686-linux"; };
66 pkgs_aarch64_linux = packageSet' { system = "aarch64-linux"; };
67 pkgs_riscv64_linux = packageSet' { system = "riscv64-linux"; };
68 pkgs_aarch64_darwin = packageSet' { system = "aarch64-darwin"; };
69 pkgs_armv6l_linux = packageSet' { system = "armv6l-linux"; };
70 pkgs_armv7l_linux = packageSet' { system = "armv7l-linux"; };
71 pkgs_x86_64_darwin = packageSet' { system = "x86_64-darwin"; };
72 pkgs_x86_64_freebsd = packageSet' { system = "x86_64-freebsd"; };
73 pkgs_i686_freebsd = packageSet' { system = "i686-freebsd"; };
74 pkgs_i686_cygwin = packageSet' { system = "i686-cygwin"; };
75 pkgs_x86_64_cygwin = packageSet' { system = "x86_64-cygwin"; };
76
77 in
78 system:
79 if system == "x86_64-linux" then
80 pkgs_x86_64_linux
81 else if system == "i686-linux" then
82 pkgs_i686_linux
83 else if system == "aarch64-linux" then
84 pkgs_aarch64_linux
85 else if system == "riscv64-linux" then
86 pkgs_riscv64_linux
87 else if system == "aarch64-darwin" then
88 pkgs_aarch64_darwin
89 else if system == "armv6l-linux" then
90 pkgs_armv6l_linux
91 else if system == "armv7l-linux" then
92 pkgs_armv7l_linux
93 else if system == "x86_64-darwin" then
94 pkgs_x86_64_darwin
95 else if system == "x86_64-freebsd" then
96 pkgs_x86_64_freebsd
97 else if system == "i686-freebsd" then
98 pkgs_i686_freebsd
99 else if system == "i686-cygwin" then
100 pkgs_i686_cygwin
101 else if system == "x86_64-cygwin" then
102 pkgs_x86_64_cygwin
103 else
104 abort "unsupported system type: ${system}";
105
106 pkgsFor = pkgsForCross null;
107
108 # More poor man's memoisation
109 pkgsForCross =
110 let
111 examplesByConfig = flip mapAttrs' systems.examples (
112 _: crossSystem:
113 nameValuePair crossSystem.config {
114 inherit crossSystem;
115 pkgsFor = mkPkgsFor crossSystem;
116 }
117 );
118 native = mkPkgsFor null;
119 in
120 crossSystem:
121 let
122 candidate = examplesByConfig.${crossSystem.config} or null;
123 in
124 if crossSystem == null then
125 native
126 else if candidate != null && matchAttrs crossSystem candidate.crossSystem then
127 candidate.pkgsFor
128 else
129 mkPkgsFor crossSystem; # uncached fallback
130
131 # Given a list of 'meta.platforms'-style patterns, return the sublist of
132 # `supportedSystems` containing systems that matches at least one of the given
133 # patterns.
134 #
135 # This is written in a funny way so that we only elaborate the systems once.
136 supportedMatches =
137 let
138 supportedPlatforms = map (system: systems.elaborate { inherit system; }) supportedSystems;
139 in
140 metaPatterns:
141 let
142 anyMatch = platform: any (meta.platformMatch platform) metaPatterns;
143 matchingPlatforms = filter anyMatch supportedPlatforms;
144 in
145 map ({ system, ... }: system) matchingPlatforms;
146
147 assertTrue =
148 bool:
149 if bool then
150 pkgs.runCommand "evaluated-to-true" { } "touch $out"
151 else
152 pkgs.runCommand "evaluated-to-false" { } "false";
153
154 /*
155 The working or failing mails for cross builds will be sent only to
156 the following maintainers, as most package maintainers will not be
157 interested in the result of cross building a package.
158 */
159 crossMaintainers = [ ];
160
161 # Generate attributes for all supported systems.
162 forAllSystems = genAttrs supportedSystems;
163
164 # Generate attributes for all systems matching at least one of the given
165 # patterns
166 forMatchingSystems = metaPatterns: genAttrs (supportedMatches metaPatterns);
167
168 /*
169 Build a package on the given set of platforms. The function `f'
170 is called for each supported platform with Nixpkgs for that
171 platform as an argument . We return an attribute set containing
172 a derivation for each supported platform, i.e. ‘{ x86_64-linux =
173 f pkgs_x86_64_linux; i686-linux = f pkgs_i686_linux; ... }’.
174 */
175 testOn = testOnCross null;
176
177 /*
178 Similar to the testOn function, but with an additional
179 'crossSystem' parameter for packageSet', defining the target
180 platform for cross builds.
181 */
182 testOnCross =
183 crossSystem: metaPatterns: f:
184 forMatchingSystems metaPatterns (system: hydraJob' (f (pkgsForCross crossSystem system)));
185
186 /*
187 Given a nested set where the leaf nodes are lists of platforms,
188 map each leaf node to `testOn [platforms...] (pkgs:
189 pkgs.<attrPath>)'.
190 */
191 mapTestOn = _mapTestOnHelper id null;
192
193 _mapTestOnHelper =
194 f: crossSystem:
195 mapAttrsRecursive (
196 path: metaPatterns: testOnCross crossSystem metaPatterns (pkgs: f (getAttrFromPath path pkgs))
197 );
198
199 /*
200 Similar to the testOn function, but with an additional 'crossSystem'
201 parameter for packageSet', defining the target platform for cross builds,
202 and triggering the build of the host derivation.
203 */
204 mapTestOnCross = _mapTestOnHelper (addMetaAttrs {
205 maintainers = crossMaintainers;
206 });
207
208 # Recursive for packages and apply a function to them
209 recursiveMapPackages =
210 f:
211 mapAttrs (
212 name: value:
213 if isDerivation value then
214 f value
215 else if value.recurseForDerivations or false || value.recurseForRelease or false then
216 recursiveMapPackages f value
217 else
218 [ ]
219 );
220
221 # Gets the list of Hydra platforms for a derivation
222 getPlatforms =
223 drv:
224 drv.meta.hydraPlatforms
225 or (subtractLists (drv.meta.badPlatforms or [ ]) (drv.meta.platforms or supportedSystems));
226
227 /*
228 Recursively map a (nested) set of derivations to an isomorphic
229 set of meta.platforms values.
230 */
231 packagePlatforms = recursiveMapPackages getPlatforms;
232
233in
234{
235 # Common platform groups on which to test packages.
236 inherit (platforms)
237 unix
238 linux
239 darwin
240 cygwin
241 all
242 ;
243
244 inherit
245 assertTrue
246 forAllSystems
247 forMatchingSystems
248 hydraJob'
249 lib
250 mapTestOn
251 mapTestOnCross
252 recursiveMapPackages
253 getPlatforms
254 packagePlatforms
255 pkgs
256 pkgsFor
257 pkgsForCross
258 supportedMatches
259 testOn
260 testOnCross
261 ;
262}