Patchwork [3/3] {e}glibc: Fix various multilib build bugs

login
register
mail settings
Submitter Ray Donnelly
Date Feb. 4, 2014, 8:35 a.m.
Message ID <CAOYw7duBJoeZxFi-MXPAztNj2Ux3pcWXimcn5Ov5fbn3ixMRbg@mail.gmail.com>
Download mbox | patch
Permalink /patch/316479/
State New
Headers show

Comments

Ray Donnelly - Feb. 4, 2014, 8:35 a.m.
# HG changeset patch
# User Ray Donnelly <mingw.android@gmail.com>
# Date 1391501320 0
#      Tue Feb 04 08:08:40 2014 +0000
# Node ID 8f8b94c987feadc63f23ca72b6de87d404c7cca7
# Parent  45760158aca33981b5bb882191043bd708b57dbb
{e}glibc: Fix various multilib build bugs

--host=${CT_TARGET} with eg -m32 is not right.
The arch part must be correct (i686 for 32-bit
and x86_64 for 64-bit). Un-fortunately GCC has
no mechanism for returning each arches triplet
so instead some hacks are used. Debian can ask
"gcc -m32 -print-multiarch" but this flag isnt
provided on other GCC builds.

The old symlinks from lib32/64 to lib are only
made if CT_MULTILIB=n, and the comment that we
are not multilib on the target side corrected.

The stub libc.so is compiled with extra_cflags
so that it is for the correct multilib arch.

The stub libc.so and crt*.o files are moved to
the multilib os directory and not the multilib
directory if gcc arg -print-multi-os-directory
is supported.

--libdir=<> is passed to libc's configure such
that it is made inplace in the multilib-os dir
and 'Fixing up multilib location' is no longer
required.

The multilib directories are sorted in reverse
order so that x86_64 is built finally. This is
because x86_64 headers are multilib-capable as
far back as glibc-2.15 (at least) whereas i686
headers were not multilib-capable until 2.16.

Signed-off-by: Ray Donnelly <mingw.android@gmail.com>

-                # Remove the multi_dir now it is no longer useful
-                CT_DoExecLog DEBUG rm -rf "${CT_SYSROOT_DIR}/${multi_dir}"
-            fi # libc_mode == final
-
-            CT_EndStep
-        fi
     done

     CT_EndStep
@@ -180,6 +181,7 @@
 #   Parameter           : Definition                            :
Type      : Default
 #   libc_headers        : Build libc headers                    : bool      : n
 #   libc_startfiles     : Build libc start-files                : bool      : n
+#   libc_triplet        : Build libc triplet                    :
string    : ${CT_TARGET}
 #   libc_full           : Build full libc                       : bool      : n
 #   extra_flags         : Extra CFLAGS to use (for multilib)    :
string    : (empty)
 #   extra_dir           : Extra subdir for multilib             :
string    : (empty)
@@ -189,6 +191,9 @@
     local libc_full
     local extra_flags
     local extra_dir
+    local extraos_dir
+    local lib_dir
+    local install_root
     local src_dir="${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}"
     local extra_cc_args
     local -a extra_config
@@ -196,6 +201,7 @@
     local glibc_cflags
     local float_extra
     local endian_extra
+    local libc_triplet="${CT_TARGET}"
     local arg

     for arg in "$@"; do
@@ -328,6 +334,29 @@
     # or even after they get installed...
     echo "ac_cv_path_BASH_SHELL=/bin/bash" >>config.cache

+    # GCC makes the distinction between multilib directories
+    # (gotten via -print-multilib or -print-multi-directory)
+    # and multilib-os directories (via -print-multi-os-directory)
+    # They are also often horribly mis-aligned, such as:
+    # multilib:    -m32=32      -m64=.
+    # multilib-os: -m32=../lib  -m64=../lib64
+    # it is important that multilib sub-folders of the sysroot use
+    # the multilib-os directory and *not* the multilib directory.
+    # The multilib directory is a GCC implementation detail rather
+    # than something that users need to be concerned about. Older
+    # GCCs do not understand -print-multi-os-directory so we fall
+    # back on some simple transformations (that are wrong in the
+    # above example!)
+    if "${cross_cc}" -print-multi-os-directory ${extra_cc_args} >
/dev/null 2>&1; then
+        lib_dir=/usr/lib/$("${cross_cc}" -print-multi-os-directory
${extra_cc_args})
+        install_root="${CT_SYSROOT_DIR}"
+    else
+        # maintain the previous behaviour if
-print-multi-os-directory doesn't work.
+        lib_dir=/usr/lib
+        install_root="${CT_SYSROOT_DIR}${extra_dir}"
+    fi
+    extraos_dir="${install_root}${lib_dir}"
+
     # Configure with --prefix the way we want it on the target...
     # There are a whole lot of settings here.  You'll probably want
     # to read up on what they all mean, and customize a bit, possibly
by setting GLIBC_EXTRA_CONFIG_ARRAY
@@ -338,11 +367,14 @@
     # Run explicitly through CONFIG_SHELL, or the build breaks badly
(loop-of-death)
     # when the shell is not bash... Sigh... :-(

-    CT_DoLog DEBUG "Using gcc for target    : '${cross_cc}'"
-    CT_DoLog DEBUG "Configuring with addons : '$(do_libc_add_ons_list ,)'"
-    CT_DoLog DEBUG "Extra config args passed: '${extra_config[*]}'"
-    CT_DoLog DEBUG "Extra CC args passed    : '${glibc_cflags}'"
-    CT_DoLog DEBUG "Extra flags (multilib)  : '${extra_flags}'"
+    CT_DoLog DEBUG "Using gcc for target     : '${cross_cc}'"
+    CT_DoLog DEBUG "Configuring with addons  : '$(do_libc_add_ons_list ,)'"
+    CT_DoLog DEBUG "Extra config args passed : '${extra_config[*]}'"
+    CT_DoLog DEBUG "Extra CC args passed     : '${glibc_cflags}'"
+    CT_DoLog DEBUG "Extra flags (multilib)   : '${extra_flags}'"
+    CT_DoLog DEBUG "Multilib os dir          : '${extraos_dir}'"
+    CT_DoLog DEBUG "Configuring with --host  : '${libc_triplet}'"
+    CT_DoLog DEBUG "Configuring with --libdir: '${lib_dir}'"

     CT_DoExecLog CFG                                                \
     BUILD_CC="${CT_BUILD}-gcc"                                      \
@@ -354,12 +386,13 @@
     "${src_dir}/configure"                                          \
         --prefix=/usr                                               \
         --build=${CT_BUILD}                                         \
-        --host=${CT_TARGET}                                         \
+        --host=${libc_triplet}                                      \
         --cache-file="$(pwd)/config.cache"                          \
         --without-cvs                                               \
         --disable-profile                                           \
         --without-gd                                                \
         --with-headers="${CT_HEADERS_DIR}"                          \
+        --libdir=${lib_dir}                                         \
         "${extra_config[@]}"                                        \
         "${CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY[@]}"

@@ -378,7 +411,7 @@
         # use the 'install-headers' makefile target to install the
         # headers
         CT_DoExecLog ALL make ${JOBSFLAGS}                          \
-                         install_root=${CT_SYSROOT_DIR}${extra_dir} \
+                         install_root="${install_root}"             \
                          install-bootstrap-headers=yes              \
                          "${extra_make_args[@]}"                    \
                          install-headers
@@ -427,22 +460,23 @@

             # there are a few object files needed to link shared libraries,
             # which we build and install by hand
-            CT_DoExecLog ALL mkdir -p "${CT_SYSROOT_DIR}${extra_dir}/usr/lib"
+            CT_DoExecLog ALL mkdir -p "${extraos_dir}"
             CT_DoExecLog ALL make ${JOBSFLAGS}  \
                         "${extra_make_args[@]}" \
                         csu/subdir_lib
             CT_DoExecLog ALL cp csu/crt1.o csu/crti.o csu/crtn.o    \
-                                "${CT_SYSROOT_DIR}${extra_dir}/usr/lib"
+                                "${extraos_dir}"

             # Finally, 'libgcc_s.so' requires a 'libc.so' to link against.
             # However, since we will never actually execute its code,
             # it doesn't matter what it contains.  So, treating '/dev/null'
             # as a C source file, we produce a dummy 'libc.so' in one step
-            CT_DoExecLog ALL "${cross_cc}" -nostdlib        \
+            CT_DoExecLog ALL "${cross_cc}" ${extra_flags}   \
+                                            -nostdlib       \
                                            -nostartfiles    \
                                            -shared          \
                                            -x c /dev/null   \
-                                           -o
"${CT_SYSROOT_DIR}${extra_dir}/usr/lib/libc.so"
+                                           -o "${extraos_dir}/libc.so"
         fi # threads == nptl
     fi # libc_headers == y

@@ -453,9 +487,9 @@
                               all

         CT_DoLog EXTRA "Installing C library"
-        CT_DoExecLog ALL make ${JOBSFLAGS}                                  \
-                              "${extra_make_args[@]}"                       \
-                              install_root="${CT_SYSROOT_DIR}${extra_dir}"  \
+        CT_DoExecLog ALL make ${JOBSFLAGS}                    \
+                              "${extra_make_args[@]}"         \
+                              install_root="${install_root}"  \
                               install

         if [ "${CT_BUILD_MANUALS}" = "y" ]; then

--
For unsubscribe information see http://sourceware.org/lists.html#faq

Patch

diff -r 45760158aca3 -r 8f8b94c987fe scripts/build/cc/gcc.sh
--- a/scripts/build/cc/gcc.sh Tue Feb 04 07:55:11 2014 +0000
+++ b/scripts/build/cc/gcc.sh Tue Feb 04 08:08:40 2014 +0000
@@ -375,6 +375,7 @@ 

     if [ "${CT_MULTILIB}" = "y" ]; then
         extra_config+=("--enable-multilib")
+        extra_config+=("--enable-targets=all")
     else
         extra_config+=("--disable-multilib")
     fi
diff -r 45760158aca3 -r 8f8b94c987fe scripts/build/libc/glibc-eglibc.sh-common
--- a/scripts/build/libc/glibc-eglibc.sh-common Tue Feb 04 07:55:11 2014 +0000
+++ b/scripts/build/libc/glibc-eglibc.sh-common Tue Feb 04 08:08:40 2014 +0000
@@ -76,6 +76,9 @@ 
     local multilib
     local multi_dir
     local multi_flags
+    local multi_arch
+    local native_arch
+    local rest_of_triplet
     local extra_dir
     local libc_headers libc_startfiles libc_full
     local hdr
@@ -85,6 +88,9 @@ 
         eval "${arg// /\\ }"
     done

+    native_arch=$(echo "${CT_TARGET}" | ${sed} "s,\(^[^\-]*\).*,\1,g")
+    rest_of_triplet=$(echo "${CT_TARGET}" | ${sed} "s,^[^\-]*\(.*\),\1,g")
+
     case "${libc_mode}" in
         startfiles)
             CT_DoStep INFO "Installing C library headers & start files"
@@ -103,8 +109,16 @@ 

     # If gcc is not configured for multilib, it still prints
     # a single line for the default settings
-    multilibs=( $("${CT_TARGET}-gcc" -print-multi-lib 2>/dev/null) )
+    # sort -r is a hack so that x86_64 gets built last because
+    # pre-2.16 only the x86_64 headers were applicable to both
+    # i686 and x86_64.
+    # The headers were unified (x86-64 won!) between 2.15 and
+    # 2.16 (BZ14117). This hack makes too many of assumptions
+    # and needs to be replaced with more robust logic. We need
+    # to force x86_64 arch to be last element in the array.
+    multilibs=( $("${CT_TARGET}-gcc" -print-multi-lib 2>/dev/null | sort -r) )
     for multilib in "${multilibs[@]}"; do
+        multi_arch="${native_arch}"
         multi_dir="${multilib%%;*}"
         if [ "${multi_dir}" != "." ]; then
             CT_DoStep INFO "Building for multilib subdir='${multi_dir}'"
@@ -114,6 +128,14 @@ 
                           )"
             extra_dir="/${multi_dir}"

+            # If more substitutions are needed then they
+            # should be added here, AArch64 for example?
+            if [ "${extra_flags}" = " -m32" ]; then
+              multi_arch=${native_arch/x86_64/i686}
+            elif [ "${extra_flags}" = " -m64" ]; then
+              multi_arch=${native_arch/i686/x86_64}
+            fi
+
             # glibc install its files in ${extra_dir}/{usr/,}lib
             # while gcc expects them in {,usr/}lib/${extra_dir}.
             # Prepare some symlinks so glibc installs in fact in
@@ -140,36 +162,15 @@ 

         CT_mkdir_pushd
"${CT_BUILD_DIR}/build-libc-${libc_mode}${extra_dir//\//_}"

-        do_libc_backend_once extra_dir="${extra_dir}"               \
-                             extra_flags="${extra_flags}"           \
-                             libc_headers="${libc_headers}"         \
-                             libc_startfiles="${libc_startfiles}"   \
+        do_libc_backend_once extra_dir="${extra_dir}"
          \
+                             extra_flags="${extra_flags}"
          \
+                             libc_headers="${libc_headers}"
          \
+                             libc_startfiles="${libc_startfiles}"
          \
+
libc_triplet="${multi_arch}${rest_of_triplet}"     \
                              libc_full="${libc_full}"

         CT_Popd

-        if [ "${multi_dir}" != "." ]; then
-            if [ "${libc_mode}" = "final" ]; then
-                CT_DoLog EXTRA "Fixing up multilib location"
-
-                # rewrite the library multiplexers
-                for d in "lib/${multi_dir}" "usr/lib/${multi_dir}"; do
-                    for l in libc libpthread libgcc_s; do
-                        if [    -f "${CT_SYSROOT_DIR}/${d}/${l}.so"    \
-                             -a ! -L ${CT_SYSROOT_DIR}/${d}/${l}.so    ]
-                        then
-                            CT_DoExecLog DEBUG ${sed} -r -i
                      \
-                                                      -e
"s:/lib/:/lib/${multi_dir}/:g;"    \
-
"${CT_SYSROOT_DIR}/${d}/${l}.so"
-                        fi
-                    done
-                done