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".
12 , cc ? null, libc ? null, bintools, coreutils ? null
14 , nativeTools, noLibc ? false, nativeLibc, nativePrefix ? ""
15 , propagateDoc ? cc != null && cc ? man
16 , extraTools ? [], extraPackages ? [], extraBuildCommands ? ""
18 , isGNU ? false, isClang ? cc.isClang or false, isZig ? cc.isZig or false
19 , isArocc ? cc.isArocc or false, isCcache ? cc.isCcache or false
21 , expand-response-params
24 # Whether or not to add `-B` and `-L` to `nix-support/cc-{c,ld}flags`
27 # Always add these flags for Clang, because in order to compile (most
28 # software) it needs libraries that are shipped and compiled with gcc.
31 # Never add these flags for a build!=host cross-compiler or a host!=target
32 # ("cross-built-native") compiler; currently nixpkgs has a special build
33 # path for these (`crossStageStatic`). Hopefully at some point that build
34 # path will be merged with this one and this conditional will be removed.
35 else if (with stdenvNoCC; buildPlatform != hostPlatform || hostPlatform != targetPlatform) then false
37 # Never add these flags when wrapping the bootstrapFiles' compiler; it has a
38 # /usr/-like layout with everything smashed into a single outpath, so it has
39 # no trouble finding its own libraries.
40 else if (cc.passthru.isFromBootstrapFiles or false) then false
42 # Add these flags when wrapping `xgcc` (the first compiler that nixpkgs builds)
43 else if (cc.passthru.isXgcc or false) then true
45 # Add these flags when wrapping `stdenv.cc`
46 else if (cc.stdenv.cc.cc.passthru.isXgcc or false) then true
48 # Do not add these flags in any other situation. This is `false` mainly to
49 # prevent these flags from being added when wrapping *old* versions of gcc
50 # (e.g. `gcc6Stdenv`), since they will cause the old gcc to get `-B` and
51 # `-L` flags pointing at the new gcc's libstdc++ headers. Example failure:
52 # https://hydra.nixos.org/build/213125495
55 # the derivation at which the `-B` and `-L` flags added by `useCcForLibs` will point
56 , gccForLibs ? if useCcForLibs then cc else null
57 , fortify-headers ? null
58 , includeFortifyHeaders ? null
61 assert nativeTools -> !propagateDoc && nativePrefix != "";
62 assert !nativeTools -> cc != null && coreutils != null && gnugrep != null;
63 assert !(nativeLibc && noLibc);
64 assert (noLibc || nativeLibc) == (libc == null);
89 inherit (stdenvNoCC) hostPlatform targetPlatform;
91 includeFortifyHeaders' = if includeFortifyHeaders != null
92 then includeFortifyHeaders
93 else (targetPlatform.libc == "musl" && isGNU);
95 # Prefix for binaries. Customarily ends with a dash separator.
97 # TODO(@Ericson2314) Make unconditional, or optional but always true by default.
98 targetPrefix = optionalString (targetPlatform != hostPlatform) (targetPlatform.config + "-");
100 ccVersion = getVersion cc;
101 ccName = removePrefix targetPrefix (getName cc);
103 libc_bin = optionalString (libc != null) (getBin libc);
104 libc_dev = optionalString (libc != null) (getDev libc);
105 libc_lib = optionalString (libc != null) (getLib libc);
107 + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}";
109 # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
110 coreutils_bin = optionalString (!nativeTools) (getBin coreutils);
112 # The "suffix salt" is a arbitrary string added in the end of env vars
113 # defined by cc-wrapper's hooks so that multiple cc-wrappers can be used
114 # without interfering. For the moment, it is defined as the target triple,
115 # adjusted to be a valid bash identifier. This should be considered an
116 # unstable implementation detail, however.
117 suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
119 useGccForLibs = useCcForLibs
121 && !targetPlatform.isDarwin
122 && !(targetPlatform.useLLVM or false)
123 && !(targetPlatform.useAndroidPrebuilt or false)
124 && !(targetPlatform.isiOS or false)
125 && gccForLibs != null;
126 gccForLibs_solib = getLib gccForLibs
127 + optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}";
129 # Analogously to cc_solib and gccForLibs_solib
130 libcxx_solib = "${getLib libcxx}/lib";
132 # The following two functions, `isGccArchSupported` and
133 # `isGccTuneSupported`, only handle those situations where a flag
134 # (`-march` or `-mtune`) is accepted by one compiler but rejected
135 # by another, and both compilers are relevant to nixpkgs. We are
136 # not trying to maintain a complete list of all flags accepted by
137 # all versions of all compilers ever in nixpkgs.
139 # The two main cases of interest are:
141 # - One compiler is gcc and the other is clang
142 # - One compiler is pkgs.gcc and the other is bootstrap-files.gcc
143 # -- older compilers (for example bootstrap's GCC 5) fail with
144 # -march=too-modern-cpu
146 isGccArchSupported = arch:
147 if targetPlatform.isPower then false else # powerpc does not allow -march=
150 x86-64-v2 = versionAtLeast ccVersion "11.0";
151 x86-64-v3 = versionAtLeast ccVersion "11.0";
152 x86-64-v4 = versionAtLeast ccVersion "11.0";
156 skylake-avx512 = true;
157 cannonlake = versionAtLeast ccVersion "8.0";
158 icelake-client = versionAtLeast ccVersion "8.0";
159 icelake-server = versionAtLeast ccVersion "8.0";
160 cascadelake = versionAtLeast ccVersion "9.0";
161 cooperlake = versionAtLeast ccVersion "10.0";
162 tigerlake = versionAtLeast ccVersion "10.0";
163 knm = versionAtLeast ccVersion "8.0";
164 alderlake = versionAtLeast ccVersion "12.0";
165 sapphirerapids = versionAtLeast ccVersion "11.0";
166 emeraldrapids = versionAtLeast ccVersion "13.0";
170 znver2 = versionAtLeast ccVersion "9.0";
171 znver3 = versionAtLeast ccVersion "11.0";
172 znver4 = versionAtLeast ccVersion "13.0";
176 x86-64-v2 = versionAtLeast ccVersion "12.0";
177 x86-64-v3 = versionAtLeast ccVersion "12.0";
178 x86-64-v4 = versionAtLeast ccVersion "12.0";
181 cannonlake = versionAtLeast ccVersion "5.0";
182 icelake-client = versionAtLeast ccVersion "7.0";
183 icelake-server = versionAtLeast ccVersion "7.0";
184 knm = versionAtLeast ccVersion "7.0";
185 alderlake = versionAtLeast ccVersion "16.0";
186 sapphirerapids = versionAtLeast ccVersion "12.0";
187 emeraldrapids = versionAtLeast ccVersion "16.0";
190 znver1 = versionAtLeast ccVersion "4.0";
191 znver2 = versionAtLeast ccVersion "9.0";
192 znver3 = versionAtLeast ccVersion "12.0";
193 znver4 = versionAtLeast ccVersion "16.0";
198 isGccTuneSupported = tune:
199 # for x86 -mtune= takes the same values as -march, plus two more:
200 if targetPlatform.isx86 then
204 }.${tune} or (isGccArchSupported tune)
205 # on arm64, the -mtune= values are specific processors
206 else if targetPlatform.isAarch64 then
211 "cortex-a72.cortex-a53" = true;
215 cortex-a53 = versionAtLeast ccVersion "3.9"; # llvm dfc5d1
218 else if targetPlatform.isPower then
219 # powerpc does not support -march
221 else if targetPlatform.isMips then
222 # for mips -mtune= takes the same values as -march
223 isGccArchSupported tune
227 # Clang does not support as many `-mtune=` values as gcc does;
228 # this function will return the best possible approximation of the
229 # provided `-mtune=` value, or `null` if none exists.
231 # Note: this function can make use of ccVersion; for example, `if
232 # versionOlder ccVersion "12" then ...`
233 findBestTuneApproximation = tune:
234 let guess = if isClang
236 # clang does not tune for big.LITTLE chips
237 "cortex-a72.cortex-a53" = "cortex-a72";
240 in if isGccTuneSupported guess
244 thumb = if targetPlatform.gcc.thumb then "thumb" else "arm";
245 tune = if targetPlatform ? gcc.tune
246 then findBestTuneApproximation targetPlatform.gcc.tune
249 # Machine flags. These are necessary to support
251 # TODO: We should make a way to support miscellaneous machine
252 # flags and other gcc flags as well.
255 # Always add -march based on cpu in triple. Sometimes there is a
256 # discrepency (x86_64 vs. x86-64), so we provide an "arch" arg in
258 optional (targetPlatform ? gcc.arch && !(targetPlatform.isDarwin && targetPlatform.isAarch64) && isGccArchSupported targetPlatform.gcc.arch) "-march=${targetPlatform.gcc.arch}" ++
259 # TODO: aarch64-darwin has mcpu incompatible with gcc
260 optional (targetPlatform ? gcc.cpu && !(targetPlatform.isDarwin && targetPlatform.isAarch64)) "-mcpu=${targetPlatform.gcc.cpu}" ++
261 # -mfloat-abi only matters on arm32 but we set it here
262 # unconditionally just in case. If the abi specifically sets hard
263 # vs. soft floats we use it here.
264 optional (targetPlatform ? gcc.float-abi) "-mfloat-abi=${targetPlatform.gcc.float-abi}" ++
265 optional (targetPlatform ? gcc.fpu) "-mfpu=${targetPlatform.gcc.fpu}" ++
266 optional (targetPlatform ? gcc.mode) "-mmode=${targetPlatform.gcc.mode}" ++
267 optional (targetPlatform ? gcc.thumb) "-m${thumb}" ++
268 optional (tune != null) "-mtune=${tune}";
270 defaultHardeningFlags = bintools.defaultHardeningFlags or [];
272 # if cc.hardeningUnsupportedFlagsByTargetPlatform exists, this is
273 # called with the targetPlatform as an argument and
274 # cc.hardeningUnsupportedFlags is completely ignored - the function
275 # is responsible for including the constant hardeningUnsupportedFlags
276 # list however it sees fit.
277 ccHardeningUnsupportedFlags = if cc ? hardeningUnsupportedFlagsByTargetPlatform
278 then cc.hardeningUnsupportedFlagsByTargetPlatform targetPlatform
279 else (cc.hardeningUnsupportedFlags or []);
281 darwinPlatformForCC = optionalString targetPlatform.isDarwin (
282 if (targetPlatform.darwinPlatform == "macos" && isGNU) then "macosx"
283 else targetPlatform.darwinPlatform
286 darwinMinVersion = optionalString targetPlatform.isDarwin (
287 targetPlatform.darwinMinVersion
290 darwinMinVersionVariable = optionalString targetPlatform.isDarwin
291 targetPlatform.darwinMinVersionVariable;
294 assert includeFortifyHeaders' -> fortify-headers != null;
296 # Ensure bintools matches
297 assert libc_bin == bintools.libc_bin;
298 assert libc_dev == bintools.libc_dev;
299 assert libc_lib == bintools.libc_lib;
300 assert nativeTools == bintools.nativeTools;
301 assert nativeLibc == bintools.nativeLibc;
302 assert nativePrefix == bintools.nativePrefix;
304 stdenvNoCC.mkDerivation {
306 + (if name != "" then name else "${ccName}-wrapper");
307 version = optionalString (cc != null) ccVersion;
309 preferLocalBuild = true;
311 outputs = [ "out" ] ++ optionals propagateDoc [ "man" "info" ];
313 # Cannot be in "passthru" due to "substituteAll"
317 inherit targetPrefix suffixSalt;
318 # "cc" is the generic name for a C compiler, but there is no one for package
319 # providing the linker and related tools. The two we use now are GNU
320 # Binutils, and Apple's "cctools"; "bintools" as an attempt to find an
321 # unused middle-ground name that evokes both.
323 inherit cc libc libcxx nativeTools nativeLibc nativePrefix isGNU isClang isZig;
325 emacsBufferSetup = pkgs: ''
326 ; We should handle propagation here too
329 (when (file-directory-p (concat arg "/include"))
330 (setenv "NIX_CFLAGS_COMPILE_${suffixSalt}" (concat (getenv "NIX_CFLAGS_COMPILE_${suffixSalt}") " -isystem " arg "/include"))))
331 '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
334 # Expose expand-response-params we are /actually/ using. In stdenv
335 # bootstrapping, expand-response-params usually comes from an earlier stage,
336 # so it is important to expose this for reference checking.
337 inherit expand-response-params;
341 inherit defaultHardeningFlags;
345 dontConfigure = true;
346 enableParallelBuilding = true;
352 wrapper = ./cc-wrapper.sh;
356 mkdir -p $out/bin $out/nix-support
362 export use_response_file_by_default=${if isClang && !isCcache then "1" else "0"}
363 substituteAll "$wrapper" "$out/bin/$dst"
364 chmod +x "$out/bin/$dst"
368 + (if nativeTools then ''
369 echo ${if targetPlatform.isDarwin then cc else nativePrefix} > $out/nix-support/orig-cc
371 ccPath="${if targetPlatform.isDarwin then cc else nativePrefix}/bin"
373 echo $cc > $out/nix-support/orig-cc
378 # Create symlinks to everything in the bintools wrapper.
380 for bbin in $bintools/bin/*; do
382 ln -s "$bbin" "$out/bin/$(basename $bbin)"
386 # We export environment variables pointing to the wrapped nonstandard
387 # cmds, lest some lousy configure script use those to guess compiler
390 export named_cc=${targetPrefix}cc
391 export named_cxx=${targetPrefix}c++
393 if [ -e $ccPath/${targetPrefix}gcc ]; then
394 wrap ${targetPrefix}gcc $wrapper $ccPath/${targetPrefix}gcc
395 ln -s ${targetPrefix}gcc $out/bin/${targetPrefix}cc
396 export named_cc=${targetPrefix}gcc
397 export named_cxx=${targetPrefix}g++
398 elif [ -e $ccPath/clang ]; then
399 wrap ${targetPrefix}clang $wrapper $ccPath/clang
400 ln -s ${targetPrefix}clang $out/bin/${targetPrefix}cc
401 export named_cc=${targetPrefix}clang
402 export named_cxx=${targetPrefix}clang++
403 elif [ -e $ccPath/arocc ]; then
404 wrap ${targetPrefix}arocc $wrapper $ccPath/arocc
405 ln -s ${targetPrefix}arocc $out/bin/${targetPrefix}cc
406 export named_cc=${targetPrefix}arocc
409 if [ -e $ccPath/${targetPrefix}g++ ]; then
410 wrap ${targetPrefix}g++ $wrapper $ccPath/${targetPrefix}g++
411 ln -s ${targetPrefix}g++ $out/bin/${targetPrefix}c++
412 elif [ -e $ccPath/clang++ ]; then
413 wrap ${targetPrefix}clang++ $wrapper $ccPath/clang++
414 ln -s ${targetPrefix}clang++ $out/bin/${targetPrefix}c++
417 if [ -e $ccPath/${targetPrefix}cpp ]; then
418 wrap ${targetPrefix}cpp $wrapper $ccPath/${targetPrefix}cpp
419 elif [ -e $ccPath/cpp ]; then
420 wrap ${targetPrefix}cpp $wrapper $ccPath/cpp
424 # No need to wrap gnat, gnatkr, gnatname or gnatprep; we can just symlink them in
425 + optionalString cc.langAda or false ''
426 for cmd in gnatbind gnatchop gnatclean gnatlink gnatls gnatmake; do
427 wrap ${targetPrefix}$cmd ${./gnat-wrapper.sh} $ccPath/${targetPrefix}$cmd
430 for cmd in gnat gnatkr gnatname gnatprep; do
431 ln -s $ccPath/${targetPrefix}$cmd $out/bin/${targetPrefix}$cmd
434 # this symlink points to the unwrapped gnat's output "out". It is used by
435 # our custom gprconfig compiler description to find GNAT's ada runtime. See
436 # ../../development/ada-modules/gprbuild/{boot.nix, nixpkgs-gnat.xml}
437 ln -sf ${cc} $out/nix-support/gprconfig-gnat-unwrapped
440 + optionalString cc.langD or false ''
441 wrap ${targetPrefix}gdc $wrapper $ccPath/${targetPrefix}gdc
444 + optionalString cc.langFortran or false ''
445 wrap ${targetPrefix}gfortran $wrapper $ccPath/${targetPrefix}gfortran
446 ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}g77
447 ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}f77
448 export named_fc=${targetPrefix}gfortran
451 + optionalString cc.langJava or false ''
452 wrap ${targetPrefix}gcj $wrapper $ccPath/${targetPrefix}gcj
455 + optionalString cc.langGo or false ''
456 wrap ${targetPrefix}gccgo $wrapper $ccPath/${targetPrefix}gccgo
457 wrap ${targetPrefix}go ${./go-wrapper.sh} $ccPath/${targetPrefix}go
461 propagatedBuildInputs = [ bintools ] ++ extraTools ++ optionals cc.langD or cc.langJava or false [ zlib ];
462 depsTargetTargetPropagated = optional (libcxx != null) libcxx ++ extraPackages;
465 ../setup-hooks/role.bash
466 ] ++ optional (cc.langC or true) ./setup-hook.sh
467 ++ optional (cc.langFortran or false) ./fortran-hook.sh
468 ++ optional (targetPlatform.isWindows) (stdenvNoCC.mkDerivation {
469 name = "win-dll-hook.sh";
472 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib" > $out
473 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib64" >> $out
474 echo addToSearchPath "LINK_DLL_FOLDERS" "${cc_solib}/lib32" >> $out
479 # Ensure flags files exists, as some other programs cat them. (That these
480 # are considered an exposed interface is a bit dubious, but fine for now.)
482 touch "$out/nix-support/cc-cflags"
483 touch "$out/nix-support/cc-ldflags"
486 # Backwards compatibility for packages expecting this file, e.g. with
487 # `$NIX_CC/nix-support/dynamic-linker`.
489 # TODO(@Ericson2314): Remove this after stable release and force
490 # everyone to refer to bintools-wrapper directly.
491 + optionalString (!isArocc) ''
492 if [[ -f "$bintools/nix-support/dynamic-linker" ]]; then
493 ln -s "$bintools/nix-support/dynamic-linker" "$out/nix-support"
495 if [[ -f "$bintools/nix-support/dynamic-linker-m32" ]]; then
496 ln -s "$bintools/nix-support/dynamic-linker-m32" "$out/nix-support"
501 ## GCC libs for non-GCC support
503 + optionalString (useGccForLibs && isClang) ''
505 echo "-B${gccForLibs}/lib/gcc/${targetPlatform.config}/${gccForLibs.version}" >> $out/nix-support/cc-cflags
507 + optionalString (useGccForLibs && !isArocc) ''
508 echo "-L${gccForLibs}/lib/gcc/${targetPlatform.config}/${gccForLibs.version}" >> $out/nix-support/cc-ldflags
509 echo "-L${gccForLibs_solib}/lib" >> $out/nix-support/cc-ldflags
512 # TODO We would like to connect this to `useGccForLibs`, but we cannot yet
513 # because `libcxxStdenv` on linux still needs this. Maybe someday we'll
514 # always set `useLLVM` on Darwin, and maybe also break down `useLLVM` into
515 # fine-grained use flags (libgcc vs compiler-rt, ld.lld vs legacy, libc++
516 # vs libstdc++, etc.) since Darwin isn't `useLLVM` on all counts. (See
517 # https://clang.llvm.org/docs/Toolchain.html for all the axes one might
518 # break `useLLVM` into.)
519 + optionalString (isClang
520 && targetPlatform.isLinux
521 && !(targetPlatform.useAndroidPrebuilt or false)
522 && !(targetPlatform.useLLVM or false)
523 && gccForLibs != null) (''
524 echo "--gcc-toolchain=${gccForLibs}" >> $out/nix-support/cc-cflags
526 # Pull in 'cc.out' target to get 'libstdc++fs.a'. It should be in
527 # 'cc.lib'. But it's a gcc package bug.
528 # TODO(trofi): remove once gcc is fixed to move libraries to .lib output.
529 echo "-L${gccForLibs}/${optionalString (targetPlatform != hostPlatform) "/${targetPlatform.config}"}/lib" >> $out/nix-support/cc-ldflags
531 # this ensures that when clang passes -lgcc_s to lld (as it does
532 # when building e.g. firefox), lld is able to find libgcc_s.so
533 + optionals (!isArocc) (concatMapStrings (libgcc: ''
534 echo "-L${libgcc}/lib" >> $out/nix-support/cc-ldflags
535 '') (toList (gccForLibs.libgcc or []))))
538 ## General libc support
541 # The "-B${libc_lib}/lib/" flag is a quick hack to force gcc to link
542 # against the crt1.o from our own glibc, rather than the one in
543 # /usr/lib. (This is only an issue when using an `impure'
544 # compiler/linker, i.e., one that searches /usr/lib and so on.)
546 # Unfortunately, setting -B appears to override the default search
547 # path. Thus, the gcc-specific "../includes-fixed" directory is
548 # now longer searched and glibc's <limits.h> header fails to
549 # compile, because it uses "#include_next <limits.h>" to find the
550 # limits.h file in ../includes-fixed. To remedy the problem,
551 # another -idirafter is necessary to add that directory again.
552 + optionalString (libc != null) (''
553 touch "$out/nix-support/libc-cflags"
554 touch "$out/nix-support/libc-ldflags"
555 '' + optionalString (!isArocc) ''
556 echo "-B${libc_lib}${libc.libdir or "/lib/"}" >> $out/nix-support/libc-crt1-cflags
557 '' + optionalString (!(cc.langD or false)) ''
558 echo "-${if isArocc then "I" else "idirafter"} ${libc_dev}${libc.incdir or "/include"}" >> $out/nix-support/libc-cflags
559 '' + optionalString (isGNU && (!(cc.langD or false))) ''
560 for dir in "${cc}"/lib/gcc/*/*/include-fixed; do
561 echo '-idirafter' ''${dir} >> $out/nix-support/libc-cflags
565 echo "${libc_lib}" > $out/nix-support/orig-libc
566 echo "${libc_dev}" > $out/nix-support/orig-libc-dev
568 # fortify-headers is a set of wrapper headers that augment libc
569 # and use #include_next to pass through to libc's true
570 # implementations, so must appear before them in search order.
571 # in theory a correctly placed -idirafter could be used, but in
572 # practice the compiler may have been built with a --with-headers
573 # like option that forces the libc headers before all -idirafter,
574 # hence -isystem here.
575 + optionalString includeFortifyHeaders' ''
576 echo "-isystem ${fortify-headers}/include" >> $out/nix-support/libc-cflags
580 ## General libc++ support
583 # We have a libc++ directly, we have one via "smuggled" GCC, or we have one
584 # bundled with the C compiler because it is GCC
585 + optionalString (libcxx != null || (useGccForLibs && gccForLibs.langCC or false) || (isGNU && cc.langCC or false)) ''
586 touch "$out/nix-support/libcxx-cxxflags"
587 touch "$out/nix-support/libcxx-ldflags"
589 # Adding -isystem flags should be done only for clang; gcc
590 # already knows how to find its own libstdc++, and adding
591 # additional -isystem flags will confuse gfortran (see
592 # https://github.com/NixOS/nixpkgs/pull/209870#issuecomment-1500550903)
593 + optionalString (libcxx == null && isClang && (useGccForLibs && gccForLibs.langCC or false)) ''
594 for dir in ${gccForLibs}/include/c++/*; do
595 echo "-isystem $dir" >> $out/nix-support/libcxx-cxxflags
597 for dir in ${gccForLibs}/include/c++/*/${targetPlatform.config}; do
598 echo "-isystem $dir" >> $out/nix-support/libcxx-cxxflags
601 + optionalString (libcxx.isLLVM or false) ''
602 echo "-isystem ${getDev libcxx}/include/c++/v1" >> $out/nix-support/libcxx-cxxflags
603 echo "-stdlib=libc++" >> $out/nix-support/libcxx-ldflags
610 # GCC shows ${cc_solib}/lib in `gcc -print-search-dirs', but not
611 # ${cc_solib}/lib64 (even though it does actually search there...)..
612 # This confuses libtool. So add it to the compiler tool search
614 + optionalString (!nativeTools && !isArocc) ''
615 if [ -e "${cc_solib}/lib64" -a ! -L "${cc_solib}/lib64" ]; then
616 ccLDFlags+=" -L${cc_solib}/lib64"
617 ccCFlags+=" -B${cc_solib}/lib64"
619 ccLDFlags+=" -L${cc_solib}/lib"
620 ccCFlags+=" -B${cc_solib}/lib"
622 '' + optionalString (cc.langAda or false && !isArocc) ''
623 touch "$out/nix-support/gnat-cflags"
624 touch "$out/nix-support/gnat-ldflags"
625 basePath=$(echo $cc/lib/*/*/*)
626 ccCFlags+=" -B$basePath -I$basePath/adainclude"
627 gnatCFlags="-I$basePath/adainclude -I$basePath/adalib"
629 echo "$gnatCFlags" >> $out/nix-support/gnat-cflags
631 echo "$ccLDFlags" >> $out/nix-support/cc-ldflags
632 echo "$ccCFlags" >> $out/nix-support/cc-cflags
633 '' + optionalString (targetPlatform.isDarwin && (libcxx != null) && (cc.isClang or false)) ''
634 echo " -L${libcxx_solib}" >> $out/nix-support/cc-ldflags
638 ## Man page and info support
640 + optionalString propagateDoc ''
642 ln -s ${cc.info} $info
643 '' + optionalString (cc.langD or cc.langJava or false && !isArocc) ''
644 echo "-B${zlib}${zlib.libdir or "/lib/"}" >> $out/nix-support/libc-cflags
651 export hardening_unsupported_flags="${concatStringsSep " " ccHardeningUnsupportedFlags}"
654 # For clang, this is handled in add-clang-cc-cflags-before.sh
655 + lib.optionalString (!isClang && machineFlags != []) ''
656 printf "%s\n" ${lib.escapeShellArgs machineFlags} >> $out/nix-support/cc-cflags-before
659 # TODO: categorize these and figure out a better place for them
660 + optionalString targetPlatform.isWindows ''
661 hardening_unsupported_flags+=" pic"
662 '' + optionalString targetPlatform.isMinGW ''
663 hardening_unsupported_flags+=" stackprotector fortify"
664 '' + optionalString targetPlatform.isAvr ''
665 hardening_unsupported_flags+=" stackprotector pic"
666 '' + optionalString (targetPlatform.libc == "newlib" || targetPlatform.libc == "newlib-nano") ''
667 hardening_unsupported_flags+=" stackprotector fortify pie pic"
668 '' + optionalString (targetPlatform.libc == "musl" && targetPlatform.isx86_32) ''
669 hardening_unsupported_flags+=" stackprotector"
670 '' + optionalString targetPlatform.isNetBSD ''
671 hardening_unsupported_flags+=" stackprotector fortify"
672 '' + optionalString cc.langAda or false ''
673 hardening_unsupported_flags+=" format stackprotector strictoverflow"
674 '' + optionalString cc.langD or false ''
675 hardening_unsupported_flags+=" format"
676 '' + optionalString cc.langFortran or false ''
677 hardening_unsupported_flags+=" format"
678 '' + optionalString targetPlatform.isWasm ''
679 hardening_unsupported_flags+=" stackprotector fortify pie pic"
680 '' + optionalString targetPlatform.isMicroBlaze ''
681 hardening_unsupported_flags+=" stackprotector"
684 + optionalString (libc != null && targetPlatform.isAvr && !isArocc) ''
685 for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do
686 echo "-B${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-crt1-cflags
690 + optionalString targetPlatform.isDarwin ''
691 echo "-arch ${targetPlatform.darwinArch}" >> $out/nix-support/cc-cflags
694 + optionalString targetPlatform.isAndroid ''
695 echo "-D__ANDROID_API__=${targetPlatform.androidSdkVersion}" >> $out/nix-support/cc-cflags
698 # There are a few tools (to name one libstdcxx5) which do not work
699 # well with multi line flags, so make the flags single line again
701 for flags in "$out/nix-support"/*flags*; do
702 substituteInPlace "$flags" --replace $'\n' ' '
705 substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
706 substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
707 substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash
710 + optionalString cc.langAda or false ''
711 substituteAll ${./add-gnat-extra-flags.sh} $out/nix-support/add-gnat-extra-flags.sh
715 ## General Clang support
716 ## Needs to go after ^ because the for loop eats \n and makes this file an invalid script
718 + optionalString isClang ''
719 # Escape twice: once for this script, once for the one it gets substituted into.
720 export machineFlags=${escapeShellArg (escapeShellArgs machineFlags)}
721 export defaultTarget=${targetPlatform.config}
722 substituteAll ${./add-clang-cc-cflags-before.sh} $out/nix-support/add-local-cc-cflags-before.sh
726 ## Extra custom steps
729 + concatStringsSep "; "
731 (name: value: "echo ${toString value} >> $out/nix-support/${name}")
738 # for substitution in utils.bash
739 # TODO(@sternenseemann): invent something cleaner than passing in "" in case of absence
740 expandResponseParams = "${expand-response-params}/bin/expand-response-params";
741 # TODO(@sternenseemann): rename env var via stdenv rebuild
742 shell = getBin runtimeShell + runtimeShell.shellPath or "";
743 gnugrep_bin = optionalString (!nativeTools) gnugrep;
744 # stdenv.cc.cc should not be null and we have nothing better for now.
745 # if the native impure bootstrap is gotten rid of this can become `inherit cc;` again.
746 cc = optionalString (!nativeTools) cc;
747 wrapperName = "CC_WRAPPER";
748 inherit suffixSalt coreutils_bin bintools;
749 inherit libc_bin libc_dev libc_lib;
750 inherit darwinPlatformForCC darwinMinVersion darwinMinVersionVariable;
751 default_hardening_flags_str = builtins.toString defaultHardeningFlags;
755 let cc_ = optionalAttrs (cc != null) cc; in
756 (optionalAttrs (cc_ ? meta) (removeAttrs cc.meta ["priority"])) //
757 { description = attrByPath ["meta" "description"] "System C compiler" cc_ + " (wrapper script)";
759 mainProgram = if name != "" then name else "${targetPrefix}${ccName}";