1{ lib }:
2
3let
4 inherit (lib)
5 any
6 attrValues
7 concatMap
8 filter
9 hasPrefix
10 isList
11 mapAttrs
12 matchAttrs
13 recursiveUpdateUntil
14 toList
15 ;
16
17 inherit (lib.strings) toJSON;
18
19 inherit (lib.systems.parse)
20 kernels
21 kernelFamilies
22 significantBytes
23 cpuTypes
24 execFormats
25 ;
26
27 abis = mapAttrs (_: abi: removeAttrs abi [ "assertions" ]) lib.systems.parse.abis;
28in
29
30rec {
31 # these patterns are to be matched against {host,build,target}Platform.parsed
32 patterns = rec {
33 # The patterns below are lists in sum-of-products form.
34 #
35 # Each attribute is list of product conditions; non-list values are treated
36 # as a singleton list. If *any* product condition in the list matches then
37 # the predicate matches. Each product condition is tested by
38 # `lib.attrsets.matchAttrs`, which requires a match on *all* attributes of
39 # the product.
40
41 isi686 = {
42 cpu = cpuTypes.i686;
43 };
44 isx86_32 = {
45 cpu = {
46 family = "x86";
47 bits = 32;
48 };
49 };
50 isx86_64 = {
51 cpu = {
52 family = "x86";
53 bits = 64;
54 };
55 };
56 isPower = {
57 cpu = {
58 family = "power";
59 };
60 };
61 isPower64 = {
62 cpu = {
63 family = "power";
64 bits = 64;
65 };
66 };
67 # This ABI is the default in NixOS PowerPC64 BE, but not on mainline GCC,
68 # so it sometimes causes issues in certain packages that makes the wrong
69 # assumption on the used ABI.
70 isAbiElfv2 = [
71 {
72 abi = {
73 abi = "elfv2";
74 };
75 }
76 {
77 abi = {
78 name = "musl";
79 };
80 cpu = {
81 family = "power";
82 bits = 64;
83 };
84 }
85 ];
86 isx86 = {
87 cpu = {
88 family = "x86";
89 };
90 };
91 isAarch32 = {
92 cpu = {
93 family = "arm";
94 bits = 32;
95 };
96 };
97 isArmv7 = map (
98 { arch, ... }:
99 {
100 cpu = { inherit arch; };
101 }
102 ) (filter (cpu: hasPrefix "armv7" cpu.arch or "") (attrValues cpuTypes));
103 isAarch64 = {
104 cpu = {
105 family = "arm";
106 bits = 64;
107 };
108 };
109 isAarch = {
110 cpu = {
111 family = "arm";
112 };
113 };
114 isMicroBlaze = {
115 cpu = {
116 family = "microblaze";
117 };
118 };
119 isMips = {
120 cpu = {
121 family = "mips";
122 };
123 };
124 isMips32 = {
125 cpu = {
126 family = "mips";
127 bits = 32;
128 };
129 };
130 isMips64 = {
131 cpu = {
132 family = "mips";
133 bits = 64;
134 };
135 };
136 isMips64n32 = {
137 cpu = {
138 family = "mips";
139 bits = 64;
140 };
141 abi = {
142 abi = "n32";
143 };
144 };
145 isMips64n64 = {
146 cpu = {
147 family = "mips";
148 bits = 64;
149 };
150 abi = {
151 abi = "64";
152 };
153 };
154 isMmix = {
155 cpu = {
156 family = "mmix";
157 };
158 };
159 isRiscV = {
160 cpu = {
161 family = "riscv";
162 };
163 };
164 isRiscV32 = {
165 cpu = {
166 family = "riscv";
167 bits = 32;
168 };
169 };
170 isRiscV64 = {
171 cpu = {
172 family = "riscv";
173 bits = 64;
174 };
175 };
176 isRx = {
177 cpu = {
178 family = "rx";
179 };
180 };
181 isSparc = {
182 cpu = {
183 family = "sparc";
184 };
185 };
186 isSparc64 = {
187 cpu = {
188 family = "sparc";
189 bits = 64;
190 };
191 };
192 isWasm = {
193 cpu = {
194 family = "wasm";
195 };
196 };
197 isMsp430 = {
198 cpu = {
199 family = "msp430";
200 };
201 };
202 isVc4 = {
203 cpu = {
204 family = "vc4";
205 };
206 };
207 isAvr = {
208 cpu = {
209 family = "avr";
210 };
211 };
212 isAlpha = {
213 cpu = {
214 family = "alpha";
215 };
216 };
217 isOr1k = {
218 cpu = {
219 family = "or1k";
220 };
221 };
222 isM68k = {
223 cpu = {
224 family = "m68k";
225 };
226 };
227 isS390 = {
228 cpu = {
229 family = "s390";
230 };
231 };
232 isS390x = {
233 cpu = {
234 family = "s390";
235 bits = 64;
236 };
237 };
238 isLoongArch64 = {
239 cpu = {
240 family = "loongarch";
241 bits = 64;
242 };
243 };
244 isJavaScript = {
245 cpu = cpuTypes.javascript;
246 };
247
248 is32bit = {
249 cpu = {
250 bits = 32;
251 };
252 };
253 is64bit = {
254 cpu = {
255 bits = 64;
256 };
257 };
258 isILP32 =
259 [
260 {
261 cpu = {
262 family = "wasm";
263 bits = 32;
264 };
265 }
266 ]
267 ++ map
268 (a: {
269 abi = {
270 abi = a;
271 };
272 })
273 [
274 "n32"
275 "ilp32"
276 "x32"
277 ];
278 isBigEndian = {
279 cpu = {
280 significantByte = significantBytes.bigEndian;
281 };
282 };
283 isLittleEndian = {
284 cpu = {
285 significantByte = significantBytes.littleEndian;
286 };
287 };
288
289 isBSD = {
290 kernel = {
291 families = { inherit (kernelFamilies) bsd; };
292 };
293 };
294 isDarwin = {
295 kernel = {
296 families = { inherit (kernelFamilies) darwin; };
297 };
298 };
299 isUnix = [
300 isBSD
301 isDarwin
302 isLinux
303 isSunOS
304 isCygwin
305 isRedox
306 ];
307
308 isMacOS = {
309 kernel = kernels.macos;
310 };
311 isiOS = {
312 kernel = kernels.ios;
313 };
314 isLinux = {
315 kernel = kernels.linux;
316 };
317 isSunOS = {
318 kernel = kernels.solaris;
319 };
320 isFreeBSD = {
321 kernel = {
322 name = "freebsd";
323 };
324 };
325 isNetBSD = {
326 kernel = kernels.netbsd;
327 };
328 isOpenBSD = {
329 kernel = kernels.openbsd;
330 };
331 isWindows = {
332 kernel = kernels.windows;
333 };
334 isCygwin = {
335 kernel = kernels.windows;
336 abi = abis.cygnus;
337 };
338 isMinGW = {
339 kernel = kernels.windows;
340 abi = abis.gnu;
341 };
342 isWasi = {
343 kernel = kernels.wasi;
344 };
345 isRedox = {
346 kernel = kernels.redox;
347 };
348 isGhcjs = {
349 kernel = kernels.ghcjs;
350 };
351 isGenode = {
352 kernel = kernels.genode;
353 };
354 isNone = {
355 kernel = kernels.none;
356 };
357
358 isAndroid = [
359 { abi = abis.android; }
360 { abi = abis.androideabi; }
361 ];
362 isGnu =
363 with abis;
364 map (a: { abi = a; }) [
365 gnuabi64
366 gnuabin32
367 gnu
368 gnueabi
369 gnueabihf
370 gnuabielfv1
371 gnuabielfv2
372 ];
373 isMusl =
374 with abis;
375 map (a: { abi = a; }) [
376 musl
377 musleabi
378 musleabihf
379 muslabin32
380 muslabi64
381 ];
382 isUClibc =
383 with abis;
384 map (a: { abi = a; }) [
385 uclibc
386 uclibceabi
387 uclibceabihf
388 ];
389
390 isEfi = [
391 {
392 cpu = {
393 family = "arm";
394 version = "6";
395 };
396 }
397 {
398 cpu = {
399 family = "arm";
400 version = "7";
401 };
402 }
403 {
404 cpu = {
405 family = "arm";
406 version = "8";
407 };
408 }
409 {
410 cpu = {
411 family = "riscv";
412 };
413 }
414 {
415 cpu = {
416 family = "x86";
417 };
418 }
419 {
420 cpu = {
421 family = "loongarch";
422 };
423 }
424 ];
425
426 isElf = {
427 kernel.execFormat = execFormats.elf;
428 };
429 isMacho = {
430 kernel.execFormat = execFormats.macho;
431 };
432 };
433
434 # given two patterns, return a pattern which is their logical AND.
435 # Since a pattern is a list-of-disjuncts, this needs to
436 patternLogicalAnd =
437 pat1_: pat2_:
438 let
439 # patterns can be either a list or a (bare) singleton; turn
440 # them into singletons for uniform handling
441 pat1 = toList pat1_;
442 pat2 = toList pat2_;
443 in
444 concatMap (
445 attr1:
446 map (
447 attr2:
448 recursiveUpdateUntil (
449 path: subattr1: subattr2:
450 if (builtins.intersectAttrs subattr1 subattr2) == { } || subattr1 == subattr2 then
451 true
452 else
453 throw ''
454 pattern conflict at path ${toString path}:
455 ${toJSON subattr1}
456 ${toJSON subattr2}
457 ''
458 ) attr1 attr2
459 ) pat2
460 ) pat1;
461
462 matchAnyAttrs =
463 patterns:
464 if isList patterns then
465 attrs: any (pattern: matchAttrs pattern attrs) patterns
466 else
467 matchAttrs patterns;
468
469 predicates = mapAttrs (_: matchAnyAttrs) patterns;
470
471 # these patterns are to be matched against the entire
472 # {host,build,target}Platform structure; they include a `parsed={}` marker so
473 # that `lib.meta.availableOn` can distinguish them from the patterns which
474 # apply only to the `parsed` field.
475
476 platformPatterns = mapAttrs (_: p: { parsed = { }; } // p) {
477 isStatic = {
478 isStatic = true;
479 };
480 };
481}