Subject: [PATCH core-updates-frozen 1/2] gnu: make-bootstrap: Fix build of static gawk.
From: Thiago Jung Bauermann <[email-masked]>
To: [email-masked]
Cc: Thiago Jung Bauermann <[email-masked]>
Date: Mon, 23 Aug 2021 17:51:27 -0300
List-Id: <debbugs-submit.debbugs.gnu.org>

* gnu/packages/make-bootstrap.scm (%static-inputs)[finalize-with-ld-flags]:
New function.
[map]<match-lambda>: Add new clause to match three elements.
[map]<gawk>: Add linker option.
* guix/build-system/gnu.scm (static-package): Add ‘#:ld-flags’ keyword
argument.
---

Hello,

gawk for ‘static-binaries-tarball’ is failing to build natively, at least for
x86_64-linux¹ and powerpc64le-linux. On both of them, the problem is the same:

--8<---------------cut here---------------start------------->8---
ld: ext.o: in function `load_ext':
/tmp/guix-build-gawk-5.1.0.drv-0/gawk-5.1.0/ext.c:59: warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o): in function `_getopt_internal_r':
(.text+0x6e0): multiple definition of `_getopt_internal_r'; support/libsupport.a(getopt.o):/tmp/guix-build-gawk-5.1.0.drv-0/gawk-5.1.0/support/getopt.c:404: first defined here
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o): in function `_getopt_internal':
(.text+0xcc0): multiple definition of `_getopt_internal'; support/libsupport.a(getopt.o):/tmp/guix-build-gawk-5.1.0.drv-0/gawk-5.1.0/support/getopt.c:1187: first defined here
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o):(.data+0x8): multiple definition of `optind'; support/libsupport.a(getopt.o):/gnu/store/zy7zwhxxbphqqmigp17j54dpbpz6wr38-glibc-2.33/include/bits/getopt_core.h:50: first defined here
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o):(.data+0x4): multiple definition of `opterr'; support/libsupport.a(getopt.o):/gnu/store/zy7zwhxxbphqqmigp17j54dpbpz6wr38-glibc-2.33/include/bits/getopt_core.h:55: first defined here
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o):(.data+0x0): multiple definition of `optopt'; support/libsupport.a(getopt.o):/gnu/store/zy7zwhxxbphqqmigp17j54dpbpz6wr38-glibc-2.33/include/bits/getopt_core.h:59: first defined here
ld: /gnu/store/qmgsfxm3ad5n7bi947n7xw0wq86blqr9-glibc-2.33-static/lib/libc.a(getopt.o): in function `getopt':
(.text+0xd20): multiple definition of `getopt'; support/libsupport.a(getopt.o):/tmp/guix-build-gawk-5.1.0.drv-0/gawk-5.1.0/support/getopt.c:1206: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [Makefile:663: gawk] Error 1
make[2]: Leaving directory '/tmp/guix-build-gawk-5.1.0.drv-0/gawk-5.1.0'
--8<---------------cut here---------------end--------------->8---

This patch fixes it by passing “--allow-multiple-definition” to the linker.

Judging by the CI results, cross-builds seems to be working. I haven’t looked
into what’s different about them.

NB: I wasn’t sure how to write a changelog for ‘%static-inputs’ so I got a bit
creative.

¹ https://ci.guix.gnu.org/build/502639/details

 gnu/packages/make-bootstrap.scm | 14 +++++++++++---
 guix/build-system/gnu.scm       |  8 ++++++--
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/gnu/packages/make-bootstrap.scm b/gnu/packages/make-bootstrap.scm
index 12e59e9f8383..79eb9d60026f 100644
--- a/gnu/packages/make-bootstrap.scm
+++ b/gnu/packages/make-bootstrap.scm
@@ -260,10 +260,15 @@ for `sh' in $PATH, and without nscd, and with static NSS modules."
                     `(modify-phases ,phases
                        (delete 'fix-egrep-and-fgrep)))))))
         (finalize (compose static-package
-                           package-with-relocatable-glibc)))
+                           package-with-relocatable-glibc))
+        (finalize-with-ld-flags (lambda (pkg ld-flags)
+                                  (package-with-relocatable-glibc
+                                   (static-package pkg #:ld-flags ld-flags)))))
     `(,@(map (match-lambda
               ((name package)
-               (list name (finalize package))))
+               (list name (finalize package)))
+               ((name package ld-flags)
+                (list name (finalize-with-ld-flags package ld-flags))))
              `(("tar" ,tar)
                ("gzip" ,gzip)
                ("bzip2" ,bzip2)
@@ -272,7 +277,10 @@ for `sh' in $PATH, and without nscd, and with static NSS modules."
                ("coreutils" ,coreutils)
                ("sed" ,sed)
                ("grep" ,grep)
-               ("gawk" ,gawk)))
+               ("gawk" ,gawk
+                ;; gawk's gnulib defines some getopt symbols which are also in
+                ;; libc.a so this linker option is needed for a static build.
+                "-Wl,--allow-multiple-definition")))
       ("bash" ,static-bash))))
 
 (define %static-binaries
diff --git a/guix/build-system/gnu.scm b/guix/build-system/gnu.scm
index ea91be5bcd0c..acbd5b3a0de4 100644
--- a/guix/build-system/gnu.scm
+++ b/guix/build-system/gnu.scm
@@ -210,7 +210,7 @@ flags for VARIABLE, the associated value is augmented."
   "A version of P linked with `-static-gcc'."
   (package-with-extra-configure-variable p "LDFLAGS" "-static-libgcc"))
 
-(define* (static-package p #:key (strip-all? #t))
+(define* (static-package p #:key (strip-all? #t) (ld-flags #f))
   "Return a statically-linked version of package P.  If STRIP-ALL? is true,
 use `--strip-all' as the arguments to `strip'."
   (package (inherit p)
@@ -220,7 +220,11 @@ use `--strip-all' as the arguments to `strip'."
                   #:strip-flags '("--strip-unneeded")))))
        (substitute-keyword-arguments a
          ((#:configure-flags flags)
-          `(cons* "--disable-shared" "LDFLAGS=-static" ,flags))
+          `(cons* "--disable-shared" (string-append "LDFLAGS=-static"
+                                                    (if ,ld-flags
+                                                        (string-append " " ,ld-flags)
+                                                        ""))
+                  ,flags))
          ((#:strip-flags flags)
           (if strip-all?
               ''("--strip-all")