mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2024-12-19 12:57:53 +00:00
First stab at multilib/uClibc.
Create a separate 'libc_backend_once', install headers into a subdirectory (different sets of headers are installed for 32- and 64-bit architectures), and create a symlink for the dynamic linker location expected by GCC. Signed-off-by: Alexey Neyman <stilor@att.net>
This commit is contained in:
parent
bf3eceb5d9
commit
f2ffdf798d
@ -29,11 +29,33 @@ CT_DoArchUClibcSelectArch() {
|
||||
}
|
||||
|
||||
# uClibc: Adjust configuration file according to the CT-NG configuration
|
||||
# Usage CT_DoArchUClibcConfig <config-file>
|
||||
# Usage: CT_DoArchUClibcConfig <config-file>
|
||||
CT_DoArchUClibcConfig() {
|
||||
CT_DoLog WARN "Support for '${CT_ARCH}' is not implemented in uClibc config tweaker."
|
||||
CT_DoLog WARN "Exact configuration file must be provided."
|
||||
}
|
||||
|
||||
# Multilib/uClibc: Adjust configuration file for given CFLAGS
|
||||
# Usage: CT_DoArchUClibcCflags <config-file> <cflags>
|
||||
CT_DoArchUClibcCflags() {
|
||||
local cfg="${1}"
|
||||
local cflags="${2}"
|
||||
|
||||
# Likely, any non-default cflags need to be reflected into the config.
|
||||
# It may work if we just pass them into EXTRA_CFLAGS, but we have no
|
||||
# idea as they might interact with the CFLAGS inferred by uClibc from
|
||||
# the configuration file.
|
||||
if [ "${cflags}" != "" ]; then
|
||||
CT_DoLog WARN "Multilib configuration not supported for uClibc/${CT_ARCH}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Multilib/uClibc: Adjust header installation path for given CFLAGS
|
||||
# Usage: CT_DoArchUClibcHeaderDir <path-variable> <cflags>
|
||||
CT_DoArchUClibcHeaderDir() {
|
||||
# Only needed if a given architecture may select different uClibc architectures.
|
||||
:;
|
||||
}
|
||||
|
||||
# Override from the actual arch implementation as needed.
|
||||
. "${CT_LIB_DIR}/scripts/build/arch/${CT_ARCH}.sh"
|
||||
|
@ -27,7 +27,6 @@ CT_DoArchTupleValues() {
|
||||
thumb)
|
||||
CT_ARCH_CC_CORE_EXTRA_CONFIG="--with-mode=thumb"
|
||||
CT_ARCH_CC_EXTRA_CONFIG="--with-mode=thumb"
|
||||
# CT_ARCH_TARGET_CFLAGS="-mthumb"
|
||||
;;
|
||||
esac
|
||||
|
||||
@ -38,6 +37,23 @@ CT_DoArchTupleValues() {
|
||||
if [ "${CT_ARCH_ARM_TUPLE_USE_EABIHF}" = "y" ]; then
|
||||
CT_TARGET_SYS="${CT_TARGET_SYS}hf"
|
||||
fi
|
||||
|
||||
# If building multilib, zero out any WITH_*/*_CFLAG - GCC on ARM does not allow
|
||||
# any of them with multilib.
|
||||
if [ "${CT_MULTILIB}" = "y" ]; then
|
||||
CT_ARCH_WITH_ARCH=
|
||||
CT_ARCH_WITH_ABI=
|
||||
CT_ARCH_WITH_CPU=
|
||||
CT_ARCH_WITH_TUNE=
|
||||
CT_ARCH_WITH_FPU=
|
||||
CT_ARCH_WITH_FLOAT=
|
||||
CT_ARCH_ARCH_CFLAG=
|
||||
CT_ARCH_ABI_CFLAG=
|
||||
CT_ARCH_CPU_CFLAG=
|
||||
CT_ARCH_TUNE_CFLAG=
|
||||
CT_ARCH_FPU_CFLAG=
|
||||
CT_ARCH_FLOAT_CFLAG=
|
||||
fi
|
||||
}
|
||||
|
||||
CT_DoArchUClibcConfig() {
|
||||
@ -45,6 +61,15 @@ CT_DoArchUClibcConfig() {
|
||||
|
||||
CT_DoArchUClibcSelectArch "${cfg}" "arm"
|
||||
|
||||
case "${CT_ARCH_ARM_MODE}" in
|
||||
arm)
|
||||
CT_KconfigDisableOption "COMPILE_IN_THUMB_MODE" "${cfg}"
|
||||
;;
|
||||
thumb)
|
||||
CT_KconfigEnableOption "COMPILE_IN_THUMB_MODE" "${cfg}"
|
||||
;;
|
||||
esac
|
||||
|
||||
# FIXME: CONFIG_ARM_OABI does not exist in neither uClibc/uClibc-ng
|
||||
# FIXME: CONFIG_ARM_EABI does not seem to affect anything in either of them, too
|
||||
# (both check the compiler's built-in define, __ARM_EABI__ instead) except for
|
||||
@ -58,3 +83,38 @@ CT_DoArchUClibcConfig() {
|
||||
CT_KconfigEnableOption "CONFIG_ARM_OABI" "${cfg}"
|
||||
fi
|
||||
}
|
||||
|
||||
CT_DoArchUClibcCflags() {
|
||||
local cfg="${1}"
|
||||
local cflags="${2}"
|
||||
local f
|
||||
|
||||
for f in ${cflags}; do
|
||||
case "${f}" in
|
||||
-mthumb)
|
||||
CT_KconfigEnableOption "COMPILE_IN_THUMB_MODE" "${cfg}"
|
||||
;;
|
||||
-marm)
|
||||
CT_KconfigDisableOption "COMPILE_IN_THUMB_MODE" "${cfg}"
|
||||
;;
|
||||
-mlittle-endian)
|
||||
CT_KconfigDisableOption "ARCH_BIG_ENDIAN" "${cfg}"
|
||||
CT_KconfigDisableOption "ARCH_WANTS_BIG_ENDIAN" "${cfg}"
|
||||
CT_KconfigEnableOption "ARCH_LITTLE_ENDIAN" "${cfg}"
|
||||
CT_KconfigEnableOption "ARCH_WANTS_LITTLE_ENDIAN" "${cfg}"
|
||||
;;
|
||||
-mbig-endian)
|
||||
CT_KconfigEnableOption "ARCH_BIG_ENDIAN" "${cfg}"
|
||||
CT_KconfigEnableOption "ARCH_WANTS_BIG_ENDIAN" "${cfg}"
|
||||
CT_KconfigDisableOption "ARCH_LITTLE_ENDIAN" "${cfg}"
|
||||
CT_KconfigDisableOption "ARCH_WANTS_LITTLE_ENDIAN" "${cfg}"
|
||||
;;
|
||||
-mhard-float|-mfloat-abi=hard|-mfloat-abi=softfp)
|
||||
CT_KconfigEnableOption "UCLIBC_HAS_FPU" "${cfg}"
|
||||
;;
|
||||
-msoft-float|-mfloat-abi=soft)
|
||||
CT_KconfigDisableOption "UCLIBC_HAS_FPU" "${cfg}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
@ -47,3 +47,25 @@ CT_DoArchUClibcConfig() {
|
||||
CT_KconfigDeleteOption "CONFIG_MIPS_ISA_MIPS64" "${cfg}"
|
||||
CT_KconfigDeleteOption "CONFIG_MIPS_ISA_MIPS64R2" "${cfg}"
|
||||
}
|
||||
|
||||
CT_DoArchUClibcCflags() {
|
||||
local cfg="${1}"
|
||||
local cflags="${2}"
|
||||
local f
|
||||
|
||||
for f in ${cflags}; do
|
||||
case "${f}" in
|
||||
-mabi=*)
|
||||
CT_KconfigDisableOption "CONFIG_MIPS_O32_ABI" "${cfg}"
|
||||
CT_KconfigDisableOption "CONFIG_MIPS_N32_ABI" "${cfg}"
|
||||
CT_KconfigDisableOption "CONFIG_MIPS_N64_ABI" "${cfg}"
|
||||
case "${f#-mabi=}" in
|
||||
32) CT_KconfigEnableOption "CONFIG_MIPS_O32_ABI" "${cfg}";;
|
||||
n32) CT_KconfigEnableOption "CONFIG_MIPS_N32_ABI" "${cfg}";;
|
||||
64) CT_KconfigEnableOption "CONFIG_MIPS_N64_ABI" "${cfg}";;
|
||||
*) CT_Abort "Unsupported ABI: ${f#-mabi=}";;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
@ -130,3 +130,40 @@ CT_DoArchUClibcConfig() {
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
CT_DoArchUClibcCflags() {
|
||||
local cfg="${1}"
|
||||
local cflags="${2}"
|
||||
local f
|
||||
|
||||
for f in ${cflags}; do
|
||||
case "${f}" in
|
||||
-m64)
|
||||
CT_DoArchUClibcSelectArch "${cfg}" "x86_64"
|
||||
;;
|
||||
-m32)
|
||||
# Since it's a part of multilib with 64-bit flavor, default
|
||||
# to new architecture (i686).
|
||||
CT_DoArchUClibcSelectArch "${cfg}" "i386"
|
||||
CT_KconfigDisableOption "CONFIG_386" "${cfg}"
|
||||
CT_KconfigDisableOption "CONFIG_486" "${cfg}"
|
||||
CT_KconfigDisableOption "CONFIG_586" "${cfg}"
|
||||
CT_KconfigEnableOption "CONFIG_686" "${cfg}"
|
||||
;;
|
||||
-mx32)
|
||||
CT_Abort "uClibc does not support x32 ABI"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
CT_DoArchUClibcHeaderDir() {
|
||||
local dir_var="${1}"
|
||||
local cflags="${2}"
|
||||
|
||||
# If it is non-default multilib, add a suffix with architecture (reported by gcc)
|
||||
# to the headers installation path.
|
||||
if [ -n "${cflags}" ]; then
|
||||
eval "${dir_var}="$( ${CT_TARGET}-gcc -print-multiarch ${cflags} )
|
||||
fi
|
||||
}
|
||||
|
@ -63,12 +63,13 @@ do_libc() {
|
||||
do_libc_backend libc_mode=final
|
||||
}
|
||||
|
||||
# Common backend for 1st and 2nd passes
|
||||
# Common backend for 1st and 2nd passes.
|
||||
do_libc_backend() {
|
||||
local libc_mode
|
||||
local multi_os_dir multi_root multilib_dir startfiles_dir
|
||||
local jflag=${CT_LIBC_UCLIBC_PARALLEL:+${JOBSFLAGS}}
|
||||
local -a make_args
|
||||
local -a multilibs
|
||||
local multilib
|
||||
local multi_dir multi_os_dir multi_flags
|
||||
local ldso ldso_f ldso_d multilib_dir
|
||||
|
||||
for arg in "$@"; do
|
||||
eval "${arg// /\\ }"
|
||||
@ -80,14 +81,86 @@ do_libc_backend() {
|
||||
*) CT_Abort "Unsupported (or unset) libc_mode='${libc_mode}'";;
|
||||
esac
|
||||
|
||||
# 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} )
|
||||
|
||||
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
|
||||
|
||||
if [ "${libc_mode}" = "final" -a "${CT_SHARED_LIBS}" = "y" ]; then
|
||||
# uClibc and GCC disagree where the dynamic linker lives. uClibc always
|
||||
# places it in the MULTILIB_DIR, while gcc does that for *some* variants
|
||||
# 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
|
||||
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} )
|
||||
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 | \
|
||||
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_Popd
|
||||
fi
|
||||
|
||||
CT_EndStep
|
||||
}
|
||||
|
||||
# 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 jflag=${CT_LIBC_UCLIBC_PARALLEL:+${JOBSFLAGS}}
|
||||
local -a make_args
|
||||
local build_dir
|
||||
local extra_cflags f cfg_cflags cf
|
||||
local hdr_install_subdir
|
||||
|
||||
for arg in "$@"; do
|
||||
eval "${arg// /\\ }"
|
||||
done
|
||||
|
||||
# Simply copy files until uClibc has the ability to build out-of-tree
|
||||
CT_DoLog EXTRA "Copying sources to build dir"
|
||||
CT_DoExecLog ALL cp -a "${CT_SRC_DIR}/${uclibc_name}-${CT_LIBC_VERSION}" \
|
||||
"${CT_BUILD_DIR}/build-libc-${libc_mode}"
|
||||
cd "${CT_BUILD_DIR}/build-libc-${libc_mode}"
|
||||
build_dir="${CT_BUILD_DIR}/build-libc-${libc_mode}${multi_dir//\//_}"
|
||||
CT_DoExecLog ALL cp -a "${CT_SRC_DIR}/${uclibc_name}-${CT_LIBC_VERSION}" "${build_dir}"
|
||||
cd "${build_dir}"
|
||||
|
||||
multi_os_dir=$( "${CT_TARGET}-gcc" -print-multi-os-directory )
|
||||
multi_root=$( "${CT_TARGET}-gcc" -print-sysroot )
|
||||
multilib_dir="lib/${multi_os_dir}"
|
||||
startfiles_dir="${multi_root}/usr/${multilib_dir}"
|
||||
CT_SanitizeVarDir multilib_dir startfiles_dir
|
||||
@ -103,7 +176,6 @@ do_libc_backend() {
|
||||
# - We do _not_ want to strip anything for now, in case we specifically
|
||||
# asked for a debug toolchain, thus the STRIPTOOL= assignment.
|
||||
make_args=( CROSS_COMPILE="${CT_TARGET}-" \
|
||||
UCLIBC_EXTRA_CFLAGS="-pipe" \
|
||||
PREFIX="${multi_root}/" \
|
||||
MULTILIB_DIR="${multilib_dir}" \
|
||||
LOCALE_DATA_FILENAME="${uclibc_locale_tarball}.tgz" \
|
||||
@ -120,10 +192,45 @@ do_libc_backend() {
|
||||
CT_LIBC_UCLIBC_CONFIG_FILE="${CT_LIB_DIR}/contrib/uClibc-defconfigs/${uclibc_name}.config"
|
||||
fi
|
||||
|
||||
manage_uClibc_config "${CT_LIBC_UCLIBC_CONFIG_FILE}" .config
|
||||
|
||||
manage_uClibc_config "${CT_LIBC_UCLIBC_CONFIG_FILE}" .config "${multi_flags}"
|
||||
CT_DoYes | CT_DoExecLog ALL ${make} "${make_args[@]}" oldconfig
|
||||
|
||||
# Now filter the multilib flags. manage_uClibc_config did the opposite of
|
||||
# what Rules.mak in uClibc would do: by the multilib's CFLAGS, it determined
|
||||
# the applicable configuration options. We don't want to pass the same options
|
||||
# in the UCLIBC_EXTRA_CFLAGS again (on some targets, the options do not correctly
|
||||
# override each other). On the other hand, we do not want to lose the options
|
||||
# that are not reflected in the .config.
|
||||
extra_cflags="-pipe"
|
||||
{ echo "include Rules.mak"; echo "show-cpu-flags:"; printf '\t@echo $(CPU_CFLAGS)\n'; } \
|
||||
> .show-cpu-cflags.mk
|
||||
cfg_cflags=$( ${make} "${make_args[@]}" \
|
||||
--no-print-directory -f .show-cpu-cflags.mk show-cpu-flags )
|
||||
CT_DoExecLog ALL rm -f .show-cpu-cflags.mk
|
||||
CT_DoLog DEBUG "CPU_CFLAGS detected by uClibc: ${cfg_cflags[@]}"
|
||||
for f in ${multi_flags}; do
|
||||
for cf in ${cfg_cflags}; do
|
||||
if [ "${f}" = "${cf}" ]; then
|
||||
f=
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "${f}" ]; then
|
||||
extra_cflags+=" ${f}"
|
||||
fi
|
||||
done
|
||||
CT_DoLog DEBUG "Filtered multilib CFLAGS: ${extra_cflags}"
|
||||
make_args+=( UCLIBC_EXTRA_CFLAGS="${extra_cflags}" )
|
||||
|
||||
# uClibc does not have a way to select the installation subdirectory for headers,
|
||||
# it is always $(DEVEL_PREFIX)/include. Also, we're reinstalling the headers
|
||||
# at the final stage (see the note below), we may already have the subdirectory
|
||||
# in /usr/include.
|
||||
CT_DoArchUClibcHeaderDir hdr_install_subdir "${multi_flags}"
|
||||
if [ -n "$hdr_install_subdir" ]; then
|
||||
CT_DoExecLog ALL cp -a "${multi_root}/usr/include" "${multi_root}/usr/include.saved"
|
||||
fi
|
||||
|
||||
if [ "${libc_mode}" = "startfiles" ]; then
|
||||
CT_DoLog EXTRA "Building headers"
|
||||
CT_DoExecLog ALL ${make} "${make_args[@]}" headers
|
||||
@ -146,7 +253,7 @@ do_libc_backend() {
|
||||
# No problem to create it for other archs.
|
||||
CT_DoLog EXTRA "Building dummy shared libs"
|
||||
CT_DoExecLog ALL "${CT_TARGET}-gcc" -nostdlib -nostartfiles \
|
||||
-shared -x c /dev/null -o libdummy.so
|
||||
-shared ${multi_flags} -x c /dev/null -o libdummy.so
|
||||
|
||||
CT_DoLog EXTRA "Installing start files"
|
||||
CT_DoExecLog ALL ${install} -m 0644 lib/crt1.o lib/crti.o lib/crtn.o \
|
||||
@ -182,7 +289,14 @@ do_libc_backend() {
|
||||
CT_DoExecLog ALL ${make} "${make_args[@]}" install
|
||||
fi # libc_mode == final
|
||||
|
||||
CT_EndStep
|
||||
# Now, if installing headers into a subdirectory, put everything in its place.
|
||||
# Remove the header subdirectory if it existed already.
|
||||
if [ -n "$hdr_install_subdir" ]; then
|
||||
CT_DoExecLog ALL mv "${multi_root}/usr/include" "${multi_root}/usr/include.new"
|
||||
CT_DoExecLog ALL mv "${multi_root}/usr/include.saved" "${multi_root}/usr/include"
|
||||
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
|
||||
}
|
||||
|
||||
# Initialises the .config file to sensible values
|
||||
@ -191,6 +305,7 @@ do_libc_backend() {
|
||||
manage_uClibc_config() {
|
||||
src="$1"
|
||||
dst="$2"
|
||||
flags="$3"
|
||||
|
||||
# Start with fresh files
|
||||
CT_DoExecLog ALL cp "${src}" "${dst}"
|
||||
@ -364,6 +479,7 @@ manage_uClibc_config() {
|
||||
|
||||
# Now allow architecture to tweak as it wants
|
||||
CT_DoArchUClibcConfig "${dst}"
|
||||
CT_DoArchUClibcCflags "${dst}" "${flags}"
|
||||
}
|
||||
|
||||
do_libc_post_cc() {
|
||||
|
Loading…
Reference in New Issue
Block a user