From 258394c19f7b3fd3700814d7b4de9336bb16e554 Mon Sep 17 00:00:00 2001 From: Alexey Neyman Date: Mon, 11 Apr 2016 23:11:22 -0700 Subject: Treat multiroots differently. 'ld' does not search for dependency libraries in multi_os_directory, so if there's both multi_os_directory and multi_root, and there is only one configuration in each multi_root, forgo the multi_os_directory suffix. Needed for sh4-multilib-linux-uclibc. Signed-off-by: Alexey Neyman diff --git a/scripts/build/libc/glibc.sh b/scripts/build/libc/glibc.sh index dc9443c..8093e08 100644 --- a/scripts/build/libc/glibc.sh +++ b/scripts/build/libc/glibc.sh @@ -66,7 +66,8 @@ do_libc_backend() { local libc_mode local -a multilibs local multilib - local multi_dir multi_os_dir multi_flags multi_last + local multi_dir multi_os_dir multi_root multi_flags multi_last + local root_suffix local target local arg @@ -86,18 +87,12 @@ do_libc_backend() { ;; esac + CT_mkdir_pushd "${CT_BUILD_DIR}/build-libc-${libc_mode}" + # 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) ) - last_multi= for multilib in "${multilibs[@]}"; do - last_multi=$(( ${#multilibs[@]} - 1 )) - if [ "${multilib%%;*}" = "${multilibs[last_multi]%%;*}" ]; then - # This is the last multilib build or multilib is '.' - # (default target, not multilib) - multi_last=y - fi - # GCC makes the distinction between: # multilib (-print-multi-lib or -print-multi-directory) and # multilib-os (--print-multi-os-directory) @@ -114,10 +109,50 @@ do_libc_backend() { # /m4a/usr/lib/m4a/ # /m4a/lib/ # /m4a/usr/lib/ + # The problem is that while GCC itself is aware of these subtleties, the + # binutils (notably, ld) it invokes under the hood are not. For example, + # if a shared library libfoo.so.1 requires libbar.so.1, ld will only search + # for libbar.so.1 in /m4a/usr/lib, but not in /m4a/usr/lib/m4a. + # In other words, 'gcc -lfoo -lbar' will work for both the default and -m4a + # cases, and 'gcc -lfoo' will work for the default, but not for -m4a. To + # address this, we first try to determine if the sysroot alone makes the + # configuration sufficiently unique. If there are no multilibs within the + # same suffixed sysroot, we can drop the multi_os_dir and both gcc and ld + # will work. If not, we'll supply both multi_root/multi_os_dir (which will + # likely break later, e.g. while building final GCC with C++ support). But, + # we've done all we can. multi_flags=$( echo "${multilib#*;}" | ${sed} -r -e 's/@/ -/g;' ) multi_dir="${multilib%%;*}" multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory ${multi_flags} ) multi_root=$( "${CT_TARGET}-gcc" -print-sysroot ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + CT_DoExecLog ALL mkdir -p "sysroot${root_suffix}" + if [ -e "sysroot${root_suffix}/seen" ]; then + CT_DoExecLog ALL rm -f "sysroot${root_suffix}/unique" + else + CT_DoExecLog ALL touch "sysroot${root_suffix}/seen" "sysroot${root_suffix}/unique" + fi + done + + last_multi= + for multilib in "${multilibs[@]}"; do + last_multi=$(( ${#multilibs[@]} - 1 )) + if [ "${multilib%%;*}" = "${multilibs[last_multi]%%;*}" ]; then + # This is the last multilib build or multilib is '.' + # (default target, not multilib) + multi_last=y + fi + + multi_flags=$( echo "${multilib#*;}" | ${sed} -r -e 's/@/ -/g;' ) + multi_dir="${multilib%%;*}" + multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory ${multi_flags} ) + multi_root=$( "${CT_TARGET}-gcc" -print-sysroot ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + + # Avoid multi_os_dir if it's the only directory in this sysroot. + if [ -e "sysroot${root_suffix}/unique" ]; then + multi_os_dir=. + fi # Adjust target tuple according to CFLAGS + any GLIBC quirks target="${CT_TARGET}" @@ -127,7 +162,7 @@ do_libc_backend() { # Ensure sysroot (with suffix, if applicable) exists CT_DoExecLog ALL mkdir -p "${multi_root}" - CT_mkdir_pushd "${CT_BUILD_DIR}/build-libc-${libc_mode}${multi_dir//\//_}" + CT_mkdir_pushd "multilib_${multi_dir//\//_}" do_libc_backend_once multi_dir="${multi_dir}" \ multi_os_dir="${multi_os_dir}" \ multi_flags="${multi_flags}" \ @@ -141,6 +176,7 @@ do_libc_backend() { done + CT_Popd CT_EndStep } diff --git a/scripts/build/libc/uClibc.sh b/scripts/build/libc/uClibc.sh index 822d381..edde815 100644 --- a/scripts/build/libc/uClibc.sh +++ b/scripts/build/libc/uClibc.sh @@ -81,6 +81,8 @@ do_libc_backend() { *) CT_Abort "Unsupported (or unset) libc_mode='${libc_mode}'";; esac + CT_mkdir_pushd "${CT_BUILD_DIR}/build-libc-${libc_mode}" + # See glibc.sh for the explanation of this magic. multilibs=( $("${CT_TARGET}-gcc" -print-multi-lib 2>/dev/null) ) for multilib in "${multilibs[@]}"; do @@ -88,6 +90,26 @@ do_libc_backend() { multi_dir="${multilib%%;*}" multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory ${multi_flags} ) multi_root=$( "${CT_TARGET}-gcc" -print-sysroot ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + CT_DoExecLog ALL mkdir -p "sysroot${root_suffix}" + if [ -e "sysroot${root_suffix}/seen" ]; then + CT_DoExecLog ALL rm -f "sysroot${root_suffix}/unique" + else + CT_DoExecLog ALL touch "sysroot${root_suffix}/seen" "sysroot${root_suffix}/unique" + fi + done + + for multilib in "${multilibs[@]}"; do + multi_flags=$( echo "${multilib#*;}" | ${sed} -r -e 's/@/ -/g;' ) + multi_dir="${multilib%%;*}" + multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory ${multi_flags} ) + multi_root=$( "${CT_TARGET}-gcc" -print-sysroot ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + + # Avoid multi_os_dir if it's the only directory in this sysroot. + if [ -e "sysroot${root_suffix}/unique" ]; then + multi_os_dir=. + fi CT_DoStep INFO "Building for multilib '${multi_flags}'" do_libc_backend_once multi_dir="${multi_dir}" \ @@ -104,17 +126,23 @@ do_libc_backend() { # and expects it in /lib for the other. So, create a symlink from lib # to the actual location, but only if that will not override the actual # file in /lib. Thus, need to do this after all the variants are built. - CT_mkdir_pushd "${CT_BUILD_DIR}/build-libc-test-ldso" - echo "int main(void) { return 0; }" > dummy.c + echo "int main(void) { return 0; }" > test-ldso.c for multilib in "${multilibs[@]}"; do multi_flags=$( echo "${multilib#*;}" | ${sed} -r -e 's/@/ -/g;' ) multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory ${multi_flags} ) multi_root=$( "${CT_TARGET}-gcc" -print-sysroot ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + + # Avoid multi_os_dir if it's the only directory in this sysroot. + if [ -e "sysroot${root_suffix}/unique" ]; then + multi_os_dir=. + fi + multilib_dir="/lib/${multi_os_dir}" CT_SanitizeVarDir multilib_dir - CT_DoExecLog ALL "${CT_TARGET}-gcc" -o dummy dummy.c ${multi_flags} - ldso=$( ${CT_TARGET}-readelf -Wl dummy | \ + CT_DoExecLog ALL "${CT_TARGET}-gcc" -o test-ldso test-ldso.c ${multi_flags} + ldso=$( ${CT_TARGET}-readelf -Wl test-ldso | \ grep 'Requesting program interpreter: ' | \ sed -e 's,.*: ,,' -e 's,\].*,,' ) ldso_d="${ldso%/ld*.so.*}" @@ -135,9 +163,9 @@ do_libc_backend() { "${multi_root}${ldso}" fi done - CT_Popd fi + CT_Popd CT_EndStep } @@ -157,9 +185,9 @@ do_libc_backend_once() { # Simply copy files until uClibc has the ability to build out-of-tree CT_DoLog EXTRA "Copying sources to build dir" - build_dir="${CT_BUILD_DIR}/build-libc-${libc_mode}${multi_dir//\//_}" + build_dir="multilib_${multi_dir//\//_}" CT_DoExecLog ALL cp -a "${CT_SRC_DIR}/${uclibc_name}-${CT_LIBC_VERSION}" "${build_dir}" - cd "${build_dir}" + CT_Pushd "${build_dir}" multilib_dir="lib/${multi_os_dir}" startfiles_dir="${multi_root}/usr/${multilib_dir}" @@ -297,6 +325,8 @@ do_libc_backend_once() { CT_DoExecLog ALL rm -rf "${multi_root}/usr/include/${hdr_install_subdir}" CT_DoExecLog ALL mv "${multi_root}/usr/include.new" "${multi_root}/usr/include/${hdr_install_subdir}" fi + + CT_Popd } # Initialises the .config file to sensible values -- cgit v0.10.2-6-g49f6