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 <stilor@att.net>
This commit is contained in:
Alexey Neyman 2016-04-11 23:11:22 -07:00
parent 99dd2f6f60
commit 258394c19f
2 changed files with 83 additions and 17 deletions

View File

@ -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() {
# <sysroot>/m4a/usr/lib/m4a/
# <sysroot>/m4a/lib/
# <sysroot>/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 <sysroot>/m4a/usr/lib, but not in <sysroot>/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
}

View File

@ -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