From c527af15278e857ffee819892e95076cd0976093 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 19 Apr 2022 17:00:36 -0700 Subject: [PATCH 1/7] stdenv: force gmp to rebuild in stage4 of the bootstrap As explained in the comment, this ensures that stage4-coreutils does not leak a reference to the bootstrap-files by way of libgmp. This will allow the next patch in this series to build stage4-coreutils using a dynamically-linked (rather than statically-linked) libgmp. --- pkgs/stdenv/linux/default.nix | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index e9104dd88cfa1..6126f742a5140 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -332,7 +332,7 @@ in # because gcc (since JAR support) already depends on zlib, and # then if we already have a zlib we want to use that for the # other purposes (binutils and top-level pkgs) too. - inherit (prevStage) gettext gnum4 bison gmp perl texinfo zlib linuxHeaders libidn2 libunistring; + inherit (prevStage) gettext gnum4 bison perl texinfo zlib linuxHeaders libidn2 libunistring; ${localSystem.libc} = getLibc prevStage; binutils = super.binutils.override { # Don't use stdenv's shell but our own @@ -343,6 +343,11 @@ in }; }; + # force gmp to rebuild so we have the option of dynamically linking + # libgmp without creating a reference path from: + # stage5.gcc -> stage4.coreutils -> stage3.glibc -> bootstrap + gmp = super.gmp.override { stdenv = self.stdenv; }; + gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; nativeLibc = false; @@ -410,7 +415,7 @@ in # Simple executable tools concatMap (p: [ (getBin p) (getLib p) ]) [ gzip bzip2 xz bash binutils.bintools coreutils diffutils findutils - gawk gnumake gnused gnutar gnugrep gnupatch patchelf ed + gawk gmp gnumake gnused gnutar gnugrep gnupatch patchelf ed ] # Library dependencies ++ map getLib ( From cad68ef2d57dfa7b11886a0254cccec310d3fdee Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 19 Apr 2022 16:07:01 -0700 Subject: [PATCH 2/7] stdenv: cause makeStaticLibraries usage to agree with usage spec The usage of `makeStaticLibraries` in stdenv/linux/default.nix is prefaced by this comment: # Link GCC statically against GMP etc. This makes sense because # these builds of the libraries are only used by GCC, so it # reduces the size of the stdenv closure. However "these builds of the libraries are only used by GCC" is not actually true. As currently written, the stage4 coreutils links against these customized, static-ified libraries. Beside the fact that the code doesn't actually do what it says, this causes other problems as well. One example is #168983, which arises because have a dynamically-linked binary (coreutils) which is built from statically-linked libraries (libgmp.a); doing this causes mayhem on platforms where `-fstack-protector` needs an auxiliary `libssp.{so,a}` library; we end up with link failures because some parts of the resulting binary want `libssp.so` and other parts want `libssp_nonshared.a`. Let's make the code actually do what the comment says, by moving these definitions into the `gcc-unwrapped` override. This will cause the stage4-coreutils to link against libgmp dynamically, rather than statically. For this reason this commit depends on the previous commit, which allows that to be done without creating a forbidden reference from stdenv-final to the bootstrap-files. --- pkgs/stdenv/linux/default.nix | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 6126f742a5140..41942aa70b39a 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -300,15 +300,14 @@ in binutils coreutils gnugrep perl patchelf linuxHeaders gnum4 bison libidn2 libunistring; ${localSystem.libc} = getLibc prevStage; - # Link GCC statically against GMP etc. This makes sense because - # these builds of the libraries are only used by GCC, so it - # reduces the size of the stdenv closure. - gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; }; - mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; }; - libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; }; - isl_0_20 = super.isl_0_20.override { stdenv = self.makeStaticLibraries self.stdenv; }; gcc-unwrapped = super.gcc-unwrapped.override { - isl = isl_0_20; + # Link GCC statically against GMP etc. This makes sense because + # these builds of the libraries are only used by GCC, so it + # reduces the size of the stdenv closure. + gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; }; + mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; }; + libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; }; + isl = super.isl_0_20.override { stdenv = self.makeStaticLibraries self.stdenv; }; # Use a deterministically built compiler # see https://github.com/NixOS/nixpkgs/issues/108475 for context reproducibleBuild = true; From 9dd7908c8f0b548688a183e5e95438b89fc1d219 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 19 Apr 2022 17:04:58 -0700 Subject: [PATCH 3/7] stdenv: label the ephemeral coreutils-stage4 package During stdenv bootstrapping, coreutils is built twice. This makes troubleshooting very difficult, because both packages have name="coreutils", so it is a hassle to figure out "which coreutils am I using / is not building"? The first of these builds is used only in stage4, and is not part of the final stdenv. Let's label that one with a different `name` attribute to make it obvious which is which. --- pkgs/stdenv/linux/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 41942aa70b39a..9c1114c22cc9d 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -347,6 +347,9 @@ in # stage5.gcc -> stage4.coreutils -> stage3.glibc -> bootstrap gmp = super.gmp.override { stdenv = self.stdenv; }; + # coreutils gets rebuilt both here and also in the final stage; we rename this one to avoid confusion + coreutils = super.coreutils.overrideAttrs (a: a // { name = "coreutils-stage4"; }); + gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; nativeLibc = false; From 502d9022e0c7f00a29496e7a0da48621b9f27510 Mon Sep 17 00:00:00 2001 From: Adam Joseph <54836058+a-m-joseph@users.noreply.github.com> Date: Wed, 20 Apr 2022 22:45:14 +0000 Subject: [PATCH 4/7] Update pkgs/stdenv/linux/default.nix Co-authored-by: sternenseemann --- pkgs/stdenv/linux/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 9c1114c22cc9d..972fff783a514 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -348,7 +348,7 @@ in gmp = super.gmp.override { stdenv = self.stdenv; }; # coreutils gets rebuilt both here and also in the final stage; we rename this one to avoid confusion - coreutils = super.coreutils.overrideAttrs (a: a // { name = "coreutils-stage4"; }); + coreutils = super.coreutils.overrideAttrs (_: { pname = "coreutils-stage4"; }); gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; From 5d2aa78bb6d8b9e705433afa13a3d78c3594d432 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Wed, 27 Apr 2022 00:27:19 -0700 Subject: [PATCH 5/7] stdenv: add -stageX markers to gmp, mpfr, libmpc, and isl --- pkgs/stdenv/linux/default.nix | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 972fff783a514..2d47e35b4ba24 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -300,14 +300,18 @@ in binutils coreutils gnugrep perl patchelf linuxHeaders gnum4 bison libidn2 libunistring; ${localSystem.libc} = getLibc prevStage; - gcc-unwrapped = super.gcc-unwrapped.override { + gcc-unwrapped = + let makeStaticLibrariesAndMark = pkg: + lib.makeOverridable (pkg.override { stdenv = self.makeStaticLibraries self.stdenv; }) + .overrideAttrs (a: { pname = "${a.pname}-stage3"; }); + in super.gcc-unwrapped.override { # Link GCC statically against GMP etc. This makes sense because # these builds of the libraries are only used by GCC, so it # reduces the size of the stdenv closure. - gmp = super.gmp.override { stdenv = self.makeStaticLibraries self.stdenv; }; - mpfr = super.mpfr.override { stdenv = self.makeStaticLibraries self.stdenv; }; - libmpc = super.libmpc.override { stdenv = self.makeStaticLibraries self.stdenv; }; - isl = super.isl_0_20.override { stdenv = self.makeStaticLibraries self.stdenv; }; + gmp = makeStaticLibrariesAndMark super.gmp; + mpfr = makeStaticLibrariesAndMark super.mpfr; + libmpc = makeStaticLibrariesAndMark super.libmpc; + isl = makeStaticLibrariesAndMark super.isl_0_20; # Use a deterministically built compiler # see https://github.com/NixOS/nixpkgs/issues/108475 for context reproducibleBuild = true; @@ -345,10 +349,10 @@ in # force gmp to rebuild so we have the option of dynamically linking # libgmp without creating a reference path from: # stage5.gcc -> stage4.coreutils -> stage3.glibc -> bootstrap - gmp = super.gmp.override { stdenv = self.stdenv; }; + gmp = lib.makeOverridable (super.gmp.override { stdenv = self.stdenv; }).overrideAttrs (a: { pname = "${a.pname}-stage4"; }); # coreutils gets rebuilt both here and also in the final stage; we rename this one to avoid confusion - coreutils = super.coreutils.overrideAttrs (_: { pname = "coreutils-stage4"; }); + coreutils = super.coreutils.overrideAttrs (a: { pname = "${a.pname}-stage4"; }); gcc = lib.makeOverridable (import ../../build-support/cc-wrapper) { nativeTools = false; From fde903a3afb8063f2f858680bfd1dcef6c76170b Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Tue, 26 Apr 2022 02:59:47 -0700 Subject: [PATCH 6/7] gcc: backport cda41ce0 from gcc 11.1.0 if isPower64 && isMusl A bug in libgcc which manifests when building static binaries using musl-libc was fixed in gcc 11.1.0, but the fix has not been backported to gcc 10. This commit cherry-picks the commit from upstream and applies it in the case (isPower64 && isMusl) where it matters: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=cda41ce0e8414aec59e6b9fbe645d96e6e8193e2 --- .../gcc/10/backport-libgcc-fix-PR97653.patch | 75 +++++++++++++++++++ pkgs/development/compilers/gcc/10/default.nix | 1 + 2 files changed, 76 insertions(+) create mode 100644 pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch diff --git a/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch b/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch new file mode 100644 index 0000000000000..ee0318eecf0a0 --- /dev/null +++ b/pkgs/development/compilers/gcc/10/backport-libgcc-fix-PR97653.patch @@ -0,0 +1,75 @@ +This patch is included upstream in gcc 11.1.0 and later: + + https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=cda41ce0e8414aec59e6b9fbe645d96e6e8193e2 + +From cda41ce0e8414aec59e6b9fbe645d96e6e8193e2 Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Sat, 3 Apr 2021 10:05:32 +0200 +Subject: [PATCH] rs6000: Fix up libgcc ABI when built with + --with-long-double-format=ieee [PR97653] + +__floatunditf and __fixtfdi and a couple of other libgcc{.a,_s.so} +entrypoints for backwards compatibility should mean IBM double double +handling (i.e. IFmode), gcc emits such calls for that format and +form IEEE long double emits *kf* instead. +When gcc is configured without --with-long-double-format=ieee , +everything is fine, but when it is not, we need to compile those +libgcc sources with -mno-gnu-attribute -mabi=ibmlongdouble. +The following snippet in libgcc/config/rs6000/t-linux was attempting +to ensure that, and for some routines it works fine (e.g. for _powitf2). +But, due to 4 different types of bugs it doesn't work for most of those +functions, which means that in --with-long-double-format=ieee +configured gcc those *tf* entrypoints instead handle the long double +arguments as if they were KFmode. + +The bugs are: +1) the first few objs properly use $(objext) as suffix, but + several other contain a typo and use $(object) instead, + which is a variable that isn't set to anything, so we don't + add .o etc. extensions +2) while unsigned fix are properly called _fixuns*, unsigned float + are called _floatun* (without s), but the var was using there + the extra s and so didn't match +3) the variable didn't cover any of the TF <-> TI conversions, + only TF <-> DI conversions +4) nothing in libgcc_s.so was handled, as those object files are + called *_s.o rather than *.o and IBM128_SHARED_OBJS used wrong + syntax of the GNU make substitution reference, which should be + $(var:a=b) standing for $(patsubst a,b,$(var)) but it used + $(var:a:b) instead + +2021-04-03 Jakub Jelinek + + PR target/97653 + * config/rs6000/t-linux (IBM128_STATIC_OBJS): Fix spelling, use + $(objext) instead of $(object). Use _floatunditf instead of + _floatunsditf. Add tf <-> ti conversion objects. + (IBM128_SHARED_OBJS): Use proper substitution reference syntax. +--- + libgcc/config/rs6000/t-linux | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/libgcc/config/rs6000/t-linux b/libgcc/config/rs6000/t-linux +index 72e9c2770a6..500210ddaf2 100644 +--- a/libgcc/config/rs6000/t-linux ++++ b/libgcc/config/rs6000/t-linux +@@ -11,10 +11,12 @@ HOST_LIBGCC2_CFLAGS += -mno-minimal-toc + # the IBM extended double format. Also turn off gnu attributes on the static + # modules. + IBM128_STATIC_OBJS = ibm-ldouble$(objext) _powitf2$(objext) \ +- ppc64-fp$(objext) _divtc3$(object) _multc3$(object) \ +- _fixtfdi$(object) _fixunstfdi$(object) \ +- _floatditf$(objext) _floatunsditf$(objext) +-IBM128_SHARED_OBJS = $(IBM128_STATIC_OBJS:$(objext):_s$(objext)) ++ ppc64-fp$(objext) _divtc3$(objext) _multc3$(objext) \ ++ _fixtfdi$(objext) _fixunstfdi$(objext) \ ++ _floatditf$(objext) _floatunditf$(objext) \ ++ _fixtfti$(objext) _fixunstfti$(objext) \ ++ _floattitf$(objext) _floatuntitf$(objext) ++IBM128_SHARED_OBJS = $(IBM128_STATIC_OBJS:$(objext)=_s$(objext)) + IBM128_OBJS = $(IBM128_STATIC_OBJS) $(IBM128_SHARED_OBJS) + + IBM128_CFLAGS = -Wno-psabi -mabi=ibmlongdouble -mno-gnu-attribute +-- +2.27.0 + diff --git a/pkgs/development/compilers/gcc/10/default.nix b/pkgs/development/compilers/gcc/10/default.nix index 1e8917ef6cf16..d12e0f216d445 100644 --- a/pkgs/development/compilers/gcc/10/default.nix +++ b/pkgs/development/compilers/gcc/10/default.nix @@ -67,6 +67,7 @@ let majorVersion = "10"; ++ optional langAda ../gnat-cflags.patch ++ optional langFortran ../gfortran-driving.patch ++ optional (targetPlatform.libc == "musl" && targetPlatform.isPower) ../ppc-musl.patch + ++ optional (targetPlatform.isMusl && targetPlatform.isPower64) ./backport-libgcc-fix-PR97653.patch # Obtain latest patch with ../update-mcfgthread-patches.sh ++ optional (!crossStageStatic && targetPlatform.isMinGW) ./Added-mcf-thread-model-support-from-mcfgthread.patch From 14af95e466dfd84676724a17ce4ba4d693fee7f5 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Wed, 27 Apr 2022 14:24:26 -0700 Subject: [PATCH 7/7] gcc: if isPower64, add --with-long-double-64 --without-long-double-128 This commit causes powerpc*-*-gnu to be configured with 64-bit IEEE-compliant `long double` (the same as ordinary `double`) rather than the nonstandard, non-IEEE "IBM double" format from AIX. Support for using only IEEE 128-bit doubles in glibc is not yet ready. This resolves several package test failures caused by weird nonstandard floating-point semantics. It also eliminates a lot of difficulties that arise when using glibc-linked tools to compile for musl-libc and vice versa. There is a long comment included in gcc/common/platform-flags.nix explaining the situation and the reasoning. --- .../compilers/gcc/common/platform-flags.nix | 46 +++++++++++++++++-- pkgs/stdenv/adapters.nix | 5 ++ pkgs/stdenv/linux/default.nix | 10 +++- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/pkgs/development/compilers/gcc/common/platform-flags.nix b/pkgs/development/compilers/gcc/common/platform-flags.nix index bd5a72f960364..f53457325204b 100644 --- a/pkgs/development/compilers/gcc/common/platform-flags.nix +++ b/pkgs/development/compilers/gcc/common/platform-flags.nix @@ -10,7 +10,47 @@ in lib.concatLists [ (lib.optional (p ? fpu) "--with-fpu=${p.fpu}") (lib.optional (p ? float) "--with-float=${p.float}") (lib.optional (p ? mode) "--with-mode=${p.mode}") - (lib.optional - (let tp = targetPlatform; in tp.isPower && tp.libc == "glibc" && tp.is64bit) - "--with-long-double-128") + + # The powerpc64 ABI has an IBM-specific, non-IEEE "long double" type + # which causes many some test failures. GCC and glibc have been + # working on migrating to 128-bit IEEE long doubles using a complex + # "fat binary" scheme that avoids having a new multiarch tuple. + # Progress with this scheme has been exceptionally slow: Fedora has + # been trying to "flip the switch" since Fedora 31 without success. + # + # As of version 2.34 glibc refuses to build using *only* the IEEE + # standard long-double type, and implementation of the "fat binary" + # scheme to support both IEEE and IBM long doubles simultaneously is + # troublesome and unreliable. Therefore, we use the same approach + # with glibc that musl uses: simply have `long double` be the same + # size as `double`: 64 bits. This is already the case on + # aarch64-darwin, 32-bit ARM, 32-bit MIPS, and Microsoft's C/C++ + # compiler for both 64-bit ARM and 32-bit x86, so it is + # well-supported by the build scripts for essentially everything in + # nixpkgs. + # + # Musl specifically checks for non-IEEE `long double`s on powerpc + # and will refuse to build if they are found to be present: + # + # https://git.musl-libc.org/cgit/musl/tree/configure#n732 + # + # This has saved musl as great deal of trouble that glibc is + # currently struggling with. By using the same approach for both + # musl and glibc we avoid a lot of headaches that come up when + # "cross-compiling" from *-linux-gnu to *-linux-musl due to the + # libgcc bundled into *-linux-gnu's being linked with the emitted + # binaries. + # + # More details: + # + # https://gcc.gnu.org/wiki/Ieee128PowerPC + # https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html + # https://fedoraproject.org/wiki/Changes/PPC64LE_Float128_Transition + # https://en.m.wikipedia.org/wiki/Long_double + # https://gcc.gnu.org/install/configure.html + # + # Below are the three possible valid combinations of options, with + # two commented out: + # + (lib.optionals targetPlatform.isPower64 [ "--without-long-double-128" "--with-long-double-64" ]) ] diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix index 9884c219ff609..62652b3183b97 100644 --- a/pkgs/stdenv/adapters.nix +++ b/pkgs/stdenv/adapters.nix @@ -87,6 +87,11 @@ rec { ]; cmakeFlags = (args.cmakeFlags or []) ++ [ "-DBUILD_SHARED_LIBS:BOOL=OFF" ]; mesonFlags = (args.mesonFlags or []) ++ [ "-Ddefault_library=static" ]; + } // lib.optionalAttrs stdenv.hostPlatform.isPower64 { + # this is an artifact of the bootstrap-files being built prior + # to moving to IEEE doubles on powerpc64le; it would go away + # if we regenerated the bootstrap-files + hardeningDisable = (args.hardeningDisable or []) ++ [ "stackprotector" ]; }); }); diff --git a/pkgs/stdenv/linux/default.nix b/pkgs/stdenv/linux/default.nix index 2d47e35b4ba24..bd87d264269fd 100644 --- a/pkgs/stdenv/linux/default.nix +++ b/pkgs/stdenv/linux/default.nix @@ -303,14 +303,20 @@ in gcc-unwrapped = let makeStaticLibrariesAndMark = pkg: lib.makeOverridable (pkg.override { stdenv = self.makeStaticLibraries self.stdenv; }) - .overrideAttrs (a: { pname = "${a.pname}-stage3"; }); + .overrideAttrs (a: { + # this is an artifact of the bootstrap-files being built prior + # to moving to IEEE doubles on powerpc64le; it would go away + # if we regenerated the bootstrap-files + NIX_CFLAGS_COMPILE = (a.NIX_CFLAGS_COMPILE or "") + " -mlong-double-64"; + pname = "${a.pname}-stage3"; + }); in super.gcc-unwrapped.override { # Link GCC statically against GMP etc. This makes sense because # these builds of the libraries are only used by GCC, so it # reduces the size of the stdenv closure. gmp = makeStaticLibrariesAndMark super.gmp; mpfr = makeStaticLibrariesAndMark super.mpfr; - libmpc = makeStaticLibrariesAndMark super.libmpc; + libmpc = lib.makeOverridable (makeStaticLibrariesAndMark super.libmpc).overrideAttrs (_: { doCheck = false; }); isl = makeStaticLibrariesAndMark super.isl_0_20; # Use a deterministically built compiler # see https://github.com/NixOS/nixpkgs/issues/108475 for context