Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at python-updates 999 lines 37 kB view raw
1# The Nixpkgs CC is not directly usable, since it doesn't know where 2# the C library and standard header files are. Therefore the compiler 3# produced by that package cannot be installed directly in a user 4# environment and used from the command line. So we use a wrapper 5# script that sets up the right environment variables so that the 6# compiler and the linker just "work". 7 8{ 9 name ? "", 10 lib, 11 stdenvNoCC, 12 runtimeShell, 13 cc ? null, 14 libc ? null, 15 bintools, 16 coreutils ? null, 17 apple-sdk ? null, 18 zlib ? null, 19 nativeTools, 20 noLibc ? false, 21 nativeLibc, 22 nativePrefix ? "", 23 propagateDoc ? cc != null && cc ? man, 24 extraTools ? [ ], 25 extraPackages ? [ ], 26 extraBuildCommands ? "", 27 nixSupport ? { }, 28 isGNU ? false, 29 isClang ? cc.isClang or false, 30 isZig ? cc.isZig or false, 31 isArocc ? cc.isArocc or false, 32 isCcache ? cc.isCcache or false, 33 gnugrep ? null, 34 expand-response-params, 35 libcxx ? null, 36 37 # Whether or not to add `-B` and `-L` to `nix-support/cc-{c,ld}flags` 38 useCcForLibs ? 39 40 # Always add these flags for Clang, because in order to compile (most 41 # software) it needs libraries that are shipped and compiled with gcc. 42 if isClang then 43 true 44 45 # Never add these flags for a build!=host cross-compiler or a host!=target 46 # ("cross-built-native") compiler; currently nixpkgs has a special build 47 # path for these (`crossStageStatic`). Hopefully at some point that build 48 # path will be merged with this one and this conditional will be removed. 49 else if (with stdenvNoCC; buildPlatform != hostPlatform || hostPlatform != targetPlatform) then 50 false 51 52 # Never add these flags when wrapping the bootstrapFiles' compiler; it has a 53 # /usr/-like layout with everything smashed into a single outpath, so it has 54 # no trouble finding its own libraries. 55 else if (cc.passthru.isFromBootstrapFiles or false) then 56 false 57 58 # Add these flags when wrapping `xgcc` (the first compiler that nixpkgs builds) 59 else if (cc.passthru.isXgcc or false) then 60 true 61 62 # Add these flags when wrapping `stdenv.cc` 63 else if (cc.stdenv.cc.cc.passthru.isXgcc or false) then 64 true 65 66 # Do not add these flags in any other situation. This is `false` mainly to 67 # prevent these flags from being added when wrapping *old* versions of gcc 68 # (e.g. `gcc6Stdenv`), since they will cause the old gcc to get `-B` and 69 # `-L` flags pointing at the new gcc's libstdc++ headers. Example failure: 70 # https://hydra.nixos.org/build/213125495 71 else 72 false, 73 74 # the derivation at which the `-B` and `-L` flags added by `useCcForLibs` will point 75 gccForLibs ? if useCcForLibs then cc else null, 76 fortify-headers ? null, 77 includeFortifyHeaders ? null, 78}: 79 80assert nativeTools -> !propagateDoc && nativePrefix != ""; 81assert !nativeTools -> cc != null && coreutils != null && gnugrep != null; 82assert !(nativeLibc && noLibc); 83assert (noLibc || nativeLibc) == (libc == null); 84 85let 86 inherit (lib) 87 attrByPath 88 concatMapStrings 89 concatStringsSep 90 escapeShellArg 91 escapeShellArgs 92 getBin 93 getDev 94 getLib 95 getName 96 getVersion 97 hasPrefix 98 mapAttrsToList 99 optional 100 optionalAttrs 101 optionals 102 optionalString 103 removePrefix 104 removeSuffix 105 replaceStrings 106 toList 107 versionAtLeast 108 ; 109 110 inherit (stdenvNoCC) hostPlatform targetPlatform; 111 112 includeFortifyHeaders' = 113 if includeFortifyHeaders != null then 114 includeFortifyHeaders 115 else 116 (targetPlatform.libc == "musl" && isGNU); 117 118 # Prefix for binaries. Customarily ends with a dash separator. 119 # 120 # TODO(@Ericson2314) Make unconditional, or optional but always true by default. 121 targetPrefix = optionalString (targetPlatform != hostPlatform) (targetPlatform.config + "-"); 122 123 ccVersion = getVersion cc; 124 ccName = removePrefix targetPrefix (getName cc); 125 126 libc_bin = optionalString (libc != null) (getBin libc); 127 libc_dev = optionalString (libc != null) (getDev libc); 128 libc_lib = optionalString (libc != null) (getLib libc); 129 cc_solib = getLib cc + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}"; 130 131 # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. 132 coreutils_bin = optionalString (!nativeTools) (getBin coreutils); 133 134 # The "suffix salt" is a arbitrary string added in the end of env vars 135 # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used 136 # without interfering. For the moment, it is defined as the target triple, 137 # adjusted to be a valid bash identifier. This should be considered an 138 # unstable implementation detail, however. 139 suffixSalt = 140 replaceStrings [ "-" "." ] [ "_" "_" ] targetPlatform.config 141 + lib.optionalString (targetPlatform.isDarwin && targetPlatform.isStatic) "_static"; 142 143 useGccForLibs = 144 useCcForLibs 145 && libcxx == null 146 && !targetPlatform.isDarwin 147 && !(targetPlatform.useLLVM or false) 148 && !(targetPlatform.useAndroidPrebuilt or false) 149 && !(targetPlatform.isiOS or false) 150 && gccForLibs != null; 151 gccForLibs_solib = 152 getLib gccForLibs + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}"; 153 154 # Analogously to cc_solib and gccForLibs_solib 155 libcxx_solib = "${getLib libcxx}/lib"; 156 157 # The following two functions, `isGccArchSupported` and 158 # `isGccTuneSupported`, only handle those situations where a flag 159 # (`-march` or `-mtune`) is accepted by one compiler but rejected 160 # by another, and both compilers are relevant to nixpkgs. We are 161 # not trying to maintain a complete list of all flags accepted by 162 # all versions of all compilers ever in nixpkgs. 163 # 164 # The two main cases of interest are: 165 # 166 # - One compiler is gcc and the other is clang 167 # - One compiler is pkgs.gcc and the other is bootstrap-files.gcc 168 # -- older compilers (for example bootstrap's GCC 5) fail with 169 # -march=too-modern-cpu 170 171 isGccArchSupported = 172 arch: 173 if targetPlatform.isPower then 174 false 175 # powerpc does not allow -march= 176 else if isGNU then 177 { 178 # Generic 179 x86-64-v2 = versionAtLeast ccVersion "11.0"; 180 x86-64-v3 = versionAtLeast ccVersion "11.0"; 181 x86-64-v4 = versionAtLeast ccVersion "11.0"; 182 183 # Intel 184 skylake = true; 185 skylake-avx512 = true; 186 cannonlake = versionAtLeast ccVersion "8.0"; 187 icelake-client = versionAtLeast ccVersion "8.0"; 188 icelake-server = versionAtLeast ccVersion "8.0"; 189 cascadelake = versionAtLeast ccVersion "9.0"; 190 cooperlake = versionAtLeast ccVersion "10.0"; 191 tigerlake = versionAtLeast ccVersion "10.0"; 192 knm = versionAtLeast ccVersion "8.0"; 193 alderlake = versionAtLeast ccVersion "12.0"; 194 sapphirerapids = versionAtLeast ccVersion "11.0"; 195 emeraldrapids = versionAtLeast ccVersion "13.0"; 196 sierraforest = versionAtLeast ccVersion "13.0"; 197 198 # AMD 199 znver1 = true; 200 znver2 = versionAtLeast ccVersion "9.0"; 201 znver3 = versionAtLeast ccVersion "11.0"; 202 znver4 = versionAtLeast ccVersion "13.0"; 203 znver5 = versionAtLeast ccVersion "14.0"; 204 205 # LoongArch64 206 # https://gcc.gnu.org/gcc-12/changes.html#loongarch 207 # la464 was added together with loongarch64 support 208 # https://gcc.gnu.org/gcc-14/changes.html#loongarch 209 "la64v1.0" = versionAtLeast ccVersion "14.0"; 210 "la64v1.1" = versionAtLeast ccVersion "14.0"; 211 la664 = versionAtLeast ccVersion "14.0"; 212 } 213 .${arch} or true 214 else if isClang then 215 { 216 #Generic 217 x86-64-v2 = versionAtLeast ccVersion "12.0"; 218 x86-64-v3 = versionAtLeast ccVersion "12.0"; 219 x86-64-v4 = versionAtLeast ccVersion "12.0"; 220 221 # Intel 222 cannonlake = versionAtLeast ccVersion "5.0"; 223 icelake-client = versionAtLeast ccVersion "7.0"; 224 icelake-server = versionAtLeast ccVersion "7.0"; 225 knm = versionAtLeast ccVersion "7.0"; 226 alderlake = versionAtLeast ccVersion "16.0"; 227 sapphirerapids = versionAtLeast ccVersion "12.0"; 228 emeraldrapids = versionAtLeast ccVersion "16.0"; 229 230 # AMD 231 znver1 = versionAtLeast ccVersion "4.0"; 232 znver2 = versionAtLeast ccVersion "9.0"; 233 znver3 = versionAtLeast ccVersion "12.0"; 234 znver4 = versionAtLeast ccVersion "16.0"; 235 znver5 = versionAtLeast ccVersion "19.1"; 236 237 # LoongArch64 238 # https://releases.llvm.org/16.0.0/tools/clang/docs/ReleaseNotes.html#loongarch-support 239 # la464 was added together with loongarch64 support 240 # https://releases.llvm.org/19.1.0/tools/clang/docs/ReleaseNotes.html#loongarch-support 241 "la64v1.0" = versionAtLeast ccVersion "19.1"; 242 "la64v1.1" = versionAtLeast ccVersion "19.1"; 243 la664 = versionAtLeast ccVersion "19.1"; 244 } 245 .${arch} or true 246 else 247 false; 248 249 isGccTuneSupported = 250 tune: 251 # for x86 -mtune= takes the same values as -march, plus two more: 252 if targetPlatform.isx86 then 253 { 254 generic = true; 255 intel = true; 256 } 257 .${tune} or (isGccArchSupported tune) 258 # on arm64, the -mtune= values are specific processors 259 else if targetPlatform.isAarch64 then 260 ( 261 if isGNU then 262 { 263 cortex-a53 = true; 264 cortex-a72 = true; 265 "cortex-a72.cortex-a53" = true; 266 } 267 .${tune} or false 268 else if isClang then 269 { 270 cortex-a53 = versionAtLeast ccVersion "3.9"; # llvm dfc5d1 271 } 272 .${tune} or false 273 else 274 false 275 ) 276 else if targetPlatform.isPower then 277 # powerpc does not support -march 278 true 279 else if targetPlatform.isMips then 280 # for mips -mtune= takes the same values as -march 281 isGccArchSupported tune 282 else 283 false; 284 285 # Clang does not support as many `-mtune=` values as gcc does; 286 # this function will return the best possible approximation of the 287 # provided `-mtune=` value, or `null` if none exists. 288 # 289 # Note: this function can make use of ccVersion; for example, `if 290 # versionOlder ccVersion "12" then ...` 291 findBestTuneApproximation = 292 tune: 293 let 294 guess = 295 if isClang then 296 { 297 # clang does not tune for big.LITTLE chips 298 "cortex-a72.cortex-a53" = "cortex-a72"; 299 } 300 .${tune} or tune 301 else 302 tune; 303 in 304 if isGccTuneSupported guess then guess else null; 305 306 thumb = if targetPlatform.gcc.thumb then "thumb" else "arm"; 307 tune = 308 if targetPlatform ? gcc.tune then findBestTuneApproximation targetPlatform.gcc.tune else null; 309 310 # Machine flags. These are necessary to support 311 312 # TODO: We should make a way to support miscellaneous machine 313 # flags and other gcc flags as well. 314 315 machineFlags = 316 # Always add -march based on cpu in triple. Sometimes there is a 317 # discrepancy (x86_64 vs. x86-64), so we provide an "arch" arg in 318 # that case. 319 optional ( 320 targetPlatform ? gcc.arch 321 && !(targetPlatform.isDarwin && targetPlatform.isAarch64) 322 && isGccArchSupported targetPlatform.gcc.arch 323 ) "-march=${targetPlatform.gcc.arch}" 324 ++ 325 # TODO: aarch64-darwin has mcpu incompatible with gcc 326 optional ( 327 targetPlatform ? gcc.cpu && !(targetPlatform.isDarwin && targetPlatform.isAarch64) 328 ) "-mcpu=${targetPlatform.gcc.cpu}" 329 ++ 330 # -mfloat-abi only matters on arm32 but we set it here 331 # unconditionally just in case. If the abi specifically sets hard 332 # vs. soft floats we use it here. 333 optional (targetPlatform ? gcc.float-abi) "-mfloat-abi=${targetPlatform.gcc.float-abi}" 334 ++ optional (targetPlatform ? gcc.fpu) "-mfpu=${targetPlatform.gcc.fpu}" 335 ++ optional (targetPlatform ? gcc.mode) "-mmode=${targetPlatform.gcc.mode}" 336 ++ optional (targetPlatform ? gcc.thumb) "-m${thumb}" 337 ++ optional (tune != null) "-mtune=${tune}" 338 ++ 339 optional (targetPlatform ? gcc.strict-align) 340 "-m${optionalString (!targetPlatform.gcc.strict-align) "no-"}strict-align" 341 ++ optional ( 342 targetPlatform ? gcc.cmodel 343 && 344 # TODO: clang on powerpcspe also needs a condition: https://github.com/llvm/llvm-project/issues/71356 345 # https://releases.llvm.org/18.1.6/tools/clang/docs/ReleaseNotes.html#loongarch-support 346 ((targetPlatform.isLoongArch64 && isClang) -> versionAtLeast ccVersion "18.1") 347 ) "-mcmodel=${targetPlatform.gcc.cmodel}"; 348 349 defaultHardeningFlags = bintools.defaultHardeningFlags or [ ]; 350 351 # if cc.hardeningUnsupportedFlagsByTargetPlatform exists, this is 352 # called with the targetPlatform as an argument and 353 # cc.hardeningUnsupportedFlags is completely ignored - the function 354 # is responsible for including the constant hardeningUnsupportedFlags 355 # list however it sees fit. 356 ccHardeningUnsupportedFlags = 357 if cc ? hardeningUnsupportedFlagsByTargetPlatform then 358 cc.hardeningUnsupportedFlagsByTargetPlatform targetPlatform 359 else 360 (cc.hardeningUnsupportedFlags or [ ]); 361 362 darwinPlatformForCC = optionalString targetPlatform.isDarwin ( 363 if (targetPlatform.darwinPlatform == "macos" && isGNU) then 364 "macosx" 365 else 366 targetPlatform.darwinPlatform 367 ); 368 369 # Header files that use `__FILE__` (e.g., for error reporting) lead 370 # to unwanted references to development packages and outputs in built 371 # binaries, like C++ programs depending on GCC and Boost at runtime. 372 # 373 # We use `-fmacro-prefix-map` to avoid the store references in these 374 # situations while keeping them in compiler diagnostics and debugging 375 # and profiling output. 376 # 377 # Unfortunately, doing this with GCC runs into issues with compiler 378 # argument length limits due to <https://gcc.gnu.org/PR111527>, so we 379 # disable it there in favour of our existing patch. 380 # 381 # TODO: Drop `mangle-NIX_STORE-in-__FILE__.patch` from GCC and make 382 # this unconditional once the upstream bug is fixed. 383 useMacroPrefixMap = !isGNU; 384in 385 386assert includeFortifyHeaders' -> fortify-headers != null; 387 388# Ensure bintools matches 389assert libc_bin == bintools.libc_bin; 390assert libc_dev == bintools.libc_dev; 391assert libc_lib == bintools.libc_lib; 392assert nativeTools == bintools.nativeTools; 393assert nativeLibc == bintools.nativeLibc; 394assert nativePrefix == bintools.nativePrefix; 395 396stdenvNoCC.mkDerivation { 397 pname = targetPrefix + (if name != "" then name else "${ccName}-wrapper"); 398 version = optionalString (cc != null) ccVersion; 399 400 preferLocalBuild = true; 401 402 outputs = [ 403 "out" 404 ] 405 ++ optionals propagateDoc [ 406 "man" 407 "info" 408 ]; 409 410 # Cannot be in "passthru" due to "substituteAll" 411 inherit isArocc; 412 413 passthru = { 414 inherit targetPrefix suffixSalt; 415 # "cc" is the generic name for a C compiler, but there is no one for package 416 # providing the linker and related tools. The two we use now are GNU 417 # Binutils, and Apple's "cctools"; "bintools" as an attempt to find an 418 # unused middle-ground name that evokes both. 419 inherit bintools; 420 inherit 421 cc 422 libc 423 libcxx 424 nativeTools 425 nativeLibc 426 nativePrefix 427 isGNU 428 isClang 429 isZig 430 ; 431 432 emacsBufferSetup = pkgs: '' 433 ; We should handle propagation here too 434 (mapc 435 (lambda (arg) 436 (when (file-directory-p (concat arg "/include")) 437 (setenv "NIX_CFLAGS_COMPILE_${suffixSalt}" (concat (getenv "NIX_CFLAGS_COMPILE_${suffixSalt}") " -isystem " arg "/include")))) 438 '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) 439 ''; 440 441 # Expose expand-response-params we are /actually/ using. In stdenv 442 # bootstrapping, expand-response-params usually comes from an earlier stage, 443 # so it is important to expose this for reference checking. 444 inherit expand-response-params; 445 446 inherit nixSupport; 447 448 inherit defaultHardeningFlags; 449 }; 450 451 dontBuild = true; 452 dontConfigure = true; 453 enableParallelBuilding = true; 454 455 # TODO(@connorbaker): 456 # This is a quick fix unblock builds broken by https://github.com/NixOS/nixpkgs/pull/370750. 457 dontCheckForBrokenSymlinks = true; 458 459 unpackPhase = '' 460 src=$PWD 461 ''; 462 463 wrapper = ./cc-wrapper.sh; 464 465 installPhase = '' 466 mkdir -p $out/bin $out/nix-support 467 468 wrap() { 469 local dst="$1" 470 local wrapper="$2" 471 export prog="$3" 472 export use_response_file_by_default=${if isClang && !isCcache then "1" else "0"} 473 substituteAll "$wrapper" "$out/bin/$dst" 474 chmod +x "$out/bin/$dst" 475 } 476 477 include() { 478 printf -- '%s %s\n' "$1" "$2" 479 ${lib.optionalString useMacroPrefixMap '' 480 local scrubbed="$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-''${2#"$NIX_STORE"/*-}" 481 printf -- '-fmacro-prefix-map=%s=%s\n' "$2" "$scrubbed" 482 ''} 483 } 484 '' 485 486 + ( 487 if nativeTools then 488 '' 489 echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc 490 491 ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin" 492 '' 493 else 494 '' 495 echo $cc > $out/nix-support/orig-cc 496 497 ccPath="${cc}/bin" 498 '' 499 ) 500 501 # Create symlinks to everything in the bintools wrapper. 502 + '' 503 for bbin in $bintools/bin/*; do 504 mkdir -p "$out/bin" 505 ln -s "$bbin" "$out/bin/$(basename $bbin)" 506 done 507 '' 508 509 # We export environment variables pointing to the wrapped nonstandard 510 # cmds, lest some lousy configure script use those to guess compiler 511 # version. 512 + '' 513 export named_cc=${targetPrefix}cc 514 export named_cxx=${targetPrefix}c++ 515 516 if [ -e $ccPath/${targetPrefix}gcc ]; then 517 wrap ${targetPrefix}gcc $wrapper $ccPath/${targetPrefix}gcc 518 ln -s ${targetPrefix}gcc $out/bin/${targetPrefix}cc 519 export named_cc=${targetPrefix}gcc 520 export named_cxx=${targetPrefix}g++ 521 elif [ -e $ccPath/clang ]; then 522 wrap ${targetPrefix}clang $wrapper $ccPath/clang 523 ln -s ${targetPrefix}clang $out/bin/${targetPrefix}cc 524 export named_cc=${targetPrefix}clang 525 export named_cxx=${targetPrefix}clang++ 526 elif [ -e $ccPath/arocc ]; then 527 wrap ${targetPrefix}arocc $wrapper $ccPath/arocc 528 ln -s ${targetPrefix}arocc $out/bin/${targetPrefix}cc 529 export named_cc=${targetPrefix}arocc 530 fi 531 532 if [ -e $ccPath/${targetPrefix}g++ ]; then 533 wrap ${targetPrefix}g++ $wrapper $ccPath/${targetPrefix}g++ 534 ln -s ${targetPrefix}g++ $out/bin/${targetPrefix}c++ 535 elif [ -e $ccPath/clang++ ]; then 536 wrap ${targetPrefix}clang++ $wrapper $ccPath/clang++ 537 ln -s ${targetPrefix}clang++ $out/bin/${targetPrefix}c++ 538 fi 539 540 if [ -e $ccPath/${targetPrefix}cpp ]; then 541 wrap ${targetPrefix}cpp $wrapper $ccPath/${targetPrefix}cpp 542 elif [ -e $ccPath/cpp ]; then 543 wrap ${targetPrefix}cpp $wrapper $ccPath/cpp 544 fi 545 '' 546 547 # No need to wrap gnat, gnatkr, gnatname or gnatprep; we can just symlink them in 548 + optionalString cc.langAda or false '' 549 for cmd in gnatbind gnatchop gnatclean gnatlink gnatls gnatmake; do 550 wrap ${targetPrefix}$cmd ${./gnat-wrapper.sh} $ccPath/${targetPrefix}$cmd 551 done 552 553 for cmd in gnat gnatkr gnatname gnatprep; do 554 ln -s $ccPath/${targetPrefix}$cmd $out/bin/${targetPrefix}$cmd 555 done 556 557 # this symlink points to the unwrapped gnat's output "out". It is used by 558 # our custom gprconfig compiler description to find GNAT's ada runtime. See 559 # ../../development/ada-modules/gprbuild/{boot.nix, nixpkgs-gnat.xml} 560 ln -sf ${cc} $out/nix-support/gprconfig-gnat-unwrapped 561 '' 562 563 + optionalString cc.langD or false '' 564 wrap ${targetPrefix}gdc $wrapper $ccPath/${targetPrefix}gdc 565 '' 566 567 + optionalString cc.langFortran or false '' 568 wrap ${targetPrefix}gfortran $wrapper $ccPath/${targetPrefix}gfortran 569 ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}g77 570 ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}f77 571 export named_fc=${targetPrefix}gfortran 572 '' 573 574 + optionalString cc.langJava or false '' 575 wrap ${targetPrefix}gcj $wrapper $ccPath/${targetPrefix}gcj 576 '' 577 578 + optionalString cc.langGo or false '' 579 wrap ${targetPrefix}gccgo $wrapper $ccPath/${targetPrefix}gccgo 580 wrap ${targetPrefix}go ${./go-wrapper.sh} $ccPath/${targetPrefix}go 581 ''; 582 583 strictDeps = true; 584 propagatedBuildInputs = [ 585 bintools 586 ] 587 ++ extraTools 588 ++ optionals cc.langD or cc.langJava or false [ zlib ]; 589 depsTargetTargetPropagated = optional (libcxx != null) libcxx ++ extraPackages; 590 591 setupHooks = [ 592 ../setup-hooks/role.bash 593 ] 594 ++ optional (cc.langC or true) ./setup-hook.sh 595 ++ optional (cc.langFortran or false) ./fortran-hook.sh 596 ++ optional (targetPlatform.isWindows) ( 597 stdenvNoCC.mkDerivation { 598 name = "win-dll-hook.sh"; 599 dontUnpack = true; 600 installPhase = '' 601 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib" > $out 602 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib64" >> $out 603 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib32" >> $out 604 ''; 605 } 606 ); 607 608 postFixup = 609 # Ensure flags files exists, as some other programs cat them. (That these 610 # are considered an exposed interface is a bit dubious, but fine for now.) 611 '' 612 touch "$out/nix-support/cc-cflags" 613 touch "$out/nix-support/cc-ldflags" 614 '' 615 616 # Backwards compatibility for packages expecting this file, e.g. with 617 # `$NIX_CC/nix-support/dynamic-linker`. 618 # 619 # TODO(@Ericson2314): Remove this after stable release and force 620 # everyone to refer to bintools-wrapper directly. 621 + optionalString (!isArocc) '' 622 if [[ -f "$bintools/nix-support/dynamic-linker" ]]; then 623 ln -s "$bintools/nix-support/dynamic-linker" "$out/nix-support" 624 fi 625 if [[ -f "$bintools/nix-support/dynamic-linker-m32" ]]; then 626 ln -s "$bintools/nix-support/dynamic-linker-m32" "$out/nix-support" 627 fi 628 '' 629 630 ## 631 ## GCC libs for non-GCC support 632 ## 633 + optionalString (useGccForLibs && isClang) '' 634 635 echo "-B${gccForLibs}/lib/gcc/${targetPlatform.config}/${gccForLibs.version}" >> $out/nix-support/cc-cflags 636 '' 637 + optionalString (useGccForLibs && !isArocc) '' 638 echo "-L${gccForLibs}/lib/gcc/${targetPlatform.config}/${gccForLibs.version}" >> $out/nix-support/cc-ldflags 639 echo "-L${gccForLibs_solib}/lib" >> $out/nix-support/cc-ldflags 640 '' 641 642 # TODO We would like to connect this to `useGccForLibs`, but we cannot yet 643 # because `libcxxStdenv` on linux still needs this. Maybe someday we'll 644 # always set `useLLVM` on Darwin, and maybe also break down `useLLVM` into 645 # fine-grained use flags (libgcc vs compiler-rt, ld.lld vs legacy, libc++ 646 # vs libstdc++, etc.) since Darwin isn't `useLLVM` on all counts. (See 647 # https://clang.llvm.org/docs/Toolchain.html for all the axes one might 648 # break `useLLVM` into.) 649 + 650 optionalString 651 ( 652 isClang 653 && targetPlatform.isLinux 654 && !(targetPlatform.useAndroidPrebuilt or false) 655 && !(targetPlatform.useLLVM or false) 656 && gccForLibs != null 657 ) 658 ( 659 '' 660 echo "--gcc-toolchain=${gccForLibs}" >> $out/nix-support/cc-cflags 661 662 # Pull in 'cc.out' target to get 'libstdc++fs.a'. It should be in 663 # 'cc.lib'. But it's a gcc package bug. 664 # TODO(trofi): remove once gcc is fixed to move libraries to .lib output. 665 echo "-L${gccForLibs}/${ 666 optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}" 667 }/lib" >> $out/nix-support/cc-ldflags 668 '' 669 # this ensures that when clang passes -lgcc_s to lld (as it does 670 # when building e.g. firefox), lld is able to find libgcc_s.so 671 + optionals (!isArocc) ( 672 concatMapStrings (libgcc: '' 673 echo "-L${libgcc}/lib" >> $out/nix-support/cc-ldflags 674 '') (toList (gccForLibs.libgcc or [ ])) 675 ) 676 ) 677 678 ## 679 ## General libc support 680 ## 681 682 # The "-B${libc_lib}/lib/" flag is a quick hack to force gcc to link 683 # against the crt1.o from our own glibc, rather than the one in 684 # /usr/lib. (This is only an issue when using an `impure' 685 # compiler/linker, i.e., one that searches /usr/lib and so on.) 686 # 687 # Unfortunately, setting -B appears to override the default search 688 # path. Thus, the gcc-specific "../includes-fixed" directory is 689 # now longer searched and glibc's <limits.h> header fails to 690 # compile, because it uses "#include_next <limits.h>" to find the 691 # limits.h file in ../includes-fixed. To remedy the problem, 692 # another -idirafter is necessary to add that directory again. 693 + optionalString (libc != null) ( 694 '' 695 touch "$out/nix-support/libc-cflags" 696 touch "$out/nix-support/libc-ldflags" 697 '' 698 + optionalString (!isArocc) '' 699 echo "-B${libc_lib}${libc.libdir or "/lib/"}" >> $out/nix-support/libc-crt1-cflags 700 '' 701 + optionalString (!(cc.langD or false)) '' 702 include "-${ 703 if isArocc then "I" else "idirafter" 704 }" "${libc_dev}${libc.incdir or "/include"}" >> $out/nix-support/libc-cflags 705 '' 706 + optionalString (isGNU && (!(cc.langD or false))) '' 707 for dir in "${cc}"/lib/gcc/*/*/include-fixed; do 708 include '-idirafter' ''${dir} >> $out/nix-support/libc-cflags 709 done 710 '' 711 + '' 712 713 echo "${libc_lib}" > $out/nix-support/orig-libc 714 echo "${libc_dev}" > $out/nix-support/orig-libc-dev 715 '' 716 # fortify-headers is a set of wrapper headers that augment libc 717 # and use #include_next to pass through to libc's true 718 # implementations, so must appear before them in search order. 719 # in theory a correctly placed -idirafter could be used, but in 720 # practice the compiler may have been built with a --with-headers 721 # like option that forces the libc headers before all -idirafter, 722 # hence -isystem here. 723 + optionalString includeFortifyHeaders' '' 724 include -isystem "${fortify-headers}/include" >> $out/nix-support/libc-cflags 725 '' 726 ) 727 728 ## 729 ## General libc++ support 730 ## 731 732 # We have a libc++ directly, we have one via "smuggled" GCC, or we have one 733 # bundled with the C compiler because it is GCC 734 + 735 optionalString 736 (libcxx != null || (useGccForLibs && gccForLibs.langCC or false) || (isGNU && cc.langCC or false)) 737 '' 738 touch "$out/nix-support/libcxx-cxxflags" 739 touch "$out/nix-support/libcxx-ldflags" 740 '' 741 # Adding -isystem flags should be done only for clang; gcc 742 # already knows how to find its own libstdc++, and adding 743 # additional -isystem flags will confuse gfortran (see 744 # https://github.com/NixOS/nixpkgs/pull/209870#issuecomment-1500550903) 745 + optionalString (libcxx == null && isClang && (useGccForLibs && gccForLibs.langCC or false)) '' 746 for dir in ${gccForLibs}/include/c++/*; do 747 include -isystem "$dir" >> $out/nix-support/libcxx-cxxflags 748 done 749 for dir in ${gccForLibs}/include/c++/*/${targetPlatform.config}; do 750 include -isystem "$dir" >> $out/nix-support/libcxx-cxxflags 751 done 752 '' 753 + optionalString (libcxx.isLLVM or false) '' 754 include -isystem "${getDev libcxx}/include/c++/v1" >> $out/nix-support/libcxx-cxxflags 755 echo "-stdlib=libc++" >> $out/nix-support/libcxx-ldflags 756 '' 757 # GCC NG friendly libc++ 758 + optionalString (libcxx != null && libcxx.isGNU or false) '' 759 include -isystem "${getDev libcxx}/include" >> $out/nix-support/libcxx-cxxflags 760 '' 761 762 ## 763 ## Initial CFLAGS 764 ## 765 766 # GCC shows ${cc_solib}/lib in `gcc -print-search-dirs', but not 767 # ${cc_solib}/lib64 (even though it does actually search there...).. 768 # This confuses libtool. So add it to the compiler tool search 769 # path explicitly. 770 + optionalString (!nativeTools && !isArocc) '' 771 if [ -e "${cc_solib}/lib64" -a ! -L "${cc_solib}/lib64" ]; then 772 ccLDFlags+=" -L${cc_solib}/lib64" 773 ccCFlags+=" -B${cc_solib}/lib64" 774 fi 775 ccLDFlags+=" -L${cc_solib}/lib" 776 ccCFlags+=" -B${cc_solib}/lib" 777 778 '' 779 + optionalString (cc.langAda or false && !isArocc) '' 780 touch "$out/nix-support/gnat-cflags" 781 touch "$out/nix-support/gnat-ldflags" 782 basePath=$(echo $cc/lib/*/*/*) 783 ccCFlags+=" -B$basePath -I$basePath/adainclude" 784 gnatCFlags="-I$basePath/adainclude -I$basePath/adalib" 785 786 echo "$gnatCFlags" >> $out/nix-support/gnat-cflags 787 '' 788 + '' 789 echo "$ccLDFlags" >> $out/nix-support/cc-ldflags 790 echo "$ccCFlags" >> $out/nix-support/cc-cflags 791 '' 792 + optionalString (targetPlatform.isDarwin && (libcxx != null) && (cc.isClang or false)) '' 793 echo " -L${libcxx_solib}" >> $out/nix-support/cc-ldflags 794 '' 795 796 ## Prevent clang from seeing /usr/include. There is a desire to achieve this 797 ## through alternate means because it breaks -sysroot and related functionality. 798 # 799 # This flag prevents global system header directories from 800 # leaking through on non‐NixOS Linux. However, on macOS, the 801 # SDK path is used as the sysroot, and forcing `-nostdlibinc` 802 # breaks `-isysroot` with an unwrapped compiler. As macOS has 803 # no `/usr/include`, there’s essentially no risk to dropping 804 # the flag there. See discussion in NixOS/nixpkgs#191152. 805 # 806 + 807 optionalString 808 ( 809 (cc.isClang or false) 810 && !(cc.isROCm or false) 811 && !targetPlatform.isDarwin 812 && !targetPlatform.isAndroid 813 ) 814 '' 815 echo " -nostdlibinc" >> $out/nix-support/cc-cflags 816 '' 817 818 ## 819 ## Man page and info support 820 ## 821 + optionalString propagateDoc '' 822 ln -s ${cc.man} $man 823 ln -s ${cc.info} $info 824 '' 825 + optionalString (cc.langD or cc.langJava or false && !isArocc) '' 826 echo "-B${zlib}${zlib.libdir or "/lib/"}" >> $out/nix-support/libc-cflags 827 '' 828 829 ## 830 ## Hardening support 831 ## 832 + '' 833 export hardening_unsupported_flags="${concatStringsSep " " ccHardeningUnsupportedFlags}" 834 '' 835 836 # Do not prevent omission of framepointers on x86 32bit due to the small 837 # number of general purpose registers. Keeping EBP available provides 838 # non-trivial performance benefits. 839 # Also skip s390/s390x as it fails to build glibc and causes 840 # performance regressions: 841 # https://bugs.launchpad.net/ubuntu-z-systems/+bug/2064538 842 # https://github.com/NixOS/nixpkgs/issues/428260 843 + ( 844 let 845 enable_fp = !targetPlatform.isx86_32 && !targetPlatform.isS390; 846 enable_leaf_fp = 847 enable_fp 848 && ( 849 targetPlatform.isx86_64 850 || targetPlatform.isAarch64 851 || (targetPlatform.isRiscV && (!isGNU || versionAtLeast ccVersion "15.1")) 852 ); 853 in 854 optionalString enable_fp '' 855 echo " -fno-omit-frame-pointer ${optionalString enable_leaf_fp "-mno-omit-leaf-frame-pointer "}" >> $out/nix-support/cc-cflags-before 856 '' 857 ) 858 859 # For clang, this is handled in add-clang-cc-cflags-before.sh 860 + optionalString (!isClang && machineFlags != [ ]) '' 861 printf "%s\n" ${lib.escapeShellArgs machineFlags} >> $out/nix-support/cc-cflags-before 862 '' 863 864 # TODO: categorize these and figure out a better place for them 865 + optionalString targetPlatform.isWindows '' 866 hardening_unsupported_flags+=" pic" 867 '' 868 + optionalString targetPlatform.isMinGW '' 869 hardening_unsupported_flags+=" stackprotector fortify" 870 '' 871 + optionalString targetPlatform.isAvr '' 872 hardening_unsupported_flags+=" stackprotector pic" 873 '' 874 + optionalString (targetPlatform.libc == "newlib" || targetPlatform.libc == "newlib-nano") '' 875 hardening_unsupported_flags+=" stackprotector fortify pie pic" 876 '' 877 + optionalString (targetPlatform.libc == "musl" && targetPlatform.isx86_32) '' 878 hardening_unsupported_flags+=" stackprotector" 879 '' 880 + optionalString targetPlatform.isNetBSD '' 881 hardening_unsupported_flags+=" stackprotector fortify" 882 '' 883 + optionalString cc.langAda or false '' 884 hardening_unsupported_flags+=" format stackprotector strictoverflow" 885 '' 886 + optionalString cc.langD or false '' 887 hardening_unsupported_flags+=" format" 888 '' 889 + optionalString cc.langFortran or false '' 890 hardening_unsupported_flags+=" format" 891 '' 892 + optionalString targetPlatform.isWasm '' 893 hardening_unsupported_flags+=" stackprotector fortify pie pic" 894 '' 895 + optionalString targetPlatform.isMicroBlaze '' 896 hardening_unsupported_flags+=" stackprotector" 897 '' 898 899 + optionalString (libc != null && targetPlatform.isAvr && !isArocc) '' 900 for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do 901 echo "-B${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-crt1-cflags 902 done 903 '' 904 905 + optionalString targetPlatform.isAndroid '' 906 echo "-D__ANDROID_API__=${targetPlatform.androidSdkVersion}" >> $out/nix-support/cc-cflags 907 '' 908 909 # There are a few tools (to name one libstdcxx5) which do not work 910 # well with multi line flags, so make the flags single line again 911 + '' 912 for flags in "$out/nix-support"/*flags*; do 913 substituteInPlace "$flags" --replace $'\n' ' ' 914 done 915 916 substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh 917 substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh 918 substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash 919 substituteAll ${../wrapper-common/darwin-sdk-setup.bash} $out/nix-support/darwin-sdk-setup.bash 920 '' 921 922 + optionalString cc.langAda or false '' 923 substituteAll ${./add-gnat-extra-flags.sh} $out/nix-support/add-gnat-extra-flags.sh 924 '' 925 926 ## 927 ## General Clang support 928 ## Needs to go after ^ because the for loop eats \n and makes this file an invalid script 929 ## 930 + optionalString isClang ( 931 let 932 hasUnsupportedGnuSuffix = hasPrefix "gnuabielfv" targetPlatform.parsed.abi.name; 933 clangCompatibleConfig = 934 if hasUnsupportedGnuSuffix then 935 removeSuffix (removePrefix "gnu" targetPlatform.parsed.abi.name) targetPlatform.config 936 else 937 targetPlatform.config; 938 explicitAbiValue = if hasUnsupportedGnuSuffix then targetPlatform.parsed.abi.abi else ""; 939 in 940 '' 941 # Escape twice: once for this script, once for the one it gets substituted into. 942 export machineFlags=${escapeShellArg (escapeShellArgs machineFlags)} 943 export defaultTarget=${clangCompatibleConfig} 944 export explicitAbiValue=${explicitAbiValue} 945 substituteAll ${./add-clang-cc-cflags-before.sh} $out/nix-support/add-local-cc-cflags-before.sh 946 '' 947 ) 948 949 ## 950 ## Extra custom steps 951 ## 952 + extraBuildCommands 953 + concatStringsSep "; " ( 954 mapAttrsToList (name: value: "echo ${toString value} >> $out/nix-support/${name}") nixSupport 955 ); 956 957 env = { 958 inherit isClang; 959 960 # for substitution in utils.bash 961 # TODO(@sternenseemann): invent something cleaner than passing in "" in case of absence 962 expandResponseParams = lib.optionalString (expand-response-params != "") ( 963 lib.getExe expand-response-params 964 ); 965 # TODO(@sternenseemann): rename env var via stdenv rebuild 966 shell = getBin runtimeShell + runtimeShell.shellPath or ""; 967 gnugrep_bin = optionalString (!nativeTools) gnugrep; 968 rm = if nativeTools then "rm" else lib.getExe' coreutils "rm"; 969 mktemp = if nativeTools then "mktemp" else lib.getExe' coreutils "mktemp"; 970 # stdenv.cc.cc should not be null and we have nothing better for now. 971 # if the native impure bootstrap is gotten rid of this can become `inherit cc;` again. 972 cc = optionalString (!nativeTools) cc; 973 wrapperName = "CC_WRAPPER"; 974 inherit suffixSalt coreutils_bin bintools; 975 inherit libc_bin libc_dev libc_lib; 976 inherit darwinPlatformForCC; 977 default_hardening_flags_str = builtins.toString defaultHardeningFlags; 978 inherit useMacroPrefixMap; 979 } 980 // lib.mapAttrs (_: lib.optionalString targetPlatform.isDarwin) { 981 # These will become empty strings when not targeting Darwin. 982 inherit (targetPlatform) darwinMinVersion darwinMinVersionVariable; 983 } 984 // lib.optionalAttrs (stdenvNoCC.targetPlatform.isDarwin && apple-sdk != null) { 985 # Wrapped compilers should do something useful even when no SDK is provided at `DEVELOPER_DIR`. 986 fallback_sdk = apple-sdk.__spliced.buildTarget or apple-sdk; 987 }; 988 989 meta = 990 let 991 cc_ = optionalAttrs (cc != null) cc; 992 in 993 (optionalAttrs (cc_ ? meta) (removeAttrs cc.meta [ "priority" ])) 994 // { 995 description = attrByPath [ "meta" "description" ] "System C compiler" cc_ + " (wrapper script)"; 996 priority = 10; 997 mainProgram = if name != "" then name else "${targetPrefix}${ccName}"; 998 }; 999}