diff options
Diffstat (limited to 'toolchain')
-rw-r--r-- | toolchain/external-toolchain/ext-tool.mk | 109 |
1 files changed, 90 insertions, 19 deletions
diff --git a/toolchain/external-toolchain/ext-tool.mk b/toolchain/external-toolchain/ext-tool.mk index 449328131..2c2562cde 100644 --- a/toolchain/external-toolchain/ext-tool.mk +++ b/toolchain/external-toolchain/ext-tool.mk @@ -1,7 +1,13 @@ + # # This file implements the support for external toolchains, i.e # toolchains that have not been produced by Buildroot itself and that -# are already available on the system on which Buildroot runs. +# are already available on the system on which Buildroot runs. So far, +# we have tested this with: +# +# * Toolchains generated by Crosstool-NG +# * Toolchains generated by Buildroot +# * ARM toolchains made available by Codesourcery # # The basic principle is the following # @@ -34,38 +40,39 @@ # directory to the target directory. Also optionaly strips the # library. # -# $1: sysroot directory +# $1: arch specific sysroot directory # $2: library name # $3: destination directory # $4: strip (y|n), default is to strip # copy_toolchain_lib_root = \ - SYSROOT_DIR="$(strip $1)"; \ + ARCH_SYSROOT_DIR="$(strip $1)"; \ LIB="$(strip $2)"; \ - DST="$(strip $3)"; \ STRIP="$(strip $4)"; \ \ - LIB_DIR="$${SYSROOT_DIR}/lib" ; \ - for FILE in `find $${LIB_DIR} -maxdepth 1 -name "$${LIB}.*"`; do \ + LIBS=`(cd $${ARCH_SYSROOT_DIR}; find . -path "./lib/$${LIB}.*" -o -path "./usr/lib/$${LIB}.*")` ; \ + for FILE in $${LIBS} ; do \ LIB=`basename $${FILE}`; \ + LIBDIR=`dirname $${FILE}` ; \ while test \! -z "$${LIB}"; do \ - rm -fr $(TARGET_DIR)$${DST}/$${LIB}; \ - mkdir -p $(TARGET_DIR)$${DST}; \ - if test -h $${LIB_DIR}/$${LIB}; then \ - cp -d $${LIB_DIR}/$${LIB} $(TARGET_DIR)$${DST}/; \ - elif test -f $${LIB_DIR}/$${LIB}; then \ - $(INSTALL) -D -m0755 $${LIB_DIR}/$${LIB} $(TARGET_DIR)$${DST}/$${LIB}; \ + FULLPATH="$${ARCH_SYSROOT_DIR}/$${LIBDIR}/$${LIB}" ; \ + rm -fr $(TARGET_DIR)/$${LIBDIR}/$${LIB}; \ + mkdir -p $(TARGET_DIR)/$${LIBDIR}; \ + if test -h $${FULLPATH} ; then \ + cp -d $${FULLPATH} $(TARGET_DIR)/$${LIBDIR}/; \ + elif test -f $${FULLPATH}; then \ + $(INSTALL) -D -m0755 $${FULLPATH} $(TARGET_DIR)/$${LIBDIR}/$${LIB}; \ case "$${STRIP}" in \ (0 | n | no) \ ;; \ (*) \ - $(TARGET_CROSS)strip "$(TARGET_DIR)$${DST}/$${LIB}"; \ + $(TARGET_CROSS)strip "$(TARGET_DIR)/$${LIBDIR}/$${LIB}"; \ ;; \ esac; \ else \ exit -1; \ fi; \ - LIB="`readlink $${LIB_DIR}/$${LIB}`"; \ + LIB="`readlink $${FULLPATH}`"; \ done; \ done; \ \ @@ -73,13 +80,54 @@ copy_toolchain_lib_root = \ # # Copy the full external toolchain sysroot directory to the staging -# dir +# dir. The operation of this function is rendered a little bit +# complicated by the support for multilib toolchains. # -# $1: sysroot directory +# We start by copying etc, lib, sbin and usr from the sysroot of the +# selected architecture variant (as pointed by ARCH_SYSROOT_DIR). This +# allows to import into the staging directory the C library and +# companion libraries for the correct architecture variant. We +# explictly only copy etc, lib, sbin and usr since other directories +# might exist for other architecture variants (on Codesourcery +# toolchain, the sysroot for the default architecture variant contains +# the armv4t and thumb2 subdirectories, which are the sysroot for the +# corresponding architecture variants), and we don't want to import +# them. +# +# Then, if the selected architecture variant is not the default one +# (i.e, if SYSROOT_DIR != ARCH_SYSROOT_DIR), then we : +# +# * Import the header files from the default architecture +# variant. Header files are typically shared between the sysroots +# for the different architecture variants. If we use the +# non-default one, header files were not copied by the previous +# step, so we copy them here from the sysroot of the default +# architecture variant. +# +# * Create a symbolic link that matches the name of the subdirectory +# for the architecture variant in the original sysroot. This is +# required as the compiler will by default look in +# sysroot_dir/arch_variant/ for libraries and headers, when the +# non-default architecture variant is used. Without this, the +# compiler fails to find libraries and headers. +# +# $1: main sysroot directory of the toolchain +# $2: arch specific sysroot directory of the toolchain +# $3: arch specific subdirectory in the sysroot # copy_toolchain_sysroot = \ SYSROOT_DIR="$(strip $1)"; \ - cp -a $${SYSROOT_DIR}/* $(STAGING_DIR)/ ; \ + ARCH_SYSROOT_DIR="$(strip $2)"; \ + ARCH_SUBDIR="$(strip $3)"; \ + for i in etc lib sbin usr ; do \ + cp -a $${ARCH_SYSROOT_DIR}/$$i $(STAGING_DIR)/ ; \ + done ; \ + if [ `readlink -f $${SYSROOT_DIR}` != `readlink -f $${ARCH_SYSROOT_DIR}` ] ; then \ + if [ ! -d $${ARCH_SYSROOT_DIR}/usr/include ] ; then \ + cp -a $${SYSROOT_DIR}/usr/include $(STAGING_DIR)/usr ; \ + fi ; \ + ln -s . $(STAGING_DIR)/$(ARCH_SUBDIR) ; \ + fi ; \ find $(STAGING_DIR) -type d | xargs chmod 755 # @@ -205,7 +253,30 @@ ifeq ($(BR2_INSTALL_LIBSTDCPP),y) EXTERNAL_LIBS+=libstdc++.so endif +# SYSROOT_DIR selection. We first try the -print-sysroot option, +# available in gcc 4.4.x and in some Codesourcery toolchains. If this +# option is not available, we fallback to the value of --with-sysroot +# as visible in CROSS-gcc -v. We don't pass the -march= option to gcc +# as we want the "main" sysroot, which contains all variants of the C +# library in the case of multilib toolchains. +SYSROOT_DIR=$(shell $(TARGET_CC) -print-sysroot 2>/dev/null) +ifeq ($(SYSROOT_DIR),) SYSROOT_DIR=$(shell readlink -f $$(LANG=C $(TARGET_CC) -print-file-name=libc.a |sed -r -e 's:usr/lib/libc\.a::;')) +endif + +# Now, find if the toolchain specifies a sub-directory for the +# specific architecture variant we're interested in. This is the case +# with multilib toolchain, when the selected architecture variant is +# not the default one. To do so, we ask the compiler by passing the +# appropriate -march= flags. ARCH_SUBDIR will contain the +# subdirectory, in the main SYSROOT_DIR, that corresponds to the +# selected architecture variant. ARCH_SYSROOT_DIR will contain the +# full path to this location. +ifneq ($(CC_TARGET_ARCH_),) +TARGET_CC_ARCH_CFLAGS+=-march=$(CC_TARGET_ARCH_) +endif +ARCH_SUBDIR=$(shell $(TARGET_CC) $(TARGET_CC_ARCH_CFLAGS) -print-multi-directory) +ARCH_SYSROOT_DIR=$(SYSROOT_DIR)/$(ARCH_SUBDIR) $(STAMP_DIR)/ext-toolchain-installed: @echo "Checking external toolchain settings" @@ -225,8 +296,8 @@ endif mkdir -p $(TARGET_DIR)/lib @echo "Copy external toolchain libraries to target..." $(Q)for libs in $(EXTERNAL_LIBS); do \ - $(call copy_toolchain_lib_root,$(SYSROOT_DIR),$$libs,/lib,$(BR2_TOOLCHAIN_EXTERNAL_STRIP)); \ + $(call copy_toolchain_lib_root,$(ARCH_SYSROOT_DIR),$$libs,$(BR2_TOOLCHAIN_EXTERNAL_STRIP)); \ done @echo "Copy external toolchain sysroot to staging..." - $(Q)$(call copy_toolchain_sysroot,$(SYSROOT_DIR)) + $(Q)$(call copy_toolchain_sysroot,$(SYSROOT_DIR),$(ARCH_SYSROOT_DIR),$(ARCH_SUBDIR)) @touch $@ |