Explorar o código

Add toolchain wrapper for external toolchains

Add a simple toolchain wrapper for external toolchains, which forces the
correct sysroot/march/mtune/floating point options needed to use it
with buildroot.

With this in place the external toolchain behaves similar to the internal
ones, and the special handling can be removed. This also means that the
toolchain is usable outside buildroot without having to pass any special
compiler flags.

Also adjust the downloadable external toolchain support to install under
HOST_DIR so it can be used after the temporary build files are removed.

Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Peter Korsgaard %!s(int64=14) %!d(string=hai) anos
pai
achega
85dc57f6fd

+ 1 - 3
Makefile

@@ -284,7 +284,6 @@ STAMP_DIR:=$(BASE_DIR)/stamps
 BINARIES_DIR:=$(BASE_DIR)/images
 BINARIES_DIR:=$(BASE_DIR)/images
 TARGET_DIR:=$(BASE_DIR)/target
 TARGET_DIR:=$(BASE_DIR)/target
 TOOLCHAIN_DIR=$(BASE_DIR)/toolchain
 TOOLCHAIN_DIR=$(BASE_DIR)/toolchain
-TOOLCHAIN_EXTERNAL_DIR=$(BASE_DIR)/external-toolchain
 TARGET_SKELETON=$(TOPDIR)/fs/skeleton
 TARGET_SKELETON=$(TOPDIR)/fs/skeleton
 
 
 BR2_DEPENDS_DIR=$(BUILD_DIR)/buildroot-config
 BR2_DEPENDS_DIR=$(BUILD_DIR)/buildroot-config
@@ -625,8 +624,7 @@ endif
 
 
 clean:
 clean:
 	rm -rf $(STAGING_DIR) $(TARGET_DIR) $(BINARIES_DIR) $(HOST_DIR) \
 	rm -rf $(STAGING_DIR) $(TARGET_DIR) $(BINARIES_DIR) $(HOST_DIR) \
-		$(STAMP_DIR) $(BUILD_DIR) $(TOOLCHAIN_DIR) $(BASE_DIR)/staging \
-		$(TOOLCHAIN_EXTERNAL_DIR)
+		$(STAMP_DIR) $(BUILD_DIR) $(TOOLCHAIN_DIR) $(BASE_DIR)/staging
 
 
 distclean: clean
 distclean: clean
 ifeq ($(DL_DIR),$(TOPDIR)/dl)
 ifeq ($(DL_DIR),$(TOPDIR)/dl)

+ 1 - 11
package/Makefile.in

@@ -103,18 +103,8 @@ TARGET_SYSROOT_OPT=--sysroot=$(STAGING_DIR)
 
 
 ifeq ($(BR2_TOOLCHAIN_BUILDROOT)$(BR2_TOOLCHAIN_CTNG),y)
 ifeq ($(BR2_TOOLCHAIN_BUILDROOT)$(BR2_TOOLCHAIN_CTNG),y)
 TARGET_CROSS=$(HOST_DIR)/usr/bin/$(REAL_GNU_TARGET_NAME)-
 TARGET_CROSS=$(HOST_DIR)/usr/bin/$(REAL_GNU_TARGET_NAME)-
-else ifeq ($(BR2_TOOLCHAIN_EXTERNAL),y)
-TOOLCHAIN_EXTERNAL_PREFIX=$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PREFIX))
-ifeq ($(BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD),y)
-TOOLCHAIN_EXTERNAL_LOCATION=$(TOOLCHAIN_EXTERNAL_DIR)
 else
 else
-TOOLCHAIN_EXTERNAL_LOCATION=$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PATH))
-endif
-ifneq ($(TOOLCHAIN_EXTERNAL_LOCATION),)
-TARGET_CROSS=$(TOOLCHAIN_EXTERNAL_LOCATION)/bin/$(TOOLCHAIN_EXTERNAL_PREFIX)-
-else
-TARGET_CROSS=$(TOOLCHAIN_EXTERNAL_PREFIX)-
-endif
+TARGET_CROSS=$(HOST_DIR)/usr/bin/$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PREFIX))-
 endif
 endif
 
 
 # Quotes are needed for spaces et al in path components.
 # Quotes are needed for spaces et al in path components.

+ 77 - 7
toolchain/toolchain-external/ext-tool.mk

@@ -41,8 +41,16 @@
 #  packages when using external toolchains. So in the end, only the
 #  packages when using external toolchains. So in the end, only the
 #  cross-compiler binaries remains external, all libraries and headers
 #  cross-compiler binaries remains external, all libraries and headers
 #  are imported into the Buildroot tree.
 #  are imported into the Buildroot tree.
+#
+#  4. Build a toolchain wrapper which executes the external toolchain
+#  with a number of arguments (sysroot/march/mtune/..) hardcoded,
+#  so we're sure the correct configuration is always used and the
+#  toolchain behaves similar to an internal toolchain.
+#  This toolchain wrapper and symlinks are installed into
+#  $(HOST_DIR)/usr/bin like for the internal toolchains, and the rest
+#  of Buildroot is handled identical for the 2 toolchain types.
 
 
-uclibc: dependencies $(STAMP_DIR)/ext-toolchain-installed
+uclibc: dependencies $(HOST_DIR)/usr/bin/ext-toolchain-wrapper
 
 
 LIB_EXTERNAL_LIBS=ld*.so libc.so libcrypt.so libdl.so libgcc_s.so libm.so libnsl.so libresolv.so librt.so libutil.so
 LIB_EXTERNAL_LIBS=ld*.so libc.so libcrypt.so libdl.so libgcc_s.so libm.so libnsl.so libresolv.so librt.so libutil.so
 ifeq ($(BR2_TOOLCHAIN_EXTERNAL_GLIBC),y)
 ifeq ($(BR2_TOOLCHAIN_EXTERNAL_GLIBC),y)
@@ -97,7 +105,51 @@ endif # ! no threads
 # present in the main sysroot, and only the libraries are available in
 # present in the main sysroot, and only the libraries are available in
 # each variant-specific sysroot directory.
 # each variant-specific sysroot directory.
 
 
-TARGET_CC_NO_SYSROOT=$(filter-out --sysroot=%,$(TARGET_CC_NOCCACHE))
+
+TOOLCHAIN_EXTERNAL_PREFIX=$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PREFIX))
+ifeq ($(BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD),y)
+TOOLCHAIN_EXTERNAL_DIR=$(HOST_DIR)/opt/ext-toolchain
+else
+TOOLCHAIN_EXTERNAL_DIR=$(call qstrip,$(BR2_TOOLCHAIN_EXTERNAL_PATH))
+endif
+
+ifeq ($(TOOLCHAIN_EXTERNAL_DIR),)
+# if no path set, figure it out from path
+TOOLCHAIN_EXTERNAL_BIN:=$(shell dirname $(shell which $(TOOLCHAIN_EXTERNAL_PREFIX)-gcc))
+else
+TOOLCHAIN_EXTERNAL_BIN:=$(TOOLCHAIN_EXTERNAL_DIR)/bin
+endif
+
+TOOLCHAIN_EXTERNAL_CROSS=$(TOOLCHAIN_EXTERNAL_BIN)/$(TOOLCHAIN_EXTERNAL_PREFIX)-
+TOOLCHAIN_EXTERNAL_CC=$(TOOLCHAIN_EXTERNAL_CROSS)gcc
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS = \
+	-DBR_CROSS_PATH='"$(TOOLCHAIN_EXTERNAL_BIN)/"' \
+	-DBR_SYSROOT='"$(STAGING_DIR)"'
+
+# march/mtune/floating point mode needs to be passed to the external toolchain
+# to select the right multilib variant
+ifneq ($(CC_TARGET_TUNE_),)
+TOOLCHAIN_EXTERNAL_CFLAGS += -mtune=$(CC_TARGET_TUNE_)
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_TUNE='"$(CC_TARGET_TUNE_)"'
+endif
+ifneq ($(CC_TARGET_ARCH_),)
+TOOLCHAIN_EXTERNAL_CFLAGS += -march=$(CC_TARGET_ARCH_)
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ARCH='"$(CC_TARGET_ARCH_)"'
+endif
+ifneq ($(CC_TARGET_ABI_),)
+TOOLCHAIN_EXTERNAL_CFLAGS += -mabi=$(CC_TARGET_ABI_)
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ABI='"$(CC_TARGET_ABI_)"'
+endif
+
+ifeq ($(BR2_SOFT_FLOAT),y)
+TOOLCHAIN_EXTERNAL_CFLAGS += -msoft-float
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_SOFTFLOAT=1
+endif
+
+ifeq ($(BR2_VFP_FLOAT),y)
+TOOLCHAIN_EXTERNAL_CFLAGS += -mfpu=vfp
+TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_VFPFLOAT=1
+endif
 
 
 ifeq ($(BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD),y)
 ifeq ($(BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD),y)
 TOOLCHAIN_EXTERNAL_DEPENDENCIES = $(TOOLCHAIN_EXTERNAL_DIR)/.extracted
 TOOLCHAIN_EXTERNAL_DEPENDENCIES = $(TOOLCHAIN_EXTERNAL_DIR)/.extracted
@@ -146,9 +198,9 @@ $(TOOLCHAIN_EXTERNAL_DIR)/.extracted: $(DL_DIR)/$(TOOLCHAIN_EXTERNAL_SOURCE)
 $(STAMP_DIR)/ext-toolchain-checked:
 $(STAMP_DIR)/ext-toolchain-checked:
 	@echo "Checking external toolchain settings"
 	@echo "Checking external toolchain settings"
 	$(Q)$(call check_cross_compiler_exists)
 	$(Q)$(call check_cross_compiler_exists)
-	$(Q)SYSROOT_DIR=`$(TARGET_CC_NO_SYSROOT) -print-sysroot 2>/dev/null` ; \
+	$(Q)SYSROOT_DIR=`$(TOOLCHAIN_EXTERNAL_CC) -print-sysroot 2>/dev/null` ; \
 	if test -z "$${SYSROOT_DIR}" ; then \
 	if test -z "$${SYSROOT_DIR}" ; then \
-		SYSROOT_DIR=`readlink -f $$(LANG=C $(TARGET_CC_NO_SYSROOT) -print-file-name=libc.a) |sed -r -e 's:usr/lib/libc\.a::;'` ; \
+		SYSROOT_DIR=`readlink -f $$(LANG=C $(TOOLCHAIN_EXTERNAL_CC) -print-file-name=libc.a) |sed -r -e 's:usr/lib/libc\.a::;'` ; \
 	fi ; \
 	fi ; \
 	if test -z "$${SYSROOT_DIR}" ; then \
 	if test -z "$${SYSROOT_DIR}" ; then \
 		@echo "External toolchain doesn't support --sysroot. Cannot use." ; \
 		@echo "External toolchain doesn't support --sysroot. Cannot use." ; \
@@ -172,15 +224,15 @@ $(STAMP_DIR)/ext-toolchain-checked:
 # the $(TARGET_DIR) and copy the whole sysroot (libraries and headers)
 # the $(TARGET_DIR) and copy the whole sysroot (libraries and headers)
 # to $(STAGING_DIR).
 # to $(STAGING_DIR).
 $(STAMP_DIR)/ext-toolchain-installed: $(TOOLCHAIN_EXTERNAL_DEPENDENCIES)
 $(STAMP_DIR)/ext-toolchain-installed: $(TOOLCHAIN_EXTERNAL_DEPENDENCIES)
-	$(Q)SYSROOT_DIR=`$(TARGET_CC_NO_SYSROOT) -print-sysroot 2>/dev/null` ; \
+	$(Q)SYSROOT_DIR=`$(TOOLCHAIN_EXTERNAL_CC) -print-sysroot 2>/dev/null` ; \
 	if test -z "$${SYSROOT_DIR}" ; then \
 	if test -z "$${SYSROOT_DIR}" ; then \
-		SYSROOT_DIR=`readlink -f $$(LANG=C $(TARGET_CC_NO_SYSROOT) -print-file-name=libc.a) |sed -r -e 's:usr/lib/libc\.a::;'` ; \
+		SYSROOT_DIR=`readlink -f $$(LANG=C $(TOOLCHAIN_EXTERNAL_CC) -print-file-name=libc.a) |sed -r -e 's:usr/lib/libc\.a::;'` ; \
 	fi ; \
 	fi ; \
 	if test -z "$${SYSROOT_DIR}" ; then \
 	if test -z "$${SYSROOT_DIR}" ; then \
 		@echo "External toolchain doesn't support --sysroot. Cannot use." ; \
 		@echo "External toolchain doesn't support --sysroot. Cannot use." ; \
 		exit 1 ; \
 		exit 1 ; \
 	fi ; \
 	fi ; \
-	ARCH_SUBDIR=`$(TARGET_CC_NO_SYSROOT) $(TARGET_CFLAGS) -print-multi-directory` ; \
+	ARCH_SUBDIR=`$(TOOLCHAIN_EXTERNAL_CC) $(TOOLCHAIN_EXTERNAL_CFLAGS) -print-multi-directory` ; \
 	ARCH_SYSROOT_DIR=$${SYSROOT_DIR}/$${ARCH_SUBDIR} ; \
 	ARCH_SYSROOT_DIR=$${SYSROOT_DIR}/$${ARCH_SUBDIR} ; \
 	mkdir -p $(TARGET_DIR)/lib ; \
 	mkdir -p $(TARGET_DIR)/lib ; \
 	echo "Copy external toolchain libraries to target..." ; \
 	echo "Copy external toolchain libraries to target..." ; \
@@ -196,3 +248,21 @@ $(STAMP_DIR)/ext-toolchain-installed: $(TOOLCHAIN_EXTERNAL_DEPENDENCIES)
 		$(call create_lib64_symlinks) ; \
 		$(call create_lib64_symlinks) ; \
 	fi ; \
 	fi ; \
 	touch $@
 	touch $@
+
+# Build toolchain wrapper for preprocessor, C and C++ compiler, and setup
+# symlinks for everything else
+$(HOST_DIR)/usr/bin/ext-toolchain-wrapper: $(STAMP_DIR)/ext-toolchain-installed
+	mkdir -p $(HOST_DIR)/usr/bin; cd $(HOST_DIR)/usr/bin; \
+	for i in $(TOOLCHAIN_EXTERNAL_CROSS)*; do \
+		case "$$i" in \
+		*cc|*cc-*|*++|*++-*|*cpp) \
+			base=$${i##*/}; \
+			ln -sf $(@F) $$base; \
+			;; \
+		*) \
+			ln -sf $$i .; \
+			;; \
+		esac; \
+	done ;
+	$(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_EXTERNAL_WRAPPER_ARGS) -s \
+		toolchain/toolchain-external/ext-toolchain-wrapper.c -o $@

+ 75 - 0
toolchain/toolchain-external/ext-toolchain-wrapper.c

@@ -0,0 +1,75 @@
+/**
+ * Buildroot wrapper for external toolchains. This simply executes the real
+ * toolchain with a number of arguments (sysroot/arch/..) hardcoded,
+ * to ensure the external toolchain uses the correct configuration.
+ *
+ * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+
+#define MAXARGS 1000
+
+static char path[PATH_MAX] = BR_CROSS_PATH;
+
+static char *args[MAXARGS] = {
+	path,
+	"--sysroot", BR_SYSROOT,
+#ifdef BR_ARCH
+	"-march=" BR_ARCH,
+#endif /* BR_ARCH */
+#ifdef BR_TUNE
+	"-mtune=" BR_TUNE,
+#endif /* BR_TUNE */
+#ifdef BR_ABI
+	"-mabi=" BR_ABI,
+#endif
+#ifdef BR_SOFTFLOAT
+	"-msoft-float",
+#endif /* BR_SOFTFLOAT */
+#ifdef BR_VFPFLOAT
+	"-mfpu=vfp",
+#endif /* BR_VFPFLOAT */
+};
+
+static const char *get_basename(const char *name)
+{
+	const char *base;
+
+	base = strrchr(name, '/');
+	if (base)
+		base++;
+	else
+		base = name;
+
+	return base;
+}
+
+int main(int argc, char **argv)
+{
+	int i;
+
+	for (i=0; args[i]; i++);
+
+	if ((argc+i) >= MAXARGS) {
+		fputs("Too many arguments\n", stderr);
+		return 1;
+	}
+
+	/* forward args */
+	memcpy(&args[i], &argv[1], sizeof(argv[0]) * (argc - 1));
+
+	strcat(path, get_basename(argv[0]));
+
+	if (execv(path, args))
+		perror(path);
+
+	return 2;
+}