summary refs log tree commit diff
path: root/pkgs/development/compilers/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/compilers/gcc')
-rw-r--r--pkgs/development/compilers/gcc/all.nix50
-rw-r--r--pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix24
-rw-r--r--pkgs/development/compilers/gcc/common/libgcc.nix4
-rw-r--r--pkgs/development/compilers/gcc/common/pre-configure.nix6
-rw-r--r--pkgs/development/compilers/gcc/default.nix54
-rw-r--r--pkgs/development/compilers/gcc/patches/11/libgcc-aarch64-darwin-detection.patch21
-rw-r--r--pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch85
-rw-r--r--pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch84
-rw-r--r--pkgs/development/compilers/gcc/patches/4.9/darwin-clang-as.patch16
-rw-r--r--pkgs/development/compilers/gcc/patches/8/gcc8-darwin-as-gstabs.patch96
-rw-r--r--pkgs/development/compilers/gcc/patches/9/gcc9-darwin-as-gstabs.patch99
-rw-r--r--pkgs/development/compilers/gcc/patches/clang-genconditions.patch34
-rw-r--r--pkgs/development/compilers/gcc/patches/default.nix24
-rw-r--r--pkgs/development/compilers/gcc/versions.nix38
14 files changed, 589 insertions, 46 deletions
diff --git a/pkgs/development/compilers/gcc/all.nix b/pkgs/development/compilers/gcc/all.nix
new file mode 100644
index 00000000000..70b4b75369a
--- /dev/null
+++ b/pkgs/development/compilers/gcc/all.nix
@@ -0,0 +1,50 @@
+{ lib
+, stdenv
+, gccStdenv
+, gcc7Stdenv
+, callPackage
+, isl_0_11, isl_0_14, isl_0_17, isl_0_20
+, libcCross
+, threadsCrossFor
+, noSysDirs
+, texinfo5
+, cloog_0_18_0, cloog
+, lowPrio
+, wrapCC
+}@args:
+
+let
+  versions = import ./versions.nix;
+  gccForMajorMinorVersion = majorMinorVersion:
+    let
+      atLeast = lib.versionAtLeast majorMinorVersion;
+      attrName = "gcc${lib.replaceStrings ["."] [""] majorMinorVersion}";
+      pkg = lowPrio (wrapCC (callPackage ./default.nix ({
+        inherit noSysDirs;
+        inherit majorMinorVersion;
+        reproducibleBuild = true;
+        profiledCompiler = false;
+        libcCross = if stdenv.targetPlatform != stdenv.buildPlatform then args.libcCross else null;
+        threadsCross = if stdenv.targetPlatform != stdenv.buildPlatform then threadsCrossFor majorMinorVersion else { };
+        isl = if       stdenv.isDarwin then null
+              else if    atLeast "9"   then isl_0_20
+              else if    atLeast "7"   then isl_0_17
+              else if    atLeast "6"   then (if stdenv.targetPlatform.isRedox then isl_0_17 else isl_0_14)
+              else if    atLeast "4.9" then isl_0_11
+              else            /* "4.8" */   isl_0_14;
+      } // lib.optionalAttrs (majorMinorVersion == "4.8") {
+        texinfo = texinfo5; # doesn't validate since 6.1 -> 6.3 bump
+      } // lib.optionalAttrs (!(atLeast "6")) {
+        cloog = if stdenv.isDarwin
+                then null
+                else if atLeast "4.9" then cloog_0_18_0
+                else          /* 4.8 */    cloog;
+      } // lib.optionalAttrs (atLeast "6" && !(atLeast "9")) {
+        # gcc 10 is too strict to cross compile gcc <= 8
+        stdenv = if (stdenv.targetPlatform != stdenv.buildPlatform) && stdenv.cc.isGNU then gcc7Stdenv else stdenv;
+      })));
+    in
+      lib.nameValuePair attrName pkg;
+in
+lib.listToAttrs (map gccForMajorMinorVersion versions.allMajorVersions)
+
diff --git a/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix b/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix
index e7dc570a560..239d6026800 100644
--- a/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix
+++ b/pkgs/development/compilers/gcc/common/libgcc-buildstuff.nix
@@ -31,7 +31,23 @@ let
   #
   SHLIB_LC = lib.optionalString stdenv.targetPlatform.isPower "-mnewlib";
 
-in ''
-    echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in
-    echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in
-  ''
+in
+''
+  echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in
+  echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in
+''
+
+  # Meanwhile, crt{i,n}.S are not present on certain platforms
+  # (e.g. LoongArch64), resulting in the following error:
+  #
+  # No rule to make target '../../../gcc-xx.x.x/libgcc/config/loongarch/crti.S', needed by 'crti.o'.  Stop.
+  #
+  # For LoongArch64 and S390, a hacky workaround is to simply touch them,
+  # as the platform forces .init_array support.
+  #
+  # https://www.openwall.com/lists/musl/2022/11/09/3
+  #
+  # 'parsed.cpu.family' won't be correct for every platform.
++ lib.optionalString (stdenv.targetPlatform.isLoongArch64 || stdenv.targetPlatform.isS390) ''
+  touch libgcc/config/${stdenv.targetPlatform.parsed.cpu.family}/crt{i,n}.S
+''
diff --git a/pkgs/development/compilers/gcc/common/libgcc.nix b/pkgs/development/compilers/gcc/common/libgcc.nix
index f3bf14e36f7..c8342ae9005 100644
--- a/pkgs/development/compilers/gcc/common/libgcc.nix
+++ b/pkgs/development/compilers/gcc/common/libgcc.nix
@@ -36,7 +36,7 @@ lib.optionals (lib.versionAtLeast version "11.0")
 
 (let
   targetPlatformSlash =
-    if hostPlatform.config == targetPlatform.config
+    if hostPlatform == targetPlatform
     then ""
     else "${targetPlatform.config}/";
 
@@ -83,7 +83,7 @@ in
     lib.optionalString (!langC) ''
       rm -f $out/lib/libgcc_s.so*
     ''
-    + lib.optionalString (hostPlatform.config != targetPlatform.config) ''
+    + lib.optionalString (hostPlatform != targetPlatform) ''
       mkdir -p $lib/lib/
       ln -s ${targetPlatformSlash}lib $lib/lib
     ''
diff --git a/pkgs/development/compilers/gcc/common/pre-configure.nix b/pkgs/development/compilers/gcc/common/pre-configure.nix
index 32e203ee491..77179d73976 100644
--- a/pkgs/development/compilers/gcc/common/pre-configure.nix
+++ b/pkgs/development/compilers/gcc/common/pre-configure.nix
@@ -116,10 +116,12 @@ in lib.optionalString (hostPlatform.isSunOS && hostPlatform.is64bit) ''
 
 # Normally (for host != target case) --without-headers automatically
 # enables 'inhibit_libc=true' in gcc's gcc/configure.ac. But case of
-# gcc->clang "cross"-compilation manages to evade it: there
+# gcc->clang or dynamic->static "cross"-compilation manages to evade it: there
 # hostPlatform != targetPlatform, hostPlatform.config == targetPlatform.config.
 # We explicitly inhibit libc headers use in this case as well.
-+ lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc) ''
++ lib.optionalString (targetPlatform != hostPlatform &&
+                      withoutTargetLibc &&
+                      targetPlatform.config == hostPlatform.config) ''
   export inhibit_libc=true
 ''
 
diff --git a/pkgs/development/compilers/gcc/default.nix b/pkgs/development/compilers/gcc/default.nix
index eb77b6f3652..01f17251308 100644
--- a/pkgs/development/compilers/gcc/default.nix
+++ b/pkgs/development/compilers/gcc/default.nix
@@ -33,6 +33,7 @@
 , nukeReferences
 , callPackage
 , majorMinorVersion
+, darwin
 
 # only for gcc<=6.x
 , langJava ? false
@@ -47,18 +48,8 @@
 }:
 
 let
-  version = {
-    "13" = "13.2.0";
-    "12" = "12.3.0";
-    "11" = "11.4.0";
-    "10" = "10.5.0";
-    "9"  =  "9.5.0";
-    "8"  =  "8.5.0";
-    "7"  =  "7.5.0";
-    "6"  =  "6.5.0";
-    "4.9"=  "4.9.4";
-    "4.8"=  "4.8.5";
-  }."${majorMinorVersion}";
+  versions = import ./versions.nix;
+  version = versions.fromMajorMinor majorMinorVersion;
 
   majorVersion = lib.versions.major version;
   atLeast13 = lib.versionAtLeast version "13";
@@ -117,8 +108,8 @@ let inherit version;
 
     /* Cross-gcc settings (build == host != target) */
     crossMingw = targetPlatform != hostPlatform && targetPlatform.isMinGW;
-    stageNameAddon = if withoutTargetLibc then "stage-static" else "stage-final";
-    crossNameAddon = optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-${stageNameAddon}-";
+    stageNameAddon = optionalString withoutTargetLibc "-nolibc";
+    crossNameAddon = optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}${stageNameAddon}-";
 
     javaAwtGtk = langJava && x11Support;
     xlibs = [
@@ -255,18 +246,8 @@ lib.pipe ((callFile ./common/builder.nix {}) ({
           else if atLeast6
           then "mirror://gnu/gcc/gcc-${version}/gcc-${version}.tar.xz"
           else "mirror://gnu/gcc/gcc-${version}/gcc-${version}.tar.bz2";
-    ${if is10 || is11 || is13 then "hash" else "sha256"} = {
-      "13.2.0" = "sha256-4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o=";
-      "12.3.0" = "sha256-lJpdT5nnhkIak7Uysi/6tVeN5zITaZdbka7Jet/ajDs=";
-      "11.4.0" = "sha256-Py2yIrAH6KSiPNW6VnJu8I6LHx6yBV7nLBQCzqc6jdk=";
-      "10.5.0" = "sha256-JRCVQ/30bzl8NHtdi3osflaUpaUczkucbh6opxyjB8E=";
-      "9.5.0"  = "13ygjmd938m0wmy946pxdhz9i1wq7z4w10l6pvidak0xxxj9yxi7";
-      "8.5.0"  = "0l7d4m9jx124xsk6xardchgy2k5j5l2b15q322k31f0va4d8826k";
-      "7.5.0"  = "0qg6kqc5l72hpnj4vr6l0p69qav0rh4anlkk3y55540zy3klc6dq";
-      "6.5.0"  = "0i89fksfp6wr1xg9l8296aslcymv2idn60ip31wr9s4pwin7kwby";
-      "4.9.4"  = "14l06m7nvcvb0igkbip58x59w3nq6315k6jcz3wr9ch1rn9d44bc";
-      "4.8.5"  = "08yggr18v373a1ihj0rg2vd6psnic42b518xcgp3r9k81xz1xyr2";
-    }."${version}";
+    ${if is10 || is11 || is13 then "hash" else "sha256"} =
+      versions.srcHashForVersion version;
   };
 
   inherit patches;
@@ -311,17 +292,15 @@ lib.pipe ((callFile ./common/builder.nix {}) ({
         libc = if libcCross != null then libcCross else stdenv.cc.libc;
       in
         (
-        '' echo "fixing the \`GLIBC_DYNAMIC_LINKER'${lib.optionalString atLeast6 ", \\`UCLIBC_DYNAMIC_LINKER',"} and \`${if atLeast6 then "MUSL" else "UCLIBC"}_DYNAMIC_LINKER' macros..."
+        '' echo "fixing the {GLIBC,UCLIBC,MUSL}_DYNAMIC_LINKER macros..."
            for header in "gcc/config/"*-gnu.h "gcc/config/"*"/"*.h
            do
              grep -q ${lib.optionalString (!atLeast6) "LIBC"}_DYNAMIC_LINKER "$header" || continue
-             echo "  fixing \`$header'..."
+             echo "  fixing $header..."
              sed -i "$header" \
-                 -e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g'${lib.optionalString atLeast6 " \\"}
-        '' + lib.optionalString atLeast6 ''
-${""}                -e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g'
-        '' + ''
-${""}          done
+                 -e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g' \
+                 -e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g'
+             done
         '' + lib.optionalString (atLeast6 && targetPlatform.libc == "musl") ''
            sed -i gcc/config/linux.h -e '1i#undef LOCAL_INCLUDE_DIR'
         ''
@@ -329,9 +308,7 @@ ${""}          done
     ))
       + lib.optionalString (atLeast7 && targetPlatform.isAvr) (''
             makeFlagsArray+=(
-          '' + (lib.optionalString atLeast10 ''
                '-s' # workaround for hitting hydra log limit
-          '') + ''
                'LIMITS_H_TEST=false'
             )
           '');
@@ -432,10 +409,15 @@ ${""}          done
       maintainers
     ;
   } // lib.optionalAttrs (!atLeast11) {
-    badPlatforms = if !is49 then [ "aarch64-darwin" ] else lib.platforms.darwin;
+    badPlatforms = if !(is48 || is49) then [ "aarch64-darwin" ] else lib.platforms.darwin;
   };
 } // optionalAttrs is7 {
   env.NIX_CFLAGS_COMPILE = lib.optionalString (stdenv.cc.isClang && langFortran) "-Wno-unused-command-line-argument";
+} // lib.optionalAttrs (!atLeast10 && stdenv.hostPlatform.isDarwin) {
+  # GCC <10 requires default cctools `strip` instead of `llvm-strip` used by Darwin bintools.
+  preBuild = ''
+    makeFlagsArray+=('STRIP=${lib.getBin darwin.cctools-port}/bin/${stdenv.cc.targetPrefix}strip')
+  '';
 } // optionalAttrs (!atLeast7) {
   env.langJava = langJava;
 } // optionalAttrs atLeast6 {
diff --git a/pkgs/development/compilers/gcc/patches/11/libgcc-aarch64-darwin-detection.patch b/pkgs/development/compilers/gcc/patches/11/libgcc-aarch64-darwin-detection.patch
new file mode 100644
index 00000000000..08dbfec6b24
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/11/libgcc-aarch64-darwin-detection.patch
@@ -0,0 +1,21 @@
+diff -u a/libgcc/config.host b/libgcc/config.host
+--- a/libgcc/config.host	2023-11-05 11:01:55.778638446 -0500
++++ b/libgcc/config.host	2023-11-05 11:07:29.405103979 -0500
+@@ -227,7 +227,7 @@
+   tmake_file="$tmake_file t-slibgcc-darwin"
+   # newer toolsets produce warnings when building for unsupported versions.
+   case ${host} in
+-    *-*-darwin1[89]* | *-*-darwin2* )
++    *-*-darwin1[89]* | *-*-darwin2* | aarch64*-*-darwin*)
+       tmake_file="t-darwin-min-8 $tmake_file"
+       ;;
+     *-*-darwin9* | *-*-darwin1[0-7]*)
+diff -ur a/libgcc/config/t-darwin-rpath b/libgcc/config/t-darwin-rpath
+--- a/libgcc/config/t-darwin-rpath	2023-11-05 11:34:18.691150009 -0500
++++ b/libgcc/config/t-darwin-rpath	2023-11-05 11:50:36.968920904 -0500
+@@ -2,4 +2,4 @@
+ SHLIB_RPATH = @rpath
+
+ # Which does not work for Darwin < 9
+-HOST_LIBGCC2_CFLAGS += -mmacosx-version-min=10.5
++SHLIB_LOADER_PATH = -Wl,-rpath,@loader_path
diff --git a/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch b/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch
new file mode 100644
index 00000000000..d938d67a2d0
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/12/mangle-NIX_STORE-in-__FILE__.patch
@@ -0,0 +1,85 @@
+From b10785c1be469319a09b10bc69db21159b0599ee Mon Sep 17 00:00:00 2001
+From: Sergei Trofimovich <siarheit@google.com>
+Date: Fri, 22 Sep 2023 22:41:49 +0100
+Subject: [PATCH] gcc/file-prefix-map.cc: always mangle __FILE__ into invalid
+ store path
+
+Without the change `__FILE__` used in static inline functions in headers
+embed paths to header files into executable images. For local headers
+it's not a problem, but for headers in `/nix/store` this causes `-dev`
+inputs to be retained in runtime closure.
+
+Typical examples are `nix` -> `nlohmann_json` and `pipewire` ->
+`lttng-ust.dev`.
+
+Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as:
+
+  -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver
+  -fmacro-prefix-map=/nix/...
+
+In practice it quickly exhausts argument lengtth limit due to `gcc`
+deficiency: https://gcc.gnu.org/PR111527
+
+Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
+is present in the environment.
+
+Tested as:
+
+    $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o -
+    ...
+    .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv"
+    ...
+
+Mangled successfully.
+--- a/gcc/file-prefix-map.cc
++++ b/gcc/file-prefix-map.cc
+@@ -60,6 +60,9 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
+   maps = map;
+ }
+ 
++/* Forward declaration for a $NIX_STORE remap hack below. */
++static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
++
+ /* Perform user-specified mapping of filename prefixes.  Return the
+    GC-allocated new name corresponding to FILENAME or FILENAME if no
+    remapping was performed.  */
+@@ -76,7 +79,30 @@ remap_filename (file_prefix_map *maps, const char *filename)
+     if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
+       break;
+   if (!map)
+-    return filename;
++    {
++      if (maps == macro_prefix_maps)
++	{
++	  /* Remap all fo $NIX_STORE/.{32} paths to
++	  * equivalent $NIX_STORE/e{32}.
++	  *
++	  * That way we avoid argument parameters explosion
++	  * and still avoid embedding headers into runtime closure:
++	  *   https://gcc.gnu.org/PR111527
++	  */
++	  char * nix_store = getenv("NIX_STORE");
++	  size_t nix_store_len = nix_store ? strlen(nix_store) : 0;
++	  const char * name = filename;
++	  size_t name_len = strlen(name);
++	  if (nix_store && name_len >= nix_store_len + 1 + 32 && memcmp(name, nix_store, nix_store_len) == 0)
++	    {
++	       s = (char *) ggc_alloc_atomic (name_len + 1);
++	       memcpy(s, name, name_len + 1);
++	       memset(s + nix_store_len + 1, 'e', 32);
++	       return s;
++	    }
++	}
++      return filename;
++    }
+   name = filename + map->old_len;
+   name_len = strlen (name) + 1;
+ 
+@@ -90,7 +116,6 @@ remap_filename (file_prefix_map *maps, const char *filename)
+    ignore it in DW_AT_producer (dwarf2out.cc).  */
+ 
+ /* Linked lists of file_prefix_map structures.  */
+-static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
+ static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map  */
+ static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map  */
+ 
diff --git a/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch b/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch
new file mode 100644
index 00000000000..57ae2111f02
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/13/mangle-NIX_STORE-in-__FILE__.patch
@@ -0,0 +1,84 @@
+From b10785c1be469319a09b10bc69db21159b0599ee Mon Sep 17 00:00:00 2001
+From: Sergei Trofimovich <siarheit@google.com>
+Date: Fri, 22 Sep 2023 22:41:49 +0100
+Subject: [PATCH] gcc/file-prefix-map.cc: always mangle __FILE__ into invalid
+ store path
+
+Without the change `__FILE__` used in static inline functions in headers
+embed paths to header files into executable images. For local headers
+it's not a problem, but for headers in `/nix/store` this causes `-dev`
+inputs to be retained in runtime closure.
+
+Typical examples are `nix` -> `nlohmann_json` and `pipewire` ->
+`lttng-ust.dev`.
+
+Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as:
+
+  -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver
+  -fmacro-prefix-map=/nix/...
+
+In practice it quickly exhausts argument lengtth limit due to `gcc`
+deficiency: https://gcc.gnu.org/PR111527
+
+Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
+is present in the environment.
+
+Tested as:
+
+    $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o -
+    ...
+    .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv"
+    ...
+
+Mangled successfully.
+--- a/gcc/file-prefix-map.cc
++++ b/gcc/file-prefix-map.cc
+@@ -69,6 +69,9 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
+   maps = map;
+ }
+ 
++/* Forward declaration for a $NIX_STORE remap hack below. */
++static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
++
+ /* Perform user-specified mapping of filename prefixes.  Return the
+    GC-allocated new name corresponding to FILENAME or FILENAME if no
+    remapping was performed.  */
+@@ -102,6 +105,29 @@ remap_filename (file_prefix_map *maps, const char *filename)
+       break;
+   if (!map)
+     {
++      if (maps == macro_prefix_maps)
++	{
++	  /* Remap all fo $NIX_STORE/.{32} paths to
++	   * equivalent $NIX_STORE/e{32}.
++	   *
++	   * That way we avoid argument parameters explosion
++	   * and still avoid embedding headers into runtime closure:
++	   *   https://gcc.gnu.org/PR111527
++	   */
++	   char * nix_store = getenv("NIX_STORE");
++	   size_t nix_store_len = nix_store ? strlen(nix_store) : 0;
++	   const char * name = realname ? realname : filename;
++	   size_t name_len = strlen(name);
++	   if (nix_store && name_len >= nix_store_len + 1 + 32 && memcmp(name, nix_store, nix_store_len) == 0)
++	     {
++		s = (char *) ggc_alloc_atomic (name_len + 1);
++		memcpy(s, name, name_len + 1);
++		memset(s + nix_store_len + 1, 'e', 32);
++		if (realname != filename)
++		  free (const_cast <char *> (realname));
++		return s;
++	     }
++	}
+       if (realname != filename)
+ 	free (const_cast <char *> (realname));
+       return filename;
+@@ -124,7 +150,6 @@ remap_filename (file_prefix_map *maps, const char *filename)
+    ignore it in DW_AT_producer (gen_command_line_string in opts.cc).  */
+ 
+ /* Linked lists of file_prefix_map structures.  */
+-static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
+ static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map  */
+ static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map  */
+ 
+
diff --git a/pkgs/development/compilers/gcc/patches/4.9/darwin-clang-as.patch b/pkgs/development/compilers/gcc/patches/4.9/darwin-clang-as.patch
new file mode 100644
index 00000000000..095713eb6c8
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/4.9/darwin-clang-as.patch
@@ -0,0 +1,16 @@
+diff -ur a/libgcc/config/t-darwin b/libgcc/config/t-darwin
+--- a/libgcc/config/t-darwin	2012-07-14 09:50:59.000000000 -0400
++++ b/libgcc/config/t-darwin	2023-11-05 21:26:11.696825584 -0500
+@@ -7,12 +7,6 @@
+ crttme.o: $(srcdir)/config/darwin-crt-tm.c
+ 	$(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -DEND -c $<
+ 
+-# -pipe because there's an assembler bug, 4077127, which causes
+-# it to not properly process the first # directive, causing temporary
+-# file names to appear in stabs, causing the bootstrap to fail.  Using -pipe
+-# works around this by not having any temporary file names.
+-HOST_LIBGCC2_CFLAGS += -pipe
+-
+ # Use unwind-dw2-fde-darwin
+ LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/config/unwind-dw2-fde-darwin.c \
+   $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/pkgs/development/compilers/gcc/patches/8/gcc8-darwin-as-gstabs.patch b/pkgs/development/compilers/gcc/patches/8/gcc8-darwin-as-gstabs.patch
new file mode 100644
index 00000000000..1ac870e5729
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/8/gcc8-darwin-as-gstabs.patch
@@ -0,0 +1,96 @@
+Backported from https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b2cee5e1e89c8f939bc36fe9756befcb93d96982
+
+diff -ur a/gcc/config/darwin.h b/gcc/config/darwin.h
+--- a/gcc/config/darwin.h	2021-05-14 04:42:08.000000000 -0400
++++ b/gcc/config/darwin.h	2023-11-06 08:53:27.629155053 -0500
+@@ -233,12 +233,18 @@
+ 
+ #define DSYMUTIL "\ndsymutil"
+ 
++/* Spec that controls whether the debug linker is run automatically for
++   a link step.  This needs to be done if there is a source file on the
++   command line which will result in a temporary object (and debug is
++   enabled).  */
++
+ #define DSYMUTIL_SPEC \
+    "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+     %{v} \
+-    %{gdwarf-2:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
+-    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm: \
+-    %{gdwarf-2:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
++    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
++    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\
++      .f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
++    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
+ 
+ #define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC
+ 
+@@ -469,18 +475,31 @@
+ /* Default ASM_DEBUG_SPEC.  Darwin's as cannot currently produce dwarf
+    debugging data.  */
+ 
++#ifdef HAS_AS_STABS_DIRECTIVE
++/* We only pass a debug option to the assembler if that supports stabs, since
++   dwarf is not uniformly supported in the assemblers.  */
+ #define ASM_DEBUG_SPEC  "%{g*:%{%:debug-level-gt(0):%{!gdwarf*:--gstabs}}}"
++#else
++#define ASM_DEBUG_SPEC ""
++#endif
++
++#undef  ASM_DEBUG_OPTION_SPEC
++#define ASM_DEBUG_OPTION_SPEC  ""
++
+ #define ASM_FINAL_SPEC \
+   "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform } %<gsplit-dwarf"
+ 
+-/* We still allow output of STABS if the assembler supports it.  */
++/* We now require C++11 to bootstrap and newer tools than those based on
++   stabs, so require DWARF-2, even if stabs is supported by the assembler.  */
++
++#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
++#define DARWIN_PREFER_DWARF
++#define DWARF2_DEBUGGING_INFO 1
++
+ #ifdef HAVE_AS_STABS_DIRECTIVE
+ #define DBX_DEBUGGING_INFO 1
+-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+ #endif
+ 
+-#define DWARF2_DEBUGGING_INFO 1
+-
+ #define DEBUG_FRAME_SECTION	  "__DWARF,__debug_frame,regular,debug"
+ #define DEBUG_INFO_SECTION	  "__DWARF,__debug_info,regular,debug"
+ #define DEBUG_ABBREV_SECTION	  "__DWARF,__debug_abbrev,regular,debug"
+diff -ur a/gcc/config/darwin9.h b/gcc/config/darwin9.h
+--- a/gcc/config/darwin9.h	2021-05-14 04:42:08.000000000 -0400
++++ b/gcc/config/darwin9.h	2023-11-06 08:54:02.663945206 -0500
+@@ -18,29 +18,6 @@
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+-/* Prefer DWARF2.  */
+-#undef PREFERRED_DEBUGGING_TYPE
+-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+-#define DARWIN_PREFER_DWARF
+-
+-/* Since DWARF2 is default, conditions for running dsymutil are different.  */
+-#undef DSYMUTIL_SPEC
+-#define DSYMUTIL_SPEC \
+-   "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+-    %{v} \
+-    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
+-    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|.f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
+-    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
+-
+-/* Tell collect2 to run dsymutil for us as necessary.  */
+-#define COLLECT_RUN_DSYMUTIL 1
+-
+-/* Only ask as for debug data if the debug style is stabs (since as doesn't
+-   yet generate dwarf.)  */
+-
+-#undef  ASM_DEBUG_SPEC
+-#define ASM_DEBUG_SPEC  "%{g*:%{%:debug-level-gt(0):%{gstabs:--gstabs}}}"
+-
+ #undef  ASM_OUTPUT_ALIGNED_COMMON
+ #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)		\
+   do {									\
diff --git a/pkgs/development/compilers/gcc/patches/9/gcc9-darwin-as-gstabs.patch b/pkgs/development/compilers/gcc/patches/9/gcc9-darwin-as-gstabs.patch
new file mode 100644
index 00000000000..454139c5396
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/9/gcc9-darwin-as-gstabs.patch
@@ -0,0 +1,99 @@
+Backported from https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=b2cee5e1e89c8f939bc36fe9756befcb93d96982
+
+diff -ur a/gcc/config/darwin.h b/gcc/config/darwin.h
+--- a/gcc/config/darwin.h	2022-05-27 03:21:10.947379000 -0400
++++ b/gcc/config/darwin.h	2023-11-06 12:18:27.209236423 -0500
+@@ -230,12 +230,18 @@
+ 
+ #define DSYMUTIL "\ndsymutil"
+ 
++/* Spec that controls whether the debug linker is run automatically for
++   a link step.  This needs to be done if there is a source file on the
++   command line which will result in a temporary object (and debug is
++   enabled).  */
++
+ #define DSYMUTIL_SPEC \
+    "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+     %{v} \
+-    %{gdwarf-2:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
+-    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm: \
+-    %{gdwarf-2:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
++    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
++    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|\
++      .f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
++    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
+ 
+ #define LINK_COMMAND_SPEC LINK_COMMAND_SPEC_A DSYMUTIL_SPEC
+ 
+@@ -463,21 +469,31 @@
+   %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
+   %{static}" ASM_MMACOSX_VERSION_MIN_SPEC
+ 
+-/* Default ASM_DEBUG_SPEC.  Darwin's as cannot currently produce dwarf
+-   debugging data.  */
+-
++#ifdef HAS_AS_STABS_DIRECTIVE
++/* We only pass a debug option to the assembler if that supports stabs, since
++   dwarf is not uniformly supported in the assemblers.  */
+ #define ASM_DEBUG_SPEC  "%{g*:%{%:debug-level-gt(0):%{!gdwarf*:--gstabs}}}"
++#else
++#define ASM_DEBUG_SPEC ""
++#endif
++
++#undef  ASM_DEBUG_OPTION_SPEC
++#define ASM_DEBUG_OPTION_SPEC  ""
++
+ #define ASM_FINAL_SPEC \
+   "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} %<gsplit-dwarf"
+ 
+-/* We still allow output of STABS if the assembler supports it.  */
++/* We now require C++11 to bootstrap and newer tools than those based on
++   stabs, so require DWARF-2, even if stabs is supported by the assembler.  */
++
++#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
++#define DARWIN_PREFER_DWARF
++#define DWARF2_DEBUGGING_INFO 1
++
+ #ifdef HAVE_AS_STABS_DIRECTIVE
+ #define DBX_DEBUGGING_INFO 1
+-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+ #endif
+ 
+-#define DWARF2_DEBUGGING_INFO 1
+-
+ #define DEBUG_FRAME_SECTION	  "__DWARF,__debug_frame,regular,debug"
+ #define DEBUG_INFO_SECTION	  "__DWARF,__debug_info,regular,debug"
+ #define DEBUG_ABBREV_SECTION	  "__DWARF,__debug_abbrev,regular,debug"
+diff -ur a/gcc/config/darwin9.h b/gcc/config/darwin9.h
+--- a/gcc/config/darwin9.h	2022-05-27 03:21:10.947379000 -0400
++++ b/gcc/config/darwin9.h	2023-11-06 12:18:48.325260590 -0500
+@@ -18,29 +18,6 @@
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+-/* Prefer DWARF2.  */
+-#undef PREFERRED_DEBUGGING_TYPE
+-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+-#define DARWIN_PREFER_DWARF
+-
+-/* Since DWARF2 is default, conditions for running dsymutil are different.  */
+-#undef DSYMUTIL_SPEC
+-#define DSYMUTIL_SPEC \
+-   "%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+-    %{v} \
+-    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -idsym}}}\
+-    %{.c|.cc|.C|.cpp|.cp|.c++|.cxx|.CPP|.m|.mm|.s|.f|.f90|.f95|.f03|.f77|.for|.F|.F90|.F95|.F03: \
+-    %{g*:%{!gstabs*:%{%:debug-level-gt(0): -dsym}}}}}}}}}}}"
+-
+-/* Tell collect2 to run dsymutil for us as necessary.  */
+-#define COLLECT_RUN_DSYMUTIL 1
+-
+-/* Only ask as for debug data if the debug style is stabs (since as doesn't
+-   yet generate dwarf.)  */
+-
+-#undef  ASM_DEBUG_SPEC
+-#define ASM_DEBUG_SPEC  "%{g*:%{%:debug-level-gt(0):%{gstabs:--gstabs}}}"
+-
+ #undef  ASM_OUTPUT_ALIGNED_COMMON
+ #define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN)		\
+   do {									\
diff --git a/pkgs/development/compilers/gcc/patches/clang-genconditions.patch b/pkgs/development/compilers/gcc/patches/clang-genconditions.patch
new file mode 100644
index 00000000000..655afd2abbc
--- /dev/null
+++ b/pkgs/development/compilers/gcc/patches/clang-genconditions.patch
@@ -0,0 +1,34 @@
+From https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92061#c5
+
+--- a/gcc/genconditions.c	2019-01-01 12:37:19.064943662 +0100
++++ b/gcc/genconditions.c	2019-10-11 10:57:11.464595789 +0200
+@@ -57,8 +57,9 @@ write_header (void)
+ \n\
+ /* It is necessary, but not entirely safe, to include the headers below\n\
+    in a generator program.  As a defensive measure, don't do so when the\n\
+-   table isn't going to have anything in it.  */\n\
+-#if GCC_VERSION >= 3001\n\
++   table isn't going to have anything in it.\n\
++   Clang 9 is buggy and doesn't handle __builtin_constant_p correctly.  */\n\
++#if GCC_VERSION >= 3001 && __clang_major__ < 9\n\
+ \n\
+ /* Do not allow checking to confuse the issue.  */\n\
+ #undef CHECKING_P\n\
+@@ -170,7 +171,7 @@ struct c_test\n\
+    vary at run time.  It works in 3.0.1 and later; 3.0 only when not\n\
+    optimizing.  */\n\
+ \n\
+-#if GCC_VERSION >= 3001\n\
++#if GCC_VERSION >= 3001 && __clang_major__ < 9\n\
+ static const struct c_test insn_conditions[] = {\n");
+ 
+   traverse_c_tests (write_one_condition, 0);
+@@ -191,7 +192,7 @@ write_writer (void)
+ 	"  unsigned int i;\n"
+         "  const char *p;\n"
+         "  puts (\"(define_conditions [\");\n"
+-	"#if GCC_VERSION >= 3001\n"
++	"#if GCC_VERSION >= 3001 && __clang_major__ < 9\n"
+ 	"  for (i = 0; i < ARRAY_SIZE (insn_conditions); i++)\n"
+ 	"    {\n"
+ 	"      printf (\"  (%d \\\"\", insn_conditions[i].value);\n"
diff --git a/pkgs/development/compilers/gcc/patches/default.nix b/pkgs/development/compilers/gcc/patches/default.nix
index 0afc6586511..c4b0dbf91b6 100644
--- a/pkgs/development/compilers/gcc/patches/default.nix
+++ b/pkgs/development/compilers/gcc/patches/default.nix
@@ -63,8 +63,8 @@ in
 ++ optionals (noSysDirs) (
   [(if atLeast12 then ./gcc-12-no-sys-dirs.patch else ./no-sys-dirs.patch)] ++
   ({
-    "13" = [ ./13/no-sys-dirs-riscv.patch ];
-    "12" = [ ./no-sys-dirs-riscv.patch ];
+    "13" = [ ./13/no-sys-dirs-riscv.patch ./13/mangle-NIX_STORE-in-__FILE__.patch ];
+    "12" = [ ./no-sys-dirs-riscv.patch ./12/mangle-NIX_STORE-in-__FILE__.patch ];
     "11" = [ ./no-sys-dirs-riscv.patch ];
     "10" = [ ./no-sys-dirs-riscv.patch ];
     "9"  = [ ./no-sys-dirs-riscv-gcc9.patch ];
@@ -178,6 +178,9 @@ in
 # https://github.com/osx-cross/homebrew-avr/issues/280#issuecomment-1272381808
 ++ optional (is11 && stdenv.isDarwin && targetPlatform.isAvr) ./avr-gcc-11.3-darwin.patch
 
+# libgcc’s `configure` script misdetects aarch64-darwin, resulting in an invalid deployment target.
+++ optional (is11 && stdenv.isDarwin && stdenv.isAarch64) ./11/libgcc-aarch64-darwin-detection.patch
+
 # openjdk build fails without this on -march=opteron; is upstream in gcc12
 ++ optionals (is11) [ ./11/gcc-issue-103910.patch ]
 
@@ -191,12 +194,19 @@ in
   sha256 = "sha256-XtykrPd5h/tsnjY1wGjzSOJ+AyyNLsfnjuOZ5Ryq9vA=";
 })
 
+# Fix undefined symbol errors when building older versions with clang
+++ optional (!atLeast11 && stdenv.cc.isClang && stdenv.hostPlatform.isDarwin) ./clang-genconditions.patch
+
 
 ## gcc 9.0 and older ##############################################################################
 
 ++ optional (majorVersion == "9") ./9/fix-struct-redefinition-on-glibc-2.36.patch
 ++ optional (atLeast7 && !atLeast10 && targetPlatform.isNetBSD) ./libstdc++-netbsd-ctypes.patch
 
+# Make Darwin bootstrap respect whether the assembler supports `--gstabs`,
+# which is not supported by the clang integrated assembler used by default on Darwin.
+++ optional (is9 && hostPlatform.isDarwin) ./9/gcc9-darwin-as-gstabs.patch
+
 
 ## gcc 8.0 and older ##############################################################################
 
@@ -204,6 +214,10 @@ in
 ++ optional (atLeast49 && !is49 && !atLeast9) ./libsanitizer-no-cyclades-9.patch
 ++ optional (is7 || is8) ./9/fix-struct-redefinition-on-glibc-2.36.patch
 
+# Make Darwin bootstrap respect whether the assembler supports `--gstabs`,
+# which is not supported by the clang integrated assembler used by default on Darwin.
+++ optional (is8 && hostPlatform.isDarwin) ./8/gcc8-darwin-as-gstabs.patch
+
 
 ## gcc 7.0 and older ##############################################################################
 
@@ -240,6 +254,12 @@ in
   ./6/gnat-glibc234.patch
 ]
 
+# The clang-based assembler used in darwin.cctools-llvm (LLVM >11) does not support piping input.
+# Fortunately, it does not exhibit the problem GCC has with the cctools assembler.
+# This patch can be dropped should darwin.cctools-llvm ever implement support.
+++ optional (!atLeast7 && hostPlatform.isDarwin && lib.versionAtLeast (lib.getVersion stdenv.cc) "12") ./4.9/darwin-clang-as.patch
+
+
 ## gcc 4.9 and older ##############################################################################
 
 ++ optional (!atLeast6) ./parallel-bconfig.patch
diff --git a/pkgs/development/compilers/gcc/versions.nix b/pkgs/development/compilers/gcc/versions.nix
new file mode 100644
index 00000000000..261ffc63454
--- /dev/null
+++ b/pkgs/development/compilers/gcc/versions.nix
@@ -0,0 +1,38 @@
+let
+  majorMinorToVersionMap = {
+    "13" = "13.2.0";
+    "12" = "12.3.0";
+    "11" = "11.4.0";
+    "10" = "10.5.0";
+    "9"  =  "9.5.0";
+    "8"  =  "8.5.0";
+    "7"  =  "7.5.0";
+    "6"  =  "6.5.0";
+    "4.9"=  "4.9.4";
+    "4.8"=  "4.8.5";
+  };
+
+  fromMajorMinor = majorMinorVersion:
+    majorMinorToVersionMap."${majorMinorVersion}";
+
+  # TODO(amjoseph): convert older hashes to SRI form
+  srcHashForVersion = version: {
+    # NOTE: there is no need to remove hashes of obsolete minor
+    # versions when adding a new minor version.
+    "13.2.0" = "sha256-4nXnZEKmBnNBon8Exca4PYYTFEAEwEE1KIY9xrXHQ9o=";
+    "12.3.0" = "sha256-lJpdT5nnhkIak7Uysi/6tVeN5zITaZdbka7Jet/ajDs=";
+    "11.4.0" = "sha256-Py2yIrAH6KSiPNW6VnJu8I6LHx6yBV7nLBQCzqc6jdk=";
+    "10.5.0" = "sha256-JRCVQ/30bzl8NHtdi3osflaUpaUczkucbh6opxyjB8E=";
+    "9.5.0"  = "13ygjmd938m0wmy946pxdhz9i1wq7z4w10l6pvidak0xxxj9yxi7";
+    "8.5.0"  = "0l7d4m9jx124xsk6xardchgy2k5j5l2b15q322k31f0va4d8826k";
+    "7.5.0"  = "0qg6kqc5l72hpnj4vr6l0p69qav0rh4anlkk3y55540zy3klc6dq";
+    "6.5.0"  = "0i89fksfp6wr1xg9l8296aslcymv2idn60ip31wr9s4pwin7kwby";
+    "4.9.4"  = "14l06m7nvcvb0igkbip58x59w3nq6315k6jcz3wr9ch1rn9d44bc";
+    "4.8.5"  = "08yggr18v373a1ihj0rg2vd6psnic42b518xcgp3r9k81xz1xyr2";
+  }."${version}";
+
+in {
+  inherit fromMajorMinor;
+  inherit srcHashForVersion;
+  allMajorVersions = builtins.attrNames majorMinorToVersionMap;
+}