Repository: bitcoin/bitcoin (language: cpp)

Issue:
guix: migrate to native GCC 10 toolchain for Linux builds
Currently, our Linux Guix builds differ from macOS and Windows, in that they use a native [GCC 7 toolchain](https://github.com/bitcoin/bitcoin/blob/2a3e8fb3592e42300ec96c9f6724e15346e30ea7/contrib/guix/manifest.scm#L150) (i.e to build glibc) and then GCC 10 to build depends and Bitcoin Core. Migrating the Linux builds to a native GCC 10 toolchain will unify us on a single native compiler.

The main issue with performing this migration is building older glibcs (2.24, 2.27) with GCC 10. When I last tried, it was apparent that either warnings produced by the newer GCC would need to be suppressed (as glibc is built -Werror), or patches to glibc would need to be backported to address any issues. For example:
```bash
x86_64-linux-gnu-gcc ../sysdeps/unix/sysv/linux/x86_64/sysdep.S -c     -I../include -I/tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/csu  -I/tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build  -I../sysdeps/unix/sysv/linux/x86_64/64  -I../sysdeps/unix/sysv/linux/x86_64  -I../sysdeps/unix/sysv/linux/x86  -I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/x86_64/nptl  -I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread  -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv  -I../sysdeps/unix/x86_64  -I../sysdeps/unix  -I../sysdeps/posix  -I../sysdeps/x86_64/64  -I../sysdeps/x86_64/fpu/multiarch  -I../sysdeps/x86_64/fpu  -I../sysdeps/x86/fpu/include -I../sysdeps/x86/fpu  -I../sysdeps/x86_64/multiarch  -I../sysdeps/x86_64  -I../sysdeps/x86  -I../sysdeps/ieee754/ldbl-96  -I../sysdeps/ieee754/dbl-64/wordsize-64  -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32  -I../sysdeps/wordsize-64  -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I. -nostdinc -isystem /gnu/store/r2h1g2vg7j36rqwyraf5wghm10ykq055-gcc-cross-sans-libc-x86_64-linux-gnu-10.3.0-lib/lib/gcc/x86_64-linux-gnu/10.3.0/include -isystem /gnu/store/r2h1g2vg7j36rqwyraf5wghm10ykq055-gcc-cross-sans-libc-x86_64-linux-gnu-10.3.0-lib/lib/gcc/x86_64-linux-gnu/10.3.0/include-fixed -isystem /gnu/store/5fhhr33nilcyi1k3s1xwcmibdhc1l39c-linux-libre-headers-cross-x86_64-linux-gnu-4.9.306/include -D_LIBC_REENTRANT -include /tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/libc-modules.h -DMODULE_NAME=libc -include ../include/libc-symbols.h  -DPIC -DSHARED     -DASSEMBLER -I/tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/csu/. -g -Werror=undef -Wa,--noexecstack   -o /tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/csu/sysdep.os -MD -MP -MF /tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/csu/sysdep.os.dt -MT /tmp/guix-build-glibc-cross-x86_64-linux-gnu-2.24.drv-0/build/csu/sysdep.os
libc-tls.c: In function ‘__libc_setup_tls’:
libc-tls.c:208:30: error: array subscript 1 is outside the bounds of an interior zero-length array ‘struct dtv_slotinfo[0]’ [-Werror=zero-length-bounds]
  208 |   static_slotinfo.si.slotinfo[1].map = main_map;
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
In file included from ../sysdeps/x86_64/ldsodefs.h:54,
                 from ../sysdeps/gnu/ldsodefs.h:46,
                 from ../sysdeps/unix/sysv/linux/ldsodefs.h:25,
                 from libc-tls.c:20:
../sysdeps/generic/ldsodefs.h:398:7: note: while referencing ‘slotinfo’
  398 |     } slotinfo[0];
      |       ^~~~~~~~
cc1: all warnings being treated as errors
```

This branch could be used as a starting point: https://github.com/fanquake/bitcoin/tree/native_gcc_10_linux (3974ac565ad575d8d4216bcac39b46a6dcd254d5). Builds for `x86_64-w64-mingw32 x86_64-apple-darwin x86_64-apple-darwin` will all work as expected. A Linux build, i.e `HOSTS="x86_64-linux-gnu" ./contrib/guix/guix-build` will not, and will fail with the error displayed above.

#### Useful skills:

* Guix
* Build system

#### Want to work on this issue?

For guidance on contributing, please read [CONTRIBUTING.md](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md) before opening your pull request.



Discussion / hints:
> HOSTS="x86_64-pc-linux-gnu"

Probably off-topic but related: Which one is (more) correct? `x86_64-pc-linux-gnu` or `x86_64-linux-gnu`. It seems we are using both?

```
❯ rg x86_64-pc-linux-gnu | wc -l
       4
❯ rg x86_64-linux-gnu | wc -l   
      25
```
Yea, that was just a copy-paste mistake, which I've amended. Both are fine how we are currently using them in our codebase.
On the one hand:
```sh
$ build-aux/config.guess 
x86_64-pc-linux-gnu
```

On the other hand, cross-compiling tools are prefixed with `x86_64-linux-gnu-`.
> Probably off-topic but related: Which one is (more) correct? x86_64-pc-linux-gnu or x86_64-linux-gnu. It seems we are using both?

I would guess they are 100% equivalent. The `-pc-` (sometimes) or `-unknown-` (othertimes) is the "manufacturer" part of the architecture tuple. It's an optional, basically freeform field that everyone ignores.

Personally I have a slight preference for leaving it out.

Fix patch:
diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm
index b61c2b8899290..34a9c608db2bd 100644
--- a/contrib/guix/manifest.scm
+++ b/contrib/guix/manifest.scm
@@ -148,9 +148,9 @@ chain for " target " development."))
 
 (define* (make-bitcoin-cross-toolchain target
                                        #:key
-                                       (base-gcc-for-libc gcc-7)
+                                       (base-gcc-for-libc base-gcc)
                                        (base-kernel-headers base-linux-kernel-headers)
-                                       (base-libc (make-glibc-without-ssp glibc-2.24))
+                                       (base-libc (make-glibc-without-ssp (make-glibc-without-werror glibc-2.24)))
                                        (base-gcc (make-gcc-rpath-link base-gcc)))
   "Convenience wrapper around MAKE-CROSS-TOOLCHAIN with default values
 desirable for building Bitcoin Core release binaries."
@@ -518,6 +518,9 @@ and endian independent.")
 inspecting signatures in Mach-O binaries.")
       (license license:expat))))
 
+(define (make-glibc-without-werror glibc)
+  (package-with-extra-configure-variable glibc "enable_werror" "no"))
+
 (define-public glibc-2.24
   (package
     (inherit glibc-2.31)
@@ -534,7 +537,8 @@ inspecting signatures in Mach-O binaries.")
               (patches (search-our-patches "glibc-ldd-x86_64.patch"
                                            "glibc-versioned-locpath.patch"
                                            "glibc-2.24-elfm-loadaddr-dynamic-rewrite.patch"
-                                           "glibc-2.24-no-build-time-cxx-header-run.patch"))))))
+                                           "glibc-2.24-no-build-time-cxx-header-run.patch"
+                                           "glibc-2.24-fcommon.patch"))))))
 
 (define-public glibc-2.27/bitcoin-patched
   (package
@@ -550,7 +554,8 @@ inspecting signatures in Mach-O binaries.")
                (base32
                 "1b2n1gxv9f4fd5yy68qjbnarhf8mf4vmlxk10i3328c1w5pmp0ca"))
               (patches (search-our-patches "glibc-ldd-x86_64.patch"
-                                           "glibc-2.27-riscv64-Use-__has_include__-to-include-asm-syscalls.h.patch"))))))
+                                           "glibc-2.27-riscv64-Use-__has_include-to-include-asm-syscalls.h.patch"
+                                           "glibc-2.27-dont-redefine-nss-database.patch"))))))
 
 (packages->manifest
  (append
@@ -581,6 +586,9 @@ inspecting signatures in Mach-O binaries.")
         automake
         pkg-config
         bison
+        ;; Native GCC 10 toolchain
+        gcc-toolchain-10
+        (list gcc-toolchain-10 "static")
         ;; Scripting
         perl
         python-3
@@ -591,26 +599,17 @@ inspecting signatures in Mach-O binaries.")
   (let ((target (getenv "HOST")))
     (cond ((string-suffix? "-mingw32" target)
            ;; Windows
-           (list ;; Native GCC 10 toolchain
-                 gcc-toolchain-10
-                 (list gcc-toolchain-10 "static")
-                 zip
+           (list zip
                  (make-mingw-pthreads-cross-toolchain "x86_64-w64-mingw32")
                  (make-nsis-for-gcc-10 nsis-x86_64)
                  osslsigncode))
           ((string-contains target "-linux-")
-           (list ;; Native GCC 7 toolchain
-                 gcc-toolchain-7
-                 (list gcc-toolchain-7 "static")
-                 (cond ((string-contains target "riscv64-")
+           (list (cond ((string-contains target "riscv64-")
                         (make-bitcoin-cross-toolchain target
-                                                      #:base-libc glibc-2.27/bitcoin-patched
+                                                      #:base-libc (make-glibc-without-werror glibc-2.27/bitcoin-patched)
                                                       #:base-kernel-headers base-linux-kernel-headers))
                        (else
                         (make-bitcoin-cross-toolchain target)))))
           ((string-contains target "darwin")
-           (list ;; Native GCC 10 toolchain
-                 gcc-toolchain-10
-                 (list gcc-toolchain-10 "static")
-                 clang-toolchain-10 binutils cmake xorriso python-signapple))
+           (list clang-toolchain-10 binutils cmake xorriso python-signapple))
           (else '())))))
diff --git a/contrib/guix/patches/glibc-2.24-fcommon.patch b/contrib/guix/patches/glibc-2.24-fcommon.patch
new file mode 100644
index 0000000000000..2bc32ede90560
--- /dev/null
+++ b/contrib/guix/patches/glibc-2.24-fcommon.patch
@@ -0,0 +1,32 @@
+commit 264a4a0dbe1f4369db315080034b500bed66016c
+Author: fanquake <fanquake@gmail.com>
+Date:   Fri May 6 11:03:04 2022 +0100
+
+    build: use -fcommon to retain legacy behaviour with GCC 10
+    
+    GCC 10 started using -fno-common by default, which causes issues with
+    the powerpc builds using gibc 2.24. A patch was commited to glibc to fix
+    the issue, 18363b4f010da9ba459b13310b113ac0647c2fcc but is non-trvial
+    to backport, and was broken in at least one way, see the followup in
+    commit 7650321ce037302bfc2f026aa19e0213b8d02fe6.
+    
+    For now, retain the legacy GCC behaviour by passing -fcommon when
+    building glibc.
+    
+    https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html.
+    https://sourceware.org/git/?p=glibc.git;a=commit;h=18363b4f010da9ba459b13310b113ac0647c2fcc
+    https://sourceware.org/git/?p=glibc.git;a=commit;h=7650321ce037302bfc2f026aa19e0213b8d02fe6
+
+diff --git a/Makeconfig b/Makeconfig
+index ee379f5852..63c4a2f234 100644
+--- a/Makeconfig
++++ b/Makeconfig
+@@ -824,7 +824,7 @@ ifeq	"$(strip $(+cflags))" ""
+ +cflags	:= $(default_cflags)
+ endif	# $(+cflags) == ""
+ 
+-+cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags)
+++cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags) -fcommon
+ +gcc-nowarn := -w
+ 
+ # Don't duplicate options if we inherited variables from the parent.
diff --git a/contrib/guix/patches/glibc-2.27-dont-redefine-nss-database.patch b/contrib/guix/patches/glibc-2.27-dont-redefine-nss-database.patch
new file mode 100644
index 0000000000000..16a595d613c11
--- /dev/null
+++ b/contrib/guix/patches/glibc-2.27-dont-redefine-nss-database.patch
@@ -0,0 +1,87 @@
+commit 78a90c2f74a2012dd3eff302189e47ff6779a757
+Author: Andreas Schwab <schwab@linux-m68k.org>
+Date:   Fri Mar 2 23:07:14 2018 +0100
+
+    Fix multiple definitions of __nss_*_database (bug 22918)
+    
+    (cherry picked from commit eaf6753f8aac33a36deb98c1031d1bad7b593d2d)
+
+diff --git a/nscd/gai.c b/nscd/gai.c
+index d081747797..576fd0045b 100644
+--- a/nscd/gai.c
++++ b/nscd/gai.c
+@@ -45,3 +45,6 @@
+ #ifdef HAVE_LIBIDN
+ # include <libidn/idn-stub.c>
+ #endif
++
++/* Some variables normally defined in libc.  */
++service_user *__nss_hosts_database attribute_hidden;
+diff --git a/nss/nsswitch.c b/nss/nsswitch.c
+index d5e655974f..b0f0c11a3e 100644
+--- a/nss/nsswitch.c
++++ b/nss/nsswitch.c
+@@ -62,7 +62,7 @@ static service_library *nss_new_service (name_database *database,
+ 
+ /* Declare external database variables.  */
+ #define DEFINE_DATABASE(name)						      \
+-  extern service_user *__nss_##name##_database attribute_hidden;	      \
++  service_user *__nss_##name##_database attribute_hidden;		      \
+   weak_extern (__nss_##name##_database)
+ #include "databases.def"
+ #undef DEFINE_DATABASE
+diff --git a/nss/nsswitch.h b/nss/nsswitch.h
+index eccb535ef5..63573b9ebc 100644
+--- a/nss/nsswitch.h
++++ b/nss/nsswitch.h
+@@ -226,10 +226,10 @@ libc_hidden_proto (__nss_hostname_digits_dots)
+ #define MAX_NR_ADDRS    48
+ 
+ /* Prototypes for __nss_*_lookup2 functions.  */
+-#define DEFINE_DATABASE(arg)				    \
+-  service_user *__nss_##arg##_database attribute_hidden;    \
+-  int __nss_##arg##_lookup2 (service_user **, const char *, \
+-			     const char *, void **);	    \
++#define DEFINE_DATABASE(arg)						      \
++  extern service_user *__nss_##arg##_database attribute_hidden;		      \
++  int __nss_##arg##_lookup2 (service_user **, const char *,		      \
++			     const char *, void **);			      \
+   libc_hidden_proto (__nss_##arg##_lookup2)
+ #include "databases.def"
+ #undef DEFINE_DATABASE
+diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c
+index f509534ca9..8c64ac59ff 100644
+--- a/posix/tst-rfc3484-2.c
++++ b/posix/tst-rfc3484-2.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef	USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
+diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c
+index ae44087a10..1c61aaf844 100644
+--- a/posix/tst-rfc3484-3.c
++++ b/posix/tst-rfc3484-3.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef	USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
+diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c
+index 7f191abbbc..8f45848e44 100644
+--- a/posix/tst-rfc3484.c
++++ b/posix/tst-rfc3484.c
+@@ -58,6 +58,7 @@ _res_hconf_init (void)
+ #undef	USE_NSCD
+ #include "../sysdeps/posix/getaddrinfo.c"
+ 
++service_user *__nss_hosts_database attribute_hidden;
+ 
+ /* This is the beginning of the real test code.  The above defines
+    (among other things) the function rfc3484_sort.  */
diff --git a/contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include__-to-include-asm-syscalls.h.patch b/contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include-to-include-asm-syscalls.h.patch
similarity index 90%
rename from contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include__-to-include-asm-syscalls.h.patch
rename to contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include-to-include-asm-syscalls.h.patch
index d6217157ee57e..c0f8495c41de1 100644
--- a/contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include__-to-include-asm-syscalls.h.patch
+++ b/contrib/guix/patches/glibc-2.27-riscv64-Use-__has_include-to-include-asm-syscalls.h.patch
@@ -1,3 +1,7 @@
+Note that this has been modified from the original commit, to use __has_include
+instead of __has_include__, as the later was causing build failures with GCC 10.
+See also: http://lists.busybox.net/pipermail/buildroot/2020-July/590376.html.
+
 https://sourceware.org/git/?p=glibc.git;a=commit;h=0b9c84906f653978fb8768c7ebd0ee14a47e662e
 
 From 562c52cc81a4e456a62e6455feb32732049e9070 Mon Sep 17 00:00:00 2001
@@ -59,7 +63,7 @@ index d612ef4c6c..0b2042620b 100644
  #include <atomic.h>
  #include <sys/cachectl.h>
 -#include <asm/syscalls.h>
-+#if __has_include__ (<asm/syscalls.h>)
++#if __has_include (<asm/syscalls.h>)
 +# include <asm/syscalls.h>
 +#else
 +# include <asm/unistd.h>


Test patch: