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