about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdam Joseph <adam@westernsemico.com>2023-07-06 03:24:33 -0700
committerAdam Joseph <adam@westernsemico.com>2023-07-06 05:50:26 -0700
commit424952b7b4c515941fc6aaac597636ba56a348e2 (patch)
treef255a142df28a1c3bca4e4a30bd0bde2ad0b2b8a
parentd3185b8a568d81a4dab14f9e19a632fc857bd49f (diff)
gccWithoutTargetLibc: link libgcc_s.so using -mnewlib if isPower
Closes #244405

Also adds considerably more commenting to document what is going on.
-rw-r--r--pkgs/development/compilers/gcc/common/pre-configure.nix33
-rw-r--r--pkgs/test/cross/default.nix2
2 files changed, 30 insertions, 5 deletions
diff --git a/pkgs/development/compilers/gcc/common/pre-configure.nix b/pkgs/development/compilers/gcc/common/pre-configure.nix
index 2561246a66f9d..e386693b22c7a 100644
--- a/pkgs/development/compilers/gcc/common/pre-configure.nix
+++ b/pkgs/development/compilers/gcc/common/pre-configure.nix
@@ -117,10 +117,35 @@ in lib.optionalString (hostPlatform.isSunOS && hostPlatform.is64bit) ''
 #   https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/
 #   https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff
 + lib.optionalString (targetPlatform != hostPlatform && withoutTargetLibc && enableShared)
-  (lib.optionalString (!stdenv.targetPlatform.isPower) ''
-    echo 'libgcc.a: crti.o crtn.o' >> libgcc/Makefile.in
-  '' + ''
-    echo 'SHLIB_LC=' >> libgcc/Makefile.in
+  (let
+
+    # crt{i,n}.o are the first and last (respectively) object file
+    # linked when producing an executable.  Traditionally these
+    # files are delivered as part of the C library, but on GNU
+    # systems they are in fact built by GCC.  Since libgcc needs to
+    # build before glibc, we can't wait for them to be copied by
+    # glibc.  At this early pre-glibc stage these files sometimes
+    # have different names.
+    crtstuff-ofiles =
+      if targetPlatform.isPower
+      then "ecrti.o ecrtn.o ncrti.o ncrtn.o"
+      else "crti.o crtn.o";
+
+    # Normally, `SHLIB_LC` is set to `-lc`, which means that
+    # `libgcc_s.so` cannot be built until `libc.so` is available.
+    # The assignment below clobbers this variable, removing the
+    # `-lc`.
+    #
+    # On PowerPC we add `-mnewlib`, which means "libc has not been
+    # built yet".  This causes libgcc's Makefile to use the
+    # gcc-built `{e,n}crt{n,i}.o` instead of failing to find the
+    # versions which have been repackaged in libc as `crt{n,i}.o`
+    #
+    SHLIB_LC = lib.optionalString targetPlatform.isPower "-mnewlib";
+
+  in ''
+    echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in
+    echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in
   '')
 
 + lib.optionalString (!enableMultilib && hostPlatform.is64bit && !hostPlatform.isMips64n32) ''
diff --git a/pkgs/test/cross/default.nix b/pkgs/test/cross/default.nix
index ad2689d5d2174..46bb3c8d522d2 100644
--- a/pkgs/test/cross/default.nix
+++ b/pkgs/test/cross/default.nix
@@ -136,7 +136,7 @@ let
     pkgs.pkgsCross.arm-embedded.stdenv
     pkgs.pkgsCross.m68k.stdenv
     pkgs.pkgsCross.aarch64-multiplatform.pkgsBuildTarget.gcc
-    #pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc
+    pkgs.pkgsCross.powernv.pkgsBuildTarget.gcc
     pkgs.pkgsCross.mips64el-linux-gnuabi64.stdenv
     pkgs.pkgsCross.mips64el-linux-gnuabin32.stdenv
     pkgs.pkgsCross.mingwW64.stdenv