diff options
author | Alexey Neyman <stilor@att.net> | 2016-04-11 13:59:16 -0700 |
---|---|---|
committer | Alexey Neyman <stilor@att.net> | 2016-08-23 11:00:27 -0700 |
commit | 98e556d3868b638a658f497af0b64ce04fc5287d (patch) | |
tree | 9921bb8eba7ecfcf66327655910d1f22cd6783e1 /scripts | |
parent | 258394c19f7b3fd3700814d7b4de9336bb16e554 (diff) | |
download | crosstool-ng-98e556d3868b638a658f497af0b64ce04fc5287d.tar.gz crosstool-ng-98e556d3868b638a658f497af0b64ce04fc5287d.tar.bz2 crosstool-ng-98e556d3868b638a658f497af0b64ce04fc5287d.zip |
Support multilib in sh/uClibc.
Signed-off-by: Alexey Neyman <stilor@att.net>
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/build/arch/sh.sh | 32 | ||||
-rw-r--r-- | scripts/build/libc/glibc.sh | 122 | ||||
-rw-r--r-- | scripts/build/libc/uClibc.sh | 125 | ||||
-rw-r--r-- | scripts/functions | 151 |
4 files changed, 213 insertions, 217 deletions
diff --git a/scripts/build/arch/sh.sh b/scripts/build/arch/sh.sh index 101e4ce8..6761435d 100644 --- a/scripts/build/arch/sh.sh +++ b/scripts/build/arch/sh.sh @@ -44,9 +44,39 @@ CT_DoArchUClibcConfig() { CT_KconfigDisableOption "CONFIG_SH3" "${cfg}" CT_KconfigDisableOption "CONFIG_SH4" "${cfg}" CT_KconfigDisableOption "CONFIG_SH4A" "${cfg}" - case "${CT_ARCH_SH_VARIAN}" in + case "${CT_ARCH_SH_VARIANT}" in sh3) CT_KconfigEnableOption "CONFIG_SH3" "${cfg}";; sh4) CT_KconfigEnableOption "CONFIG_SH4" "${cfg}";; sh4a) CT_KconfigEnableOption "CONFIG_SH4A" "${cfg}";; esac } + +CT_DoArchUClibcCflags() { + local cfg="${1}" + local cflags="${2}" + local f + + for f in ${cflags}; do + case "${f}" in + -m3) + CT_KconfigEnableOption "CONFIG_SH3" "${cfg}" + ;; + -m4) + CT_KconfigEnableOption "CONFIG_SH4" "${cfg}" + CT_KconfigEnableOption "UCLIBC_HAS_FPU" "${cfg}" + ;; + -m4-nofpu) + CT_KconfigEnableOption "CONFIG_SH4" "${cfg}" + CT_KconfigDisableOption "UCLIBC_HAS_FPU" "${cfg}" + ;; + -m4a) + CT_KconfigEnableOption "CONFIG_SH4A" "${cfg}" + CT_KconfigEnableOption "UCLIBC_HAS_FPU" "${cfg}" + ;; + -m4a-nofpu) + CT_KconfigEnableOption "CONFIG_SH4A" "${cfg}" + CT_KconfigDisableOption "UCLIBC_HAS_FPU" "${cfg}" + ;; + esac + done +} diff --git a/scripts/build/libc/glibc.sh b/scripts/build/libc/glibc.sh index 8093e08b..8027b8f8 100644 --- a/scripts/build/libc/glibc.sh +++ b/scripts/build/libc/glibc.sh @@ -64,11 +64,6 @@ do_libc_post_cc() { # libc_mode : 'startfiles' or 'final' : string : (none) do_libc_backend() { local libc_mode - local -a multilibs - local multilib - local multi_dir multi_os_dir multi_root multi_flags multi_last - local root_suffix - local target local arg for arg in "$@"; do @@ -88,94 +83,7 @@ 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) ) - for multilib in "${multilibs[@]}"; do - # GCC makes the distinction between: - # multilib (-print-multi-lib or -print-multi-directory) and - # multilib-os (--print-multi-os-directory) - # as the gcc library and gcc sysroot library paths, respectively. - # For example, on x86_64: - # multilib: -m32=32 -m64=. - # multilib-os: -m32=../lib -m64=../lib64 - # Moreover, while some multilibs can coexist in the same sysroot (e.g. - # on x86), some have a "sysroot suffix" to separate incompatible variants. - # Such sysroot suffixes combine with multilib-os directories, e.g. - # on sh4 with -m4a multilib, the search order in sysroot is (dropping some - # directories for brevity: - # <sysroot>/m4a/lib/m4a/ - # <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}" - CT_DoMultilibTarget target ${extra_flags} - CT_DoArchGlibcAdjustTuple target - CT_DoStep INFO "Building for multilib '${multi_flags}'" - - # Ensure sysroot (with suffix, if applicable) exists - CT_DoExecLog ALL mkdir -p "${multi_root}" - CT_mkdir_pushd "multilib_${multi_dir//\//_}" - do_libc_backend_once multi_dir="${multi_dir}" \ - multi_os_dir="${multi_os_dir}" \ - multi_flags="${multi_flags}" \ - multi_root="${multi_root}" \ - multi_last="${multi_last}" \ - libc_mode="${libc_mode}" \ - libc_target="${target}" - - CT_Popd - CT_EndStep - - done - + CT_IterateMultilibs do_libc_backend_once multilib libc_mode="${libc_mode}" CT_Popd CT_EndStep } @@ -184,26 +92,28 @@ do_libc_backend() { # Usage: do_libc_backend_once param=value [...] # Parameter : Definition : Type # libc_mode : 'startfiles' or 'final' : string : (empty) -# libc_target : Build libc target triplet : string : (empty) -# multi_root : Installation root, chosen for multilib: string : (empty) -# multi_flags : Extra CFLAGS to use (for multilib) : string : (empty) -# multi_dir : Extra subdir for multilib (gcc) : string : (empty) -# multi_os_dir : Extra subdir for multilib (os) : string : (empty) -# multi_last : The last multilib target : bool : n +# multi_* : as defined in CT_IterateMultilibs : (varies) : do_libc_backend_once() { - local multi_flags multi_dir multi_os_dir multi_root multi_last multi_root + local multi_flags multi_dir multi_os_dir multi_root multi_index multi_count local startfiles_dir local src_dir="${CT_SRC_DIR}/${CT_LIBC}-${CT_LIBC_VERSION}" local -a extra_config local -a extra_make_args local glibc_cflags - local libc_target="${CT_TARGET}" local arg opt for arg in "$@"; do eval "${arg// /\\ }" done + CT_DoStep INFO "Building for multilib ${multi_index}/${multi_count}: '${multi_flags}'" + + # Ensure sysroot (with suffix, if applicable) exists + CT_DoExecLog ALL mkdir -p "${multi_root}" + + # Adjust target tuple according GLIBC quirks + CT_DoArchGlibcAdjustTuple multi_target + # Glibc seems to be smart enough to know about the cases that can coexist # in the same root and installs them into proper multilib-os directory; all # we need is to point to the right root. We do need to handle multilib-os @@ -335,7 +245,7 @@ do_libc_backend_once() { CT_DoLog DEBUG "Extra config args passed : '${extra_config[*]}'" CT_DoLog DEBUG "Extra CFLAGS passed : '${glibc_cflags}'" CT_DoLog DEBUG "Placing startfiles into : '${startfiles_dir}'" - CT_DoLog DEBUG "Configuring with --host : '${libc_target}'" + CT_DoLog DEBUG "Configuring with --host : '${multi_target}'" # CFLAGS are only applied when compiling .c files. .S files are compiled with ASFLAGS, # but they are not passed by configure. Thus, pass everything in CC instead. @@ -348,7 +258,7 @@ do_libc_backend_once() { "${src_dir}/configure" \ --prefix=/usr \ --build=${CT_BUILD} \ - --host=${libc_target} \ + --host=${multi_target} \ --cache-file="$(pwd)/config.cache" \ --without-cvs \ --disable-profile \ @@ -474,7 +384,7 @@ do_libc_backend_once() { install_root="${multi_root}" \ install - if [ "${CT_BUILD_MANUALS}" = "y" -a "${multi_last}" = "y" ]; then + if [ "${CT_BUILD_MANUALS}" = "y" -a "${multi_index}" = "${multi_count}" ]; then # We only need to build the manuals once. Only build them on the # last multilib target. If it's not multilib, it will happen on the # only target. @@ -488,10 +398,12 @@ do_libc_backend_once() { ${CT_PREFIX_DIR}/share/doc fi - if [ "${CT_LIBC_LOCALES}" = "y" -a "${multi_last}" = "y" ]; then + if [ "${CT_LIBC_LOCALES}" = "y" -a "${multi_index}" = "${multi_count}" ]; then do_libc_locales fi fi # libc_mode = final + + CT_EndStep } # Build up the addons list, separated with $1 diff --git a/scripts/build/libc/uClibc.sh b/scripts/build/libc/uClibc.sh index edde8159..046ba1d0 100644 --- a/scripts/build/libc/uClibc.sh +++ b/scripts/build/libc/uClibc.sh @@ -66,10 +66,7 @@ do_libc() { # Common backend for 1st and 2nd passes. do_libc_backend() { local libc_mode - local -a multilibs - local multilib - local multi_dir multi_os_dir multi_flags - local ldso ldso_f ldso_d multilib_dir + local arg for arg in "$@"; do eval "${arg// /\\ }" @@ -82,43 +79,7 @@ do_libc_backend() { 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 - 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 - - 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}" \ - multi_os_dir="${multi_os_dir}" \ - multi_flags="${multi_flags}" \ - multi_root="${multi_root}" \ - libc_mode="${libc_mode}" - CT_EndStep - done + CT_IterateMultilibs do_libc_backend_once multilib libc_mode="${libc_mode}" if [ "${libc_mode}" = "final" -a "${CT_SHARED_LIBS}" = "y" ]; then # uClibc and GCC disagree where the dynamic linker lives. uClibc always @@ -127,42 +88,7 @@ do_libc_backend() { # 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. 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 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.*}" - ldso_f="${ldso##*/}" - if [ -z "${ldso}" -o "${ldso_d}" = "${multilib_dir}" ]; then - # GCC cannot produce shared executable, or the base directory - # for ld.so is the same as the multi_os_directory - continue - fi - - # If there is no such file in the expected ldso dir, create a symlink to - # multilib_dir ld.so - if [ ! -r "${multi_root}${ldso}" ]; then - # Convert ldso_d to "how many levels we need to go up" and remove - # leading slash. - ldso_d=$( echo "${ldso_d#/}" | sed 's,[^/]\+,..,g' ) - CT_DoExecLog ALL ln -sf "${ldso_d}${multilib_dir}/${ldso_f}" \ - "${multi_root}${ldso}" - fi - done + CT_IterateMultilibs do_libc_ldso_fixup ldso_fixup fi CT_Popd @@ -172,10 +98,10 @@ do_libc_backend() { # Common backend for 1st and 2nd passes, once per multilib. do_libc_backend_once() { local libc_mode - local multi_dir multi_os_dir multi_root multilib_dir startfiles_dir + local multi_dir multi_os_dir multi_root multi_flags multi_index multi_count + local multilib_dir startfiles_dir local jflag=${CT_LIBC_UCLIBC_PARALLEL:+${JOBSFLAGS}} local -a make_args - local build_dir local extra_cflags f cfg_cflags cf local hdr_install_subdir @@ -183,11 +109,11 @@ do_libc_backend_once() { eval "${arg// /\\ }" done + CT_DoStep INFO "Building for multilib ${multi_index}/${multi_count}: '${multi_flags}'" + # Simply copy files until uClibc has the ability to build out-of-tree CT_DoLog EXTRA "Copying sources to build dir" - build_dir="multilib_${multi_dir//\//_}" - CT_DoExecLog ALL cp -a "${CT_SRC_DIR}/${uclibc_name}-${CT_LIBC_VERSION}" "${build_dir}" - CT_Pushd "${build_dir}" + CT_DoExecLog ALL cp -aT "${CT_SRC_DIR}/${uclibc_name}-${CT_LIBC_VERSION}" . multilib_dir="lib/${multi_os_dir}" startfiles_dir="${multi_root}/usr/${multilib_dir}" @@ -326,7 +252,40 @@ do_libc_backend_once() { CT_DoExecLog ALL mv "${multi_root}/usr/include.new" "${multi_root}/usr/include/${hdr_install_subdir}" fi - CT_Popd + CT_EndStep +} + +do_libc_ldso_fixup() { + local multi_dir multi_os_dir multi_root multi_flags multi_index multi_count + local ldso ldso_f ldso_d multilib_dir + + for arg in "$@"; do + eval "${arg// /\\ }" + done + + CT_DoLog EXTRA "Checking dynamic linker for multilib '${multi_flags}'" + + multilib_dir="/lib/${multi_os_dir}" + CT_SanitizeVarDir multilib_dir + + 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,\].*,,' ) + CT_DoLog DEBUG "Detected dynamic linker for multilib '${multi_flags}': '${ldso}'" + + ldso_d="${ldso%/ld*.so.*}" + ldso_f="${ldso##*/}" + # Create symlink if GCC produced an executable, dynamically linked, it was requesting + # a linker not in the current directory, and there is no such file in the expected + # ldso dir. + if [ -n "${ldso}" -a "${ldso_d}" != "${multilib_dir}" -a ! -r "${multi_root}${ldso}" ]; then + # Convert ldso_d to "how many levels we need to go up" and remove + # leading slash. + ldso_d=$( echo "${ldso_d#/}" | sed 's,[^/]\+,..,g' ) + CT_DoExecLog ALL ln -sf "${ldso_d}${multilib_dir}/${ldso_f}" \ + "${multi_root}${ldso}" + fi } # Initialises the .config file to sensible values diff --git a/scripts/functions b/scripts/functions index ef75e09e..f1dfd127 100644 --- a/scripts/functions +++ b/scripts/functions @@ -1366,25 +1366,6 @@ CT_DoBuildTargetTuple() { fi } -# This function determines the target tuple for a given set of compiler -# flags, using either GCC's multiarch feature (if supported; if not, -# GCC prints nothing and exits with status 0), falling back to calling -# the architecture-specific functions. -CT_DoMultilibTarget() { - local target_var="$1"; shift - local -a multi_flags=( "$@" ) - local gcc_multiarch - - gcc_multiarch=$( "${CT_TARGET}-gcc" -print-multiarch "${multi_flags[@]}" ) - if [ -n "${gcc_multiarch}" ]; then - eval "${target_var}=${gcc_multiarch}" - return - fi - - # Fall back to arch-specific guesswork - CT_DoArchMultilibTarget "${target_var}" "${multi_flags[@]}" -} - # This function does pause the build until the user strikes "Return" # Usage: CT_DoPause [optional_message] CT_DoPause() { @@ -1529,9 +1510,9 @@ CT_DoLoadState(){ # This function sets a kconfig option to a specific value in a .config file # Usage: CT_KconfigSetOption <option> <value> <file> CT_KconfigSetOption() { - option="$1" - value="$2" - file="$3" + local option="$1" + local value="$2" + local file="$3" ${grep} -E -q "^${option}=.*" "${file}" && \ ${sed} -i -r -e "s;^${option}=.*$;${option}=${value};" "${file}" || \ @@ -1543,8 +1524,8 @@ CT_KconfigSetOption() { # This function enables a kconfig option to '=y' in a .config file # Usage: CT_KconfigEnableOption <option> <file> CT_KconfigEnableOption() { - option="$1" - file="$2" + local option="$1" + local file="$2" CT_KconfigSetOption "${option}" "y" "${file}" } @@ -1552,8 +1533,8 @@ CT_KconfigEnableOption() { # This function disables a kconfig option in a .config file # Usage: CT_KconfigDisableOption <option> <file> CT_KconfigDisableOption() { - option="${1}" - file="${2}" + local option="${1}" + local file="${2}" ${grep} -E -q "^# ${option} is not set$" "${file}" || \ ${grep} -E -q "^${option}=.*$" "${file}" && \ @@ -1565,11 +1546,125 @@ CT_KconfigDisableOption() { # is set or commented out. # Usage: CT_KconfigDeleteOption <option> <file> CT_KconfigDeleteOption() { - option="${1}" - file="${2}" + local option="${1}" + local file="${2}" ${grep} -E -q "^# ${option} is not set$" "${file}" && \ ${sed} -i -r -e "/^# ${option} is not set$/d" "${file}" || \ ${grep} -E -q "^${option}=.*$" "${file}" && \ ${sed} -i -r -e "/^${option}=.*$/d" "${file}" || true } + +# Multilib iterator. The caller should be in a directory where the directories +# will be created, one per multilib, and the specified command will be run in +# each of them. The following arguments will be passed to the invoked command: +# multi_flags CFLAGS for this multilib +# multi_dir GCC internal library location for the multilib +# multi_os_dir OS library location for the multilib +# multi_root Sysroot for this multilib +# multi_target Target tuple, either as reported by GCC or by our guesswork +# multi_count Total number of multilibs +# multi_index Index of the current multilib +# Any additional arguments passed to this function will be forwarded to the called +# function as well. +# Usage: CT_IterateMultilibs <function> <prefix> <additional-args...> +CT_IterateMultilibs() { + local func="${1}" + local prefix="${2}" + local -a multilibs + local multi_dir multi_os_dir multi_root multi_flags multi_index multi_target + local root_suffix + + # Name used internally below + if [ "${prefix}" = "sysroot-check" ]; then + CT_Abort "Bad prefix used in CT_IterateMultilibs" + fi + + # Drop mandatory arguments + shift 2 + + # 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) ) + CT_DoExecLog ALL rm -rf "sysroot-check" + for multilib in "${multilibs[@]}"; do + # GCC makes the distinction between: + # multilib (-print-multi-lib or -print-multi-directory) and + # multilib-os (--print-multi-os-directory) + # as the gcc library and gcc sysroot library paths, respectively. + # For example, on x86_64: + # multilib: -m32=32 -m64=. + # multilib-os: -m32=../lib -m64=../lib64 + # Moreover, while some multilibs can coexist in the same sysroot (e.g. + # on x86), some have a "sysroot suffix" to separate incompatible variants. + # Such sysroot suffixes combine with multilib-os directories, e.g. + # on sh4 with -m4a multilib, the search order in sysroot is (dropping some + # directories for brevity: + # <sysroot>/m4a/lib/m4a/ + # <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-check${root_suffix}" + if [ -e "sysroot-check${root_suffix}/seen" ]; then + CT_DoExecLog ALL rm -f "sysroot-check${root_suffix}/unique" + else + CT_DoExecLog ALL touch "sysroot-check${root_suffix}/seen" \ + "sysroot-check${root_suffix}/unique" + fi + done + + # Now, actual iteration. + # This uses either GCC's multiarch feature (if supported; if not, + # GCC prints nothing and exits with status 0), falling back to calling + # the architecture-specific functions. + multi_index=1 + 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} ) + multi_target=$( "${CT_TARGET}-gcc" -print-multiarch ${multi_flags} ) + root_suffix="${multi_root#${CT_SYSROOT_DIR}}" + + # If GCC did not report the target tuple (i.e. this configuration is not + # multiarch-capable), fall back to our guesswork. + if [ -z "${multi_target}" ]; then + multi_target="${CT_TARGET}" + CT_DoArchMultilibTarget multi_target ${multi_flags} + fi + + # Avoid multi_os_dir if it's the only directory in this sysroot. + if [ -e "sysroot-check${root_suffix}/unique" ]; then + multi_os_dir=. + fi + + CT_mkdir_pushd "${prefix}_${multi_dir//\//_}" + $func multi_dir="${multi_dir}" \ + multi_os_dir="${multi_os_dir}" \ + multi_flags="${multi_flags}" \ + multi_root="${multi_root}" \ + multi_target="${multi_target}" \ + multi_index="${multi_index}" \ + multi_count="${#multilibs[@]}" \ + "$@" + CT_Popd + multi_index=$((multi_index+1)) + done +} |