~ruther/guix-local

c4a100f3c6ddaa7f8bcd44cbaa5c733c9f4110f4 — Leo Nikkilä 1 year, 9 months ago c6e3584
gnu: gcc-6: Use libstdc++ headers appropriate for each GCC.

After the "hack" introduced for <https://issues.guix.gnu.org/42392>, all GCCs
are built with the current GCC's libstdc++ headers.  This results in subtly
broken C++ headers in older versions, which aren't necessarily compatible with
libstdc++s from other versions.

For example, this test case works with GCC 11:

    $ guix shell --container --emulate-fhs --pure -e '(@ (gnu packages gcc) gcc)' binutils -- sh -c 'echo -e "#include <cmath>\nint main() { return std::isnan(0); }" | g++ -x c++ -; echo $?'
    0

but fails with GCC 9:

    $ guix shell --container --emulate-fhs --pure -e '(@ (gnu packages gcc) gcc-9)' binutils -- sh -c 'echo -e "#include <cmath>\nint main() { return std::isnan(0); }" | g++ -x c++ -; echo $?'

    In file included from /gnu/store/gkh2rljdrnj24q1q7baa6bhb119251w4-profile/include/c++/cmath:45,
                     from <stdin>:1:
    <stdin>: In function 'int main()':
    <stdin>:2:26: error: '__builtin_isnan' is not a member of 'std'; did you mean '__builtin_isnan'?
    <built-in>: note: '__builtin_isnan' declared here
    1

This specific error can be traced back to the GCC build, where GCC 10 and 11
are configured with:

    checking for ISO C99 support in <math.h> for C++11... yes

but GCC 9 is configured with:

    checking for ISO C99 support in <math.h> for C++11... no

The configure check fails due to errors like these due to the mismatched
libstdc++:

    configure:17817: checking for ISO C99 support in <math.h> for C++11
    […]
    In file included from /gnu/store/y3kk0ybf7hqwndl8xpm61r4a5b3lhwix-libstdc++-11.4.0/include/cmath:41,
                     from /gnu/store/y3kk0ybf7hqwndl8xpm61r4a5b3lhwix-libstdc++-11.4.0/include/math.h:36,
                     from conftest.cpp:41:
    /gnu/store/y3kk0ybf7hqwndl8xpm61r4a5b3lhwix-libstdc++-11.4.0/include/bits/c++config.h:491:18: error: missing binary operator before token "("
      491 | #if __has_builtin(__builtin_is_constant_evaluated)
          |                  ^

Updating libstdc++ to reference each GCC works around this.

* gnu/packages/gcc.scm (libstdc++, libstdc++-headers): Remove variables.
(make-libstdc++-headers): New procedure.
(gcc-6)[native-inputs]: Use it with `this-package'.

Change-Id: Ie05878c83860c4ccc29d66b916d11613e367e142
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Modified-by: Ludovic Courtès <ludo@gnu.org>
1 files changed, 25 insertions(+), 25 deletions(-)

M gnu/packages/gcc.scm
M gnu/packages/gcc.scm => gnu/packages/gcc.scm +25 -25
@@ 18,6 18,7 @@
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;; Copyright © 2024 Nguyễn Gia Phong <mcsinyx@disroot.org>
;;; Copyright © 2025 Janneke Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2025 Leo Nikkilä <hello@lnikki.la>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 53,6 54,7 @@
  #:use-module (gnu packages perl)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module (guix memoization)
  #:use-module (guix build-system gnu)
  #:use-module (guix build-system trivial)
  #:use-module (guix gexp)


@@ 579,7 581,7 @@ Go.  It also includes runtime support libraries for these languages.")
       ;; XXX: This gross hack allows us to have libstdc++'s <bits/c++config.h>
       ;; in the search path, thereby avoiding misconfiguration of libstdc++:
       ;; <https://bugs.gnu.org/42392>.
       ("libstdc++" ,libstdc++-headers)
       ("libstdc++" ,(make-libstdc++-headers this-package))

       ,@(package-inputs gcc-4.7)))))



@@ 1127,30 1129,28 @@ using compilers other than GCC."
    (propagated-inputs '())
    (synopsis "GNU C++ standard library")))

(define libstdc++
  ;; Libstdc++ matching the default GCC.
  (make-libstdc++ gcc))

(define libstdc++-headers
  ;; XXX: This package is for internal use to work around
  ;; <https://bugs.gnu.org/42392> (see above).  The main difference compared
  ;; to the libstdc++ headers that come with 'gcc' is that <bits/c++config.h>
  ;; is right under include/c++ and not under
  ;; include/c++/x86_64-unknown-linux-gnu (aka. GPLUSPLUS_TOOL_INCLUDE_DIR).
  (package
    (inherit libstdc++)
    (name "libstdc++-headers")
    (outputs '("out"))
    (build-system trivial-build-system)
    (arguments
     '(#:builder (let* ((out       (assoc-ref %outputs "out"))
                        (libstdc++ (assoc-ref %build-inputs "libstdc++")))
                   (mkdir out)
                   (mkdir (string-append out "/include"))
                   (symlink (string-append libstdc++ "/include")
                            (string-append out "/include/c++")))))
    (inputs `(("libstdc++" ,libstdc++)))
    (synopsis "Headers of GNU libstdc++")))
(define make-libstdc++-headers
  (mlambdaq (gcc)      ;memoize to play well with the object cache
    ;; XXX: This package is for internal use to work around
    ;; <https://bugs.gnu.org/42392> (see above).  The main difference compared
    ;; to the libstdc++ headers that come with 'gcc' is that <bits/c++config.h>
    ;; is right under include/c++ and not under
    ;; include/c++/x86_64-unknown-linux-gnu (aka. GPLUSPLUS_TOOL_INCLUDE_DIR).
    (let ((libstdc++ (make-libstdc++ gcc)))
      (package
        (inherit libstdc++)
        (name "libstdc++-headers")
        (outputs '("out"))
        (build-system trivial-build-system)
        (arguments
         '(#:builder (let* ((out       (assoc-ref %outputs "out"))
                            (libstdc++ (assoc-ref %build-inputs "libstdc++")))
                       (mkdir out)
                       (mkdir (string-append out "/include"))
                       (symlink (string-append libstdc++ "/include")
                                (string-append out "/include/c++")))))
        (inputs `(("libstdc++" ,libstdc++)))
        (synopsis "Headers of GNU libstdc++")))))

(define-public libstdc++-4.9
  (make-libstdc++ gcc-4.9))