From 792a15b14b3381a5be59f9042c4636dfefc62c9a Mon Sep 17 00:00:00 2001 From: OPNA2608 Date: Fri, 2 Jan 2026 16:31:07 +0100 Subject: [PATCH] findutils: Fix gnulib test failure on ppc64 --- pkgs/tools/misc/findutils/default.nix | 9 +- ...loat-h-tests-port-to-C23-PowerPC-GCC.patch | 225 ++++++++++++++++++ 2 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 pkgs/tools/misc/findutils/gnulib-float-h-tests-port-to-C23-PowerPC-GCC.patch diff --git a/pkgs/tools/misc/findutils/default.nix b/pkgs/tools/misc/findutils/default.nix index 083c38138fdc..a5e8459355ac 100644 --- a/pkgs/tools/misc/findutils/default.nix +++ b/pkgs/tools/misc/findutils/default.nix @@ -24,7 +24,14 @@ stdenv.mkDerivation (finalAttrs: { substituteInPlace xargs/xargs.c --replace 'char default_cmd[] = "echo";' 'char default_cmd[] = "${coreutils}/bin/echo";' ''; - patches = [ ./no-install-statedir.patch ]; + patches = [ + ./no-install-statedir.patch + + # Fixes test-float failure on ppc64 with C23 + # https://lists.gnu.org/archive/html/bug-gnulib/2025-07/msg00021.html + # Multiple upstream commits squashed with adjustments, see header + ./gnulib-float-h-tests-port-to-C23-PowerPC-GCC.patch + ]; nativeBuildInputs = [ updateAutotoolsGnuConfigScriptsHook ]; buildInputs = [ coreutils ]; # bin/updatedb script needs to call sort diff --git a/pkgs/tools/misc/findutils/gnulib-float-h-tests-port-to-C23-PowerPC-GCC.patch b/pkgs/tools/misc/findutils/gnulib-float-h-tests-port-to-C23-PowerPC-GCC.patch new file mode 100644 index 000000000000..5eb610a1c2c6 --- /dev/null +++ b/pkgs/tools/misc/findutils/gnulib-float-h-tests-port-to-C23-PowerPC-GCC.patch @@ -0,0 +1,225 @@ +Applied the following incremental gnulib commits: + +- 55a366a06fbd98bf13adc531579e3513cee97a32 +- 65ed9d3b24ad09fd61d326c83e7f1b05f6e9d65f +- ce8e9de0bf34bc63dffc67ab384334c509175f64 +- 6164b4cb0887b5331a4e64449107decd37d32735 + +With adjustments specific to the structure & differences in findutils: + +- gnulib code is split across gl/lib and gnulib-tests +- float.in.h seems old, lacking blocks for standards C11 and up. Relevant code for LDBL_NORM_MAX was added. +- A Makefile.in is used for the test flags instead of the fancy automake modules + in the upstream gnulib project, so we add -lm to the float test there. + Surrounding texts in this file are slightly different in every project. +--- +diff '--color=auto' -ruN a/gl/lib/float.c b/gl/lib/float.c +--- a/gl/lib/float.c 2024-01-01 21:35:38.000000000 +0100 ++++ b/gl/lib/float.c 2026-01-02 16:11:07.508755119 +0100 +@@ -22,7 +22,7 @@ + + #if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ + const union gl_long_double_union gl_LDBL_MAX = +- { { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL } }; ++ { { DBL_MAX, DBL_MAX / 0x1p53 } }; + #elif defined __i386__ + const union gl_long_double_union gl_LDBL_MAX = + { { 0xFFFFFFFF, 0xFFFFFFFF, 32766 } }; +diff '--color=auto' -ruN a/gl/lib/float.in.h b/gl/lib/float.in.h +--- a/gl/lib/float.in.h 2024-01-01 21:35:38.000000000 +0100 ++++ b/gl/lib/float.in.h 2026-01-02 16:13:56.571684867 +0100 +@@ -111,44 +111,38 @@ + # define LDBL_MAX_10_EXP 4932 + #endif + +-/* On AIX 7.1 with gcc 4.2, the values of LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX are +- wrong. +- On Linux/PowerPC with gcc 4.4, the value of LDBL_MAX is wrong. */ +-#if (defined _ARCH_PPC || defined _POWER) && defined _AIX && (LDBL_MANT_DIG == 106) && defined __GNUC__ ++/* On PowerPC with gcc 15 when using __ibm128 long double, the value of ++ LDBL_MIN_EXP, LDBL_MIN, LDBL_MAX, and LDBL_NORM_MAX are wrong. */ ++#if ((defined _ARCH_PPC || defined _POWER) && LDBL_MANT_DIG == 106 \ ++ && defined __GNUC__) + # undef LDBL_MIN_EXP + # define LDBL_MIN_EXP DBL_MIN_EXP + # undef LDBL_MIN_10_EXP + # define LDBL_MIN_10_EXP DBL_MIN_10_EXP + # undef LDBL_MIN + # define LDBL_MIN 2.22507385850720138309023271733240406422e-308L /* DBL_MIN = 2^-1022 */ +-#endif +-#if (defined _ARCH_PPC || defined _POWER) && (defined _AIX || defined __linux__) && (LDBL_MANT_DIG == 106) && defined __GNUC__ + # undef LDBL_MAX +-/* LDBL_MAX is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xFFFFFFFF }. +- It is not easy to define: +- #define LDBL_MAX 1.79769313486231580793728971405302307166e308L +- is too small, whereas +- #define LDBL_MAX 1.79769313486231580793728971405302307167e308L +- is too large. Apparently a bug in GCC decimal-to-binary conversion. +- Also, I can't get values larger than +- #define LDBL63 ((long double) (1ULL << 63)) +- #define LDBL882 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) +- #define LDBL945 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) +- #define LDBL1008 (LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63 * LDBL63) +- #define LDBL_MAX (LDBL1008 * 65535.0L + LDBL945 * (long double) 9223372036821221375ULL + LDBL882 * (long double) 4611686018427387904ULL) +- which is represented as { 0x7FEFFFFF, 0xFFFFFFFF, 0x7C8FFFFF, 0xF8000000 }. +- So, define it like this through a reference to an external variable ++/* LDBL_MAX is 2**1024 - 2**918, represented as: { 0x7FEFFFFF, 0xFFFFFFFF, ++ 0x7C9FFFFF, 0xFFFFFFFF }. ++ ++ Do not write it as a constant expression, as GCC would likely treat ++ that as infinity due to the vagaries of this platform's funky arithmetic. ++ Instead, define it through a reference to an external variable. ++ Like the following, but using a union to avoid type mismatches: + +- const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }; ++ const double LDBL_MAX[2] = { DBL_MAX, DBL_MAX / 0x1p53 }; + extern const long double LDBL_MAX; + +- or through a pointer cast ++ The following alternative would not work as well when GCC is optimizing: ++ ++ #define LDBL_MAX (*(long double const *) (double[]) ++ { DBL_MAX, DBL_MAX / 0x1p53 }) + +- #define LDBL_MAX \ +- (*(const long double *) (double[]) { DBL_MAX, DBL_MAX / (double)134217728UL / (double)134217728UL }) ++ The following alternative would require GCC 6 or later: + +- Unfortunately, this is not a constant expression, and the latter expression +- does not work well when GCC is optimizing.. */ ++ #define LDBL_MAX __builtin_pack_longdouble (DBL_MAX, DBL_MAX / 0x1p53) ++ ++ Unfortunately none of the alternatives are constant expressions. */ + # if !GNULIB_defined_long_double_union + union gl_long_double_union + { +@@ -159,6 +153,8 @@ + # endif + extern const union gl_long_double_union gl_LDBL_MAX; + # define LDBL_MAX (gl_LDBL_MAX.ld) ++# undef LDBL_NORM_MAX ++# define LDBL_NORM_MAX LDBL_MAX + #endif + + /* On IRIX 6.5, with cc, the value of LDBL_MANT_DIG is wrong. +@@ -179,6 +175,35 @@ + # endif + #endif + ++/* On PowerPC platforms, 'long double' has a double-double representation. ++ Up to ISO C 17, this was outside the scope of ISO C because it can represent ++ numbers with mantissas of the form 1.<52 bits><52 bits>, such as ++ 1.0L + 4.94065645841246544176568792868221e-324L = 1 + 2^-1074; see ++ ISO C 17 § 5.2.4.2.2.(3). ++ In ISO C 23, wording has been included that makes this 'long double' ++ representation compliant; see ISO C 23 § 5.2.5.3.3.(8)-(9). In this setting, ++ numbers with mantissas of the form 1.<52 bits><52 bits> are ++ called "unnormalized". And since LDBL_EPSILON must be normalized (per ++ ISO C 23 § 5.2.5.3.3.(33)), it must be 2^-105. */ ++#if defined __powerpc__ && LDBL_MANT_DIG == 106 ++# undef LDBL_EPSILON ++# define LDBL_EPSILON 2.46519032881566189191165176650870696773e-32L /* 2^-105 */ ++#endif ++ ++/* ============================ ISO C23 support ============================ */ ++ ++/* 'long double' properties */ ++ ++#ifndef LDBL_NORM_MAX ++# ifdef __LDBL_NORM_MAX__ ++# define LDBL_NORM_MAX __LDBL_NORM_MAX__ ++# else ++# define LDBL_NORM_MAX LDBL_MAX ++# endif ++#endif ++ ++/* ================================= Other ================================= */ ++ + #if @REPLACE_ITOLD@ + /* Pull in a function that fixes the 'int' to 'long double' conversion + of glibc 2.7. */ +diff '--color=auto' -ruN a/gnulib-tests/Makefile.in b/gnulib-tests/Makefile.in +--- a/gnulib-tests/Makefile.in 2024-06-01 18:18:09.000000000 +0200 ++++ b/gnulib-tests/Makefile.in 2026-01-02 15:56:12.645625323 +0100 +@@ -1172,7 +1172,7 @@ + ../gl/lib/libgnulib.a libtests.a $(am__DEPENDENCIES_1) + test_float_SOURCES = test-float.c + test_float_OBJECTS = test-float.$(OBJEXT) +-test_float_LDADD = $(LDADD) ++test_float_LDADD = $(LDADD) -lm + test_float_DEPENDENCIES = libtests.a ../gl/lib/libgnulib.a libtests.a \ + ../gl/lib/libgnulib.a libtests.a $(am__DEPENDENCIES_1) + test_fnmatch_SOURCES = test-fnmatch.c +diff '--color=auto' -ruN a/gnulib-tests/test-float.c b/gnulib-tests/test-float.c +--- a/gnulib-tests/test-float.c 2024-05-27 21:48:37.000000000 +0200 ++++ b/gnulib-tests/test-float.c 2026-01-02 16:15:21.261123584 +0100 +@@ -59,6 +59,8 @@ + + /* ------------------------------------------------------------------------- */ + ++#include ++ + #include "fpucw.h" + #include "macros.h" + +@@ -295,6 +297,44 @@ + + /* -------------------- Check macros for 'long double' -------------------- */ + ++static int ++test_isfinitel (long double volatile x) ++{ ++ if (x != x) ++ return 0; ++ long double volatile zero = x * 0; ++ return zero == 0; ++} ++ ++/* Return X after normalization. This makes a difference on platforms ++ where long double can represent unnormalized values. For example, ++ suppose x = 1 + 2**-106 on PowerPC with IBM long double where ++ FLT_RADIX = 2, LDBL_MANT_DIG = 106, and LDBL_EPSILON = 2**-105. ++ Then 1 < x < 1 + LDBL_EPSILON, and normalize_long_double (x) returns 1. */ ++static long double ++normalize_long_double (long double volatile x) ++{ ++ if (FLT_RADIX == 2 && test_isfinitel (x)) ++ { ++ int xexp; ++ long double volatile ++ frac = frexpl (x, &xexp), ++ significand = frac * pow2l (LDBL_MANT_DIG), ++ normalized_significand = truncl (significand), ++ normalized_x = normalized_significand * pow2l (xexp - LDBL_MANT_DIG); ++ ++ /* The test_isfinitel defends against PowerPC with IBM long double, ++ which fritzes out near LDBL_MAX. */ ++ if (test_isfinitel (normalized_x)) ++ x = normalized_x; ++ } ++ else ++ { ++ /* Hope that X is already normalized. */ ++ } ++ return x; ++} ++ + static void + test_long_double (void) + { +@@ -354,11 +394,14 @@ + for (n = 0; n <= 2 * LDBL_MANT_DIG; n++) + { + volatile long double half_n = pow2l (- n); /* 2^-n */ +- volatile long double x = me - half_n; ++ volatile long double x = normalize_long_double (me - half_n); + if (x < me) + ASSERT (x <= 1.0L); + } + } ++ ++ /* Check the value of LDBL_NORM_MAX. */ ++ ASSERT (LDBL_NORM_MAX == normalize_long_double (LDBL_MAX)); + } + + int