at master 24 kB view raw
1# Define the list of system with their properties. 2# 3# See https://clang.llvm.org/docs/CrossCompilation.html and 4# http://llvm.org/docs/doxygen/html/Triple_8cpp_source.html especially 5# Triple::normalize. Parsing should essentially act as a more conservative 6# version of that last function. 7# 8# Most of the types below come in "open" and "closed" pairs. The open ones 9# specify what information we need to know about systems in general, and the 10# closed ones are sub-types representing the whitelist of systems we support in 11# practice. 12# 13# Code in the remainder of nixpkgs shouldn't rely on the closed ones in 14# e.g. exhaustive cases. Its more a sanity check to make sure nobody defines 15# systems that overlap with existing ones and won't notice something amiss. 16# 17{ lib }: 18 19let 20 inherit (lib) 21 all 22 any 23 attrValues 24 elem 25 elemAt 26 hasPrefix 27 id 28 length 29 mapAttrs 30 mergeOneOption 31 optionalString 32 splitString 33 versionAtLeast 34 ; 35 36 inherit (lib.strings) match; 37 38 inherit (lib.systems.inspect.predicates) 39 isAarch32 40 isBigEndian 41 isDarwin 42 isLinux 43 isPower64 44 isWindows 45 isCygwin 46 ; 47 48 inherit (lib.types) 49 enum 50 float 51 isType 52 mkOptionType 53 number 54 setType 55 string 56 types 57 ; 58 59 setTypes = 60 type: 61 mapAttrs ( 62 name: value: 63 assert type.check value; 64 setType type.name ({ inherit name; } // value) 65 ); 66 67 # gnu-config will ignore the portion of a triple matching the 68 # regex `e?abi.*$` when determining the validity of a triple. In 69 # other words, `i386-linuxabichickenlips` is a valid triple. 70 removeAbiSuffix = 71 x: 72 let 73 found = match "(.*)e?abi.*" x; 74 in 75 if found == null then x else elemAt found 0; 76 77in 78 79rec { 80 81 ################################################################################ 82 83 types.openSignificantByte = mkOptionType { 84 name = "significant-byte"; 85 description = "Endianness"; 86 merge = mergeOneOption; 87 }; 88 89 types.significantByte = enum (attrValues significantBytes); 90 91 significantBytes = setTypes types.openSignificantByte { 92 bigEndian = { }; 93 littleEndian = { }; 94 }; 95 96 ################################################################################ 97 98 # Reasonable power of 2 99 types.bitWidth = enum [ 100 8 101 16 102 32 103 64 104 128 105 ]; 106 107 ################################################################################ 108 109 types.openCpuType = mkOptionType { 110 name = "cpu-type"; 111 description = "instruction set architecture name and information"; 112 merge = mergeOneOption; 113 check = 114 x: 115 types.bitWidth.check x.bits 116 && (if 8 < x.bits then types.significantByte.check x.significantByte else !(x ? significantByte)); 117 }; 118 119 types.cpuType = enum (attrValues cpuTypes); 120 121 cpuTypes = 122 let 123 inherit (significantBytes) bigEndian littleEndian; 124 in 125 setTypes types.openCpuType { 126 arm = { 127 bits = 32; 128 significantByte = littleEndian; 129 family = "arm"; 130 }; 131 armv5tel = { 132 bits = 32; 133 significantByte = littleEndian; 134 family = "arm"; 135 version = "5"; 136 arch = "armv5t"; 137 }; 138 armv6m = { 139 bits = 32; 140 significantByte = littleEndian; 141 family = "arm"; 142 version = "6"; 143 arch = "armv6-m"; 144 }; 145 armv6l = { 146 bits = 32; 147 significantByte = littleEndian; 148 family = "arm"; 149 version = "6"; 150 arch = "armv6"; 151 }; 152 armv7a = { 153 bits = 32; 154 significantByte = littleEndian; 155 family = "arm"; 156 version = "7"; 157 arch = "armv7-a"; 158 }; 159 armv7r = { 160 bits = 32; 161 significantByte = littleEndian; 162 family = "arm"; 163 version = "7"; 164 arch = "armv7-r"; 165 }; 166 armv7m = { 167 bits = 32; 168 significantByte = littleEndian; 169 family = "arm"; 170 version = "7"; 171 arch = "armv7-m"; 172 }; 173 armv7l = { 174 bits = 32; 175 significantByte = littleEndian; 176 family = "arm"; 177 version = "7"; 178 arch = "armv7"; 179 }; 180 armv8a = { 181 bits = 32; 182 significantByte = littleEndian; 183 family = "arm"; 184 version = "8"; 185 arch = "armv8-a"; 186 }; 187 armv8r = { 188 bits = 32; 189 significantByte = littleEndian; 190 family = "arm"; 191 version = "8"; 192 arch = "armv8-a"; 193 }; 194 armv8m = { 195 bits = 32; 196 significantByte = littleEndian; 197 family = "arm"; 198 version = "8"; 199 arch = "armv8-m"; 200 }; 201 aarch64 = { 202 bits = 64; 203 significantByte = littleEndian; 204 family = "arm"; 205 version = "8"; 206 arch = "armv8-a"; 207 }; 208 aarch64_be = { 209 bits = 64; 210 significantByte = bigEndian; 211 family = "arm"; 212 version = "8"; 213 arch = "armv8-a"; 214 }; 215 216 i386 = { 217 bits = 32; 218 significantByte = littleEndian; 219 family = "x86"; 220 arch = "i386"; 221 }; 222 i486 = { 223 bits = 32; 224 significantByte = littleEndian; 225 family = "x86"; 226 arch = "i486"; 227 }; 228 i586 = { 229 bits = 32; 230 significantByte = littleEndian; 231 family = "x86"; 232 arch = "i586"; 233 }; 234 i686 = { 235 bits = 32; 236 significantByte = littleEndian; 237 family = "x86"; 238 arch = "i686"; 239 }; 240 x86_64 = { 241 bits = 64; 242 significantByte = littleEndian; 243 family = "x86"; 244 arch = "x86-64"; 245 }; 246 247 microblaze = { 248 bits = 32; 249 significantByte = bigEndian; 250 family = "microblaze"; 251 }; 252 microblazeel = { 253 bits = 32; 254 significantByte = littleEndian; 255 family = "microblaze"; 256 }; 257 258 mips = { 259 bits = 32; 260 significantByte = bigEndian; 261 family = "mips"; 262 }; 263 mipsel = { 264 bits = 32; 265 significantByte = littleEndian; 266 family = "mips"; 267 }; 268 mips64 = { 269 bits = 64; 270 significantByte = bigEndian; 271 family = "mips"; 272 }; 273 mips64el = { 274 bits = 64; 275 significantByte = littleEndian; 276 family = "mips"; 277 }; 278 279 mmix = { 280 bits = 64; 281 significantByte = bigEndian; 282 family = "mmix"; 283 }; 284 285 m68k = { 286 bits = 32; 287 significantByte = bigEndian; 288 family = "m68k"; 289 }; 290 291 powerpc = { 292 bits = 32; 293 significantByte = bigEndian; 294 family = "power"; 295 }; 296 powerpc64 = { 297 bits = 64; 298 significantByte = bigEndian; 299 family = "power"; 300 }; 301 powerpc64le = { 302 bits = 64; 303 significantByte = littleEndian; 304 family = "power"; 305 }; 306 powerpcle = { 307 bits = 32; 308 significantByte = littleEndian; 309 family = "power"; 310 }; 311 312 riscv32 = { 313 bits = 32; 314 significantByte = littleEndian; 315 family = "riscv"; 316 }; 317 riscv64 = { 318 bits = 64; 319 significantByte = littleEndian; 320 family = "riscv"; 321 }; 322 323 s390 = { 324 bits = 32; 325 significantByte = bigEndian; 326 family = "s390"; 327 }; 328 s390x = { 329 bits = 64; 330 significantByte = bigEndian; 331 family = "s390"; 332 }; 333 334 sparc = { 335 bits = 32; 336 significantByte = bigEndian; 337 family = "sparc"; 338 }; 339 sparc64 = { 340 bits = 64; 341 significantByte = bigEndian; 342 family = "sparc"; 343 }; 344 345 wasm32 = { 346 bits = 32; 347 significantByte = littleEndian; 348 family = "wasm"; 349 }; 350 wasm64 = { 351 bits = 64; 352 significantByte = littleEndian; 353 family = "wasm"; 354 }; 355 356 alpha = { 357 bits = 64; 358 significantByte = littleEndian; 359 family = "alpha"; 360 }; 361 362 rx = { 363 bits = 32; 364 significantByte = littleEndian; 365 family = "rx"; 366 }; 367 msp430 = { 368 bits = 16; 369 significantByte = littleEndian; 370 family = "msp430"; 371 }; 372 avr = { 373 bits = 8; 374 family = "avr"; 375 }; 376 377 vc4 = { 378 bits = 32; 379 significantByte = littleEndian; 380 family = "vc4"; 381 }; 382 383 or1k = { 384 bits = 32; 385 significantByte = bigEndian; 386 family = "or1k"; 387 }; 388 389 loongarch64 = { 390 bits = 64; 391 significantByte = littleEndian; 392 family = "loongarch"; 393 }; 394 395 javascript = { 396 bits = 32; 397 significantByte = littleEndian; 398 family = "javascript"; 399 }; 400 } 401 // { 402 # aliases 403 # Apple architecture name, as used by `darwinArch`; required by 404 # LLVM ≥ 20. 405 arm64 = cpuTypes.aarch64; 406 }; 407 408 # GNU build systems assume that older NetBSD architectures are using a.out. 409 gnuNetBSDDefaultExecFormat = 410 cpu: 411 if 412 (cpu.family == "arm" && cpu.bits == 32) 413 || (cpu.family == "sparc" && cpu.bits == 32) 414 || (cpu.family == "m68k" && cpu.bits == 32) 415 || (cpu.family == "x86" && cpu.bits == 32) 416 then 417 execFormats.aout 418 else 419 execFormats.elf; 420 421 # Determine when two CPUs are compatible with each other. That is, 422 # can code built for system B run on system A? For that to happen, 423 # the programs that system B accepts must be a subset of the 424 # programs that system A accepts. 425 # 426 # We have the following properties of the compatibility relation, 427 # which must be preserved when adding compatibility information for 428 # additional CPUs. 429 # - (reflexivity) 430 # Every CPU is compatible with itself. 431 # - (transitivity) 432 # If A is compatible with B and B is compatible with C then A is compatible with C. 433 # 434 # Note: Since 22.11 the archs of a mode switching CPU are no longer considered 435 # pairwise compatible. Mode switching implies that binaries built for A 436 # and B respectively can't be executed at the same time. 437 isCompatible = 438 with cpuTypes; 439 a: b: 440 any id [ 441 # x86 442 (b == i386 && isCompatible a i486) 443 (b == i486 && isCompatible a i586) 444 (b == i586 && isCompatible a i686) 445 446 # XXX: Not true in some cases. Like in WSL mode. 447 (b == i686 && isCompatible a x86_64) 448 449 # ARMv4 450 (b == arm && isCompatible a armv5tel) 451 452 # ARMv5 453 (b == armv5tel && isCompatible a armv6l) 454 455 # ARMv6 456 (b == armv6l && isCompatible a armv6m) 457 (b == armv6m && isCompatible a armv7l) 458 459 # ARMv7 460 (b == armv7l && isCompatible a armv7a) 461 (b == armv7l && isCompatible a armv7r) 462 (b == armv7l && isCompatible a armv7m) 463 464 # ARMv8 465 (b == aarch64 && a == armv8a) 466 (b == armv8a && isCompatible a aarch64) 467 (b == armv8r && isCompatible a armv8a) 468 (b == armv8m && isCompatible a armv8a) 469 470 # PowerPC 471 (b == powerpc && isCompatible a powerpc64) 472 (b == powerpcle && isCompatible a powerpc64le) 473 474 # MIPS 475 (b == mips && isCompatible a mips64) 476 (b == mipsel && isCompatible a mips64el) 477 478 # RISCV 479 (b == riscv32 && isCompatible a riscv64) 480 481 # SPARC 482 (b == sparc && isCompatible a sparc64) 483 484 # WASM 485 (b == wasm32 && isCompatible a wasm64) 486 487 # identity 488 (b == a) 489 ]; 490 491 ################################################################################ 492 493 types.openVendor = mkOptionType { 494 name = "vendor"; 495 description = "vendor for the platform"; 496 merge = mergeOneOption; 497 }; 498 499 types.vendor = enum (attrValues vendors); 500 501 vendors = setTypes types.openVendor { 502 apple = { }; 503 pc = { }; 504 knuth = { }; 505 506 # Actually matters, unlocking some MinGW-w64-specific options in GCC. See 507 # bottom of https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/ 508 w64 = { }; 509 510 none = { }; 511 unknown = { }; 512 }; 513 514 ################################################################################ 515 516 types.openExecFormat = mkOptionType { 517 name = "exec-format"; 518 description = "executable container used by the kernel"; 519 merge = mergeOneOption; 520 }; 521 522 types.execFormat = enum (attrValues execFormats); 523 524 execFormats = setTypes types.openExecFormat { 525 aout = { }; # a.out 526 elf = { }; 527 macho = { }; 528 pe = { }; 529 wasm = { }; 530 531 unknown = { }; 532 }; 533 534 ################################################################################ 535 536 types.openKernelFamily = mkOptionType { 537 name = "exec-format"; 538 description = "executable container used by the kernel"; 539 merge = mergeOneOption; 540 }; 541 542 types.kernelFamily = enum (attrValues kernelFamilies); 543 544 kernelFamilies = setTypes types.openKernelFamily { 545 bsd = { }; 546 darwin = { }; 547 }; 548 549 ################################################################################ 550 551 types.openKernel = mkOptionType { 552 name = "kernel"; 553 description = "kernel name and information"; 554 merge = mergeOneOption; 555 check = 556 x: types.execFormat.check x.execFormat && all types.kernelFamily.check (attrValues x.families); 557 }; 558 559 types.kernel = enum (attrValues kernels); 560 561 kernels = 562 let 563 inherit (execFormats) 564 elf 565 pe 566 wasm 567 unknown 568 macho 569 ; 570 inherit (kernelFamilies) bsd darwin; 571 in 572 setTypes types.openKernel { 573 # TODO(@Ericson2314): Don't want to mass-rebuild yet to keeping 'darwin' as 574 # the normalized name for macOS. 575 macos = { 576 execFormat = macho; 577 families = { inherit darwin; }; 578 name = "darwin"; 579 }; 580 ios = { 581 execFormat = macho; 582 families = { inherit darwin; }; 583 }; 584 freebsd = { 585 execFormat = elf; 586 families = { inherit bsd; }; 587 name = "freebsd"; 588 }; 589 linux = { 590 execFormat = elf; 591 families = { }; 592 }; 593 netbsd = { 594 execFormat = elf; 595 families = { inherit bsd; }; 596 }; 597 none = { 598 execFormat = unknown; 599 families = { }; 600 }; 601 openbsd = { 602 execFormat = elf; 603 families = { inherit bsd; }; 604 }; 605 solaris = { 606 execFormat = elf; 607 families = { }; 608 }; 609 wasi = { 610 execFormat = wasm; 611 families = { }; 612 }; 613 redox = { 614 execFormat = elf; 615 families = { }; 616 }; 617 windows = { 618 execFormat = pe; 619 families = { }; 620 }; 621 cygwin = { 622 execFormat = pe; 623 families = { }; 624 }; 625 ghcjs = { 626 execFormat = unknown; 627 families = { }; 628 }; 629 genode = { 630 execFormat = elf; 631 families = { }; 632 }; 633 mmixware = { 634 execFormat = unknown; 635 families = { }; 636 }; 637 } 638 // { 639 # aliases 640 # 'darwin' is the kernel for all of them. We choose macOS by default. 641 darwin = kernels.macos; 642 watchos = kernels.ios; 643 tvos = kernels.ios; 644 win32 = kernels.windows; 645 }; 646 647 ################################################################################ 648 649 types.openAbi = mkOptionType { 650 name = "abi"; 651 description = "binary interface for compiled code and syscalls"; 652 merge = mergeOneOption; 653 }; 654 655 types.abi = enum (attrValues abis); 656 657 abis = setTypes types.openAbi { 658 msvc = { }; 659 660 # Note: eabi is specific to ARM and PowerPC. 661 # On PowerPC, this corresponds to PPCEABI. 662 # On ARM, this corresponds to ARMEABI. 663 eabi = { 664 float = "soft"; 665 }; 666 eabihf = { 667 float = "hard"; 668 }; 669 670 # Other architectures should use ELF in embedded situations. 671 elf = { }; 672 673 androideabi = { }; 674 android = { 675 assertions = [ 676 { 677 assertion = platform: !platform.isAarch32; 678 message = '' 679 The "android" ABI is not for 32-bit ARM. Use "androideabi" instead. 680 ''; 681 } 682 ]; 683 }; 684 685 gnueabi = { 686 float = "soft"; 687 }; 688 gnueabihf = { 689 float = "hard"; 690 }; 691 gnu = { 692 assertions = [ 693 { 694 assertion = platform: !platform.isAarch32; 695 message = '' 696 The "gnu" ABI is ambiguous on 32-bit ARM. Use "gnueabi" or "gnueabihf" instead. 697 ''; 698 } 699 { 700 assertion = platform: !(platform.isPower64 && platform.isBigEndian); 701 message = '' 702 The "gnu" ABI is ambiguous on big-endian 64-bit PowerPC. Use "gnuabielfv2" or "gnuabielfv1" instead. 703 ''; 704 } 705 ]; 706 }; 707 gnuabi64 = { 708 abi = "64"; 709 }; 710 muslabi64 = { 711 abi = "64"; 712 }; 713 714 # NOTE: abi=n32 requires a 64-bit MIPS chip! That is not a typo. 715 # It is basically the 64-bit abi with 32-bit pointers. Details: 716 # https://www.linux-mips.org/pub/linux/mips/doc/ABI/MIPS-N32-ABI-Handbook.pdf 717 gnuabin32 = { 718 abi = "n32"; 719 }; 720 muslabin32 = { 721 abi = "n32"; 722 }; 723 724 gnuabielfv2 = { 725 abi = "elfv2"; 726 }; 727 gnuabielfv1 = { 728 abi = "elfv1"; 729 }; 730 731 musleabi = { 732 float = "soft"; 733 }; 734 musleabihf = { 735 float = "hard"; 736 }; 737 musl = { }; 738 739 uclibceabi = { 740 float = "soft"; 741 }; 742 uclibceabihf = { 743 float = "hard"; 744 }; 745 uclibc = { }; 746 747 unknown = { }; 748 }; 749 750 ################################################################################ 751 752 types.parsedPlatform = mkOptionType { 753 name = "system"; 754 description = "fully parsed representation of llvm- or nix-style platform tuple"; 755 merge = mergeOneOption; 756 check = 757 { 758 cpu, 759 vendor, 760 kernel, 761 abi, 762 }: 763 types.cpuType.check cpu 764 && types.vendor.check vendor 765 && types.kernel.check kernel 766 && types.abi.check abi; 767 }; 768 769 isSystem = isType "system"; 770 771 mkSystem = 772 components: 773 assert types.parsedPlatform.check components; 774 setType "system" components; 775 776 mkSkeletonFromList = 777 l: 778 { 779 "1" = 780 if elemAt l 0 == "avr" then 781 { 782 cpu = elemAt l 0; 783 kernel = "none"; 784 abi = "unknown"; 785 } 786 else 787 throw "system string '${lib.concatStringsSep "-" l}' with 1 component is ambiguous"; 788 "2" = # We only do 2-part hacks for things Nix already supports 789 if elemAt l 1 == "cygwin" then 790 mkSkeletonFromList [ 791 (elemAt l 0) 792 "pc" 793 "cygwin" 794 ] 795 # MSVC ought to be the default ABI so this case isn't needed. But then it 796 # becomes difficult to handle the gnu* variants for Aarch32 correctly for 797 # minGW. So it's easier to make gnu* the default for the MinGW, but 798 # hack-in MSVC for the non-MinGW case right here. 799 else if elemAt l 1 == "windows" then 800 { 801 cpu = elemAt l 0; 802 kernel = "windows"; 803 abi = "msvc"; 804 } 805 else if (elemAt l 1) == "elf" then 806 { 807 cpu = elemAt l 0; 808 vendor = "unknown"; 809 kernel = "none"; 810 abi = elemAt l 1; 811 } 812 else 813 { 814 cpu = elemAt l 0; 815 kernel = elemAt l 1; 816 }; 817 "3" = 818 # cpu-kernel-environment 819 if 820 elemAt l 1 == "linux" 821 || elem (elemAt l 2) [ 822 "eabi" 823 "eabihf" 824 "elf" 825 "gnu" 826 ] 827 then 828 { 829 cpu = elemAt l 0; 830 kernel = elemAt l 1; 831 abi = elemAt l 2; 832 vendor = "unknown"; 833 } 834 # cpu-vendor-os 835 else if 836 elemAt l 1 == "apple" 837 || elem (elemAt l 2) [ 838 "redox" 839 "mmixware" 840 "ghcjs" 841 "mingw32" 842 ] 843 || hasPrefix "freebsd" (elemAt l 2) 844 || hasPrefix "netbsd" (elemAt l 2) 845 || hasPrefix "openbsd" (elemAt l 2) 846 || hasPrefix "genode" (elemAt l 2) 847 || hasPrefix "wasm32" (elemAt l 0) 848 then 849 { 850 cpu = elemAt l 0; 851 vendor = elemAt l 1; 852 kernel = 853 if elemAt l 2 == "mingw32" then 854 "windows" # autotools breaks on -gnu for window 855 else 856 elemAt l 2; 857 } 858 # lots of tools expect a triplet for Cygwin, even though the vendor is just "pc" 859 else if elemAt l 2 == "cygwin" then 860 { 861 cpu = elemAt l 0; 862 vendor = elemAt l 1; 863 kernel = "cygwin"; 864 } 865 else 866 throw "system string '${lib.concatStringsSep "-" l}' with 3 components is ambiguous"; 867 "4" = { 868 cpu = elemAt l 0; 869 vendor = elemAt l 1; 870 kernel = elemAt l 2; 871 abi = elemAt l 3; 872 }; 873 } 874 .${toString (length l)} 875 or (throw "system string '${lib.concatStringsSep "-" l}' has invalid number of hyphen-separated components"); 876 877 # This should revert the job done by config.guess from the gcc compiler. 878 mkSystemFromSkeleton = 879 { 880 cpu, 881 # Optional, but fallback too complex for here. 882 # Inferred below instead. 883 vendor ? 884 assert false; 885 null, 886 kernel, 887 # Also inferred below 888 abi ? 889 assert false; 890 null, 891 }@args: 892 let 893 getCpu = name: cpuTypes.${name} or (throw "Unknown CPU type: ${name}"); 894 getVendor = name: vendors.${name} or (throw "Unknown vendor: ${name}"); 895 getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}"); 896 getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}"); 897 898 parsed = { 899 cpu = getCpu args.cpu; 900 vendor = 901 if args ? vendor then 902 getVendor args.vendor 903 else if isDarwin parsed then 904 vendors.apple 905 else if (isWindows parsed || isCygwin parsed) then 906 vendors.pc 907 else 908 vendors.unknown; 909 kernel = 910 if hasPrefix "darwin" args.kernel then 911 getKernel "darwin" 912 else if hasPrefix "netbsd" args.kernel then 913 getKernel "netbsd" 914 else 915 getKernel (removeAbiSuffix args.kernel); 916 abi = 917 if args ? abi then 918 getAbi args.abi 919 else if isLinux parsed || isWindows parsed then 920 if isAarch32 parsed then 921 if versionAtLeast (parsed.cpu.version or "0") "6" then abis.gnueabihf else abis.gnueabi 922 # Default ppc64 BE to ELFv2 923 else if isPower64 parsed && isBigEndian parsed then 924 abis.gnuabielfv2 925 else 926 abis.gnu 927 else 928 abis.unknown; 929 }; 930 931 in 932 mkSystem parsed; 933 934 mkSystemFromString = s: mkSystemFromSkeleton (mkSkeletonFromList (splitString "-" s)); 935 936 kernelName = kernel: kernel.name + toString (kernel.version or ""); 937 938 darwinArch = cpu: if cpu.name == "aarch64" then "arm64" else cpu.name; 939 940 doubleFromSystem = 941 { 942 cpu, 943 kernel, 944 abi, 945 ... 946 }: 947 if kernel.families ? darwin then "${cpu.name}-darwin" else "${cpu.name}-${kernelName kernel}"; 948 949 tripleFromSystem = 950 { 951 cpu, 952 vendor, 953 kernel, 954 abi, 955 ... 956 }@sys: 957 assert isSystem sys; 958 let 959 optExecFormat = optionalString ( 960 kernel.name == "netbsd" && gnuNetBSDDefaultExecFormat cpu != kernel.execFormat 961 ) kernel.execFormat.name; 962 optAbi = optionalString (abi != abis.unknown) "-${abi.name}"; 963 cpuName = if kernel.families ? darwin then darwinArch cpu else cpu.name; 964 in 965 "${cpuName}-${vendor.name}-${kernelName kernel}${optExecFormat}${optAbi}"; 966 967 ################################################################################ 968 969}