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