toolchain-external: move wrapper to toolchain directory
authorArnout Vandecappelle <arnout@mind.be>
Sun, 4 Oct 2015 12:28:41 +0000 (13:28 +0100)
committerPeter Korsgaard <peter@korsgaard.com>
Sun, 4 Oct 2015 16:22:19 +0000 (18:22 +0200)
The toolchain wrapper will be reused for the internal toolchain, so it
belongs in the toolchain directory. Also, the ext- prefix is removed
from it. The build commands are moved to a new toolchain-wrapper.mk.

The wrapper arguments that are also relevant for the internal toolchain
wrapper are moved to toolchain-wrapper.mk, the rest stays in
toolchain-external.mk.

While we're at it, move the building of the toolchain wrapper to the
build step of toolchain-external. There is no specific reason to do
this, other than that it fits better semantically. Also remove the
MESSAGE call, otherwise we'd see:
>>> toolchain-external undefined Building
>>> toolchain-external undefined Building toolchain wrapper
/usr/bin/gcc ...
Having an extra "Building toolchain wrapper' message is pointless.

The useless condition on $(BR2_TARGET_OPTIMIZATION) is removed. It was
always true because it wasn't qstrip'ped first, so clearly it works
without that condition as well.

Also rewrapped some comments and removed the 'external' reference.

Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
Cc: Fabio Porcedda <fabio.porcedda@gmail.com>
Cc: Jérôme Oufella <jerome.oufella@savoirfairelinux.com>
Reviewed-by: Romain Naour <romain.naour@openwide.fr>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
toolchain/toolchain-external/ext-toolchain-wrapper.c [deleted file]
toolchain/toolchain-external/toolchain-external.mk
toolchain/toolchain-wrapper.c [new file with mode: 0644]
toolchain/toolchain-wrapper.mk [new file with mode: 0644]

diff --git a/toolchain/toolchain-external/ext-toolchain-wrapper.c b/toolchain/toolchain-external/ext-toolchain-wrapper.c
deleted file mode 100644 (file)
index b3b02d8..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/**
- * 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.
- * The hardcoded path arguments are defined relative to the actual location
- * of the binary.
- *
- * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
- * (C) 2011 Daniel Nyström <daniel.nystrom@timeterminal.se>
- * (C) 2012 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
- * (C) 2013 Spenser Gilliland <spenser@gillilanding.com>
- *
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-
-static char path[PATH_MAX];
-static char sysroot[PATH_MAX];
-
-/**
- * GCC errors out with certain combinations of arguments (examples are
- * -mfloat-abi={hard|soft} and -m{little|big}-endian), so we have to ensure
- * that we only pass the predefined one to the real compiler if the inverse
- * option isn't in the argument list.
- * This specifies the worst case number of extra arguments we might pass
- * Currently, we have:
- *     -mfloat-abi=
- *     -march=
- *     -mcpu=
- */
-#define EXCLUSIVE_ARGS 3
-
-static char *predef_args[] = {
-       path,
-       "--sysroot", sysroot,
-#ifdef BR_ABI
-       "-mabi=" BR_ABI,
-#endif
-#ifdef BR_FPU
-       "-mfpu=" BR_FPU,
-#endif
-#ifdef BR_SOFTFLOAT
-       "-msoft-float",
-#endif /* BR_SOFTFLOAT */
-#ifdef BR_MODE
-       "-m" BR_MODE,
-#endif
-#ifdef BR_64
-       "-m64",
-#endif
-#ifdef BR_BINFMT_FLAT
-       "-Wl,-elf2flt",
-#endif
-#ifdef BR_MIPS_TARGET_LITTLE_ENDIAN
-       "-EL",
-#endif
-#if defined(BR_MIPS_TARGET_BIG_ENDIAN) || defined(BR_ARC_TARGET_BIG_ENDIAN)
-       "-EB",
-#endif
-#ifdef BR_ADDITIONAL_CFLAGS
-       BR_ADDITIONAL_CFLAGS
-#endif
-};
-
-static void check_unsafe_path(const char *path, int paranoid)
-{
-       char **c;
-       static char *unsafe_paths[] = {
-               "/lib", "/usr/include", "/usr/lib", "/usr/local/include", "/usr/local/lib", NULL,
-       };
-
-       for (c = unsafe_paths; *c != NULL; c++) {
-               if (!strncmp(path, *c, strlen(*c))) {
-                       fprintf(stderr, "%s: %s: unsafe header/library path used in cross-compilation: '%s'\n",
-                               program_invocation_short_name,
-                               paranoid ? "ERROR" : "WARNING", path);
-                       if (paranoid)
-                               exit(1);
-                       continue;
-               }
-       }
-}
-
-int main(int argc, char **argv)
-{
-       char **args, **cur;
-       char *relbasedir, *absbasedir;
-       char *progpath = argv[0];
-       char *basename;
-       char *env_debug;
-       char *paranoid_wrapper;
-       int paranoid;
-       int ret, i, count = 0, debug;
-
-       /* Calculate the relative paths */
-       basename = strrchr(progpath, '/');
-       if (basename) {
-               *basename = '\0';
-               basename++;
-               relbasedir = malloc(strlen(progpath) + 7);
-               if (relbasedir == NULL) {
-                       perror(__FILE__ ": malloc");
-                       return 2;
-               }
-               sprintf(relbasedir, "%s/../..", argv[0]);
-               absbasedir = realpath(relbasedir, NULL);
-       } else {
-               basename = progpath;
-               absbasedir = malloc(PATH_MAX + 1);
-               ret = readlink("/proc/self/exe", absbasedir, PATH_MAX);
-               if (ret < 0) {
-                       perror(__FILE__ ": readlink");
-                       return 2;
-               }
-               absbasedir[ret] = '\0';
-               for (i = ret; i > 0; i--) {
-                       if (absbasedir[i] == '/') {
-                               absbasedir[i] = '\0';
-                               if (++count == 3)
-                                       break;
-                       }
-               }
-       }
-       if (absbasedir == NULL) {
-               perror(__FILE__ ": realpath");
-               return 2;
-       }
-
-       /* Fill in the relative paths */
-#ifdef BR_CROSS_PATH_REL
-       ret = snprintf(path, sizeof(path), "%s/" BR_CROSS_PATH_REL "/%s", absbasedir, basename);
-#else /* BR_CROSS_PATH_ABS */
-       ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s", basename);
-#endif
-       if (ret >= sizeof(path)) {
-               perror(__FILE__ ": overflow");
-               return 3;
-       }
-       ret = snprintf(sysroot, sizeof(sysroot), "%s/" BR_SYSROOT, absbasedir);
-       if (ret >= sizeof(sysroot)) {
-               perror(__FILE__ ": overflow");
-               return 3;
-       }
-
-       cur = args = malloc(sizeof(predef_args) +
-                           (sizeof(char *) * (argc + EXCLUSIVE_ARGS)));
-       if (args == NULL) {
-               perror(__FILE__ ": malloc");
-               return 2;
-       }
-
-       /* start with predefined args */
-       memcpy(cur, predef_args, sizeof(predef_args));
-       cur += sizeof(predef_args) / sizeof(predef_args[0]);
-
-#ifdef BR_FLOAT_ABI
-       /* add float abi if not overridden in args */
-       for (i = 1; i < argc; i++) {
-               if (!strncmp(argv[i], "-mfloat-abi=", strlen("-mfloat-abi=")) ||
-                   !strcmp(argv[i], "-msoft-float") ||
-                   !strcmp(argv[i], "-mhard-float"))
-                       break;
-       }
-
-       if (i == argc)
-               *cur++ = "-mfloat-abi=" BR_FLOAT_ABI;
-#endif
-
-#if defined(BR_ARCH) || \
-    defined(BR_CPU)
-       /* Add our -march/cpu flags, but only if none of
-        * -march/mtune/mcpu are already specified on the commandline
-        */
-       for (i = 1; i < argc; i++) {
-               if (!strncmp(argv[i], "-march=", strlen("-march=")) ||
-                   !strncmp(argv[i], "-mtune=", strlen("-mtune=")) ||
-                   !strncmp(argv[i], "-mcpu=",  strlen("-mcpu=" )))
-                       break;
-       }
-       if (i == argc) {
-#ifdef BR_ARCH
-               *cur++ = "-march=" BR_ARCH;
-#endif
-#ifdef BR_CPU
-               *cur++ = "-mcpu=" BR_CPU;
-#endif
-       }
-#endif /* ARCH || CPU */
-
-       paranoid_wrapper = getenv("BR_COMPILER_PARANOID_UNSAFE_PATH");
-       if (paranoid_wrapper && strlen(paranoid_wrapper) > 0)
-               paranoid = 1;
-       else
-               paranoid = 0;
-
-       /* Check for unsafe library and header paths */
-       for (i = 1; i < argc; i++) {
-
-               /* Skip options that do not start with -I and -L */
-               if (strncmp(argv[i], "-I", 2) && strncmp(argv[i], "-L", 2))
-                       continue;
-
-               /* We handle two cases: first the case where -I/-L and
-                * the path are separated by one space and therefore
-                * visible as two separate options, and then the case
-                * where they are stuck together forming one single
-                * option.
-                */
-               if (argv[i][2] == '\0') {
-                       i++;
-                       if (i == argc)
-                               continue;
-                       check_unsafe_path(argv[i], paranoid);
-               } else {
-                       check_unsafe_path(argv[i] + 2, paranoid);
-               }
-       }
-
-       /* append forward args */
-       memcpy(cur, &argv[1], sizeof(char *) * (argc - 1));
-       cur += argc - 1;
-
-       /* finish with NULL termination */
-       *cur = NULL;
-
-       /* Debug the wrapper to see actual arguments passed to
-        * the compiler:
-        * unset, empty, or 0: do not trace
-        * set to 1          : trace all arguments on a single line
-        * set to 2          : trace one argument per line
-        */
-       if ((env_debug = getenv("BR2_DEBUG_WRAPPER"))) {
-               debug = atoi(env_debug);
-               if (debug > 0) {
-                       fprintf(stderr, "Toolchain wrapper executing:");
-                       for (i = 0; args[i]; i++)
-                               fprintf(stderr, "%s'%s'",
-                                       (debug == 2) ? "\n    " : " ", args[i]);
-                       fprintf(stderr, "\n");
-               }
-       }
-
-       if (execv(path, args))
-               perror(path);
-
-       free(args);
-
-       return 2;
-}
index ad4084e172d938b68f194becc30f768897f5be5d..3fb165c8b4895f390cfb2c5063145d3d0e5afcc7 100644 (file)
@@ -153,15 +153,14 @@ TOOLCHAIN_EXTERNAL_CROSS = $(TOOLCHAIN_EXTERNAL_BIN)/$(TOOLCHAIN_EXTERNAL_PREFIX
 TOOLCHAIN_EXTERNAL_CC = $(TOOLCHAIN_EXTERNAL_CROSS)gcc
 TOOLCHAIN_EXTERNAL_CXX = $(TOOLCHAIN_EXTERNAL_CROSS)g++
 TOOLCHAIN_EXTERNAL_READELF = $(TOOLCHAIN_EXTERNAL_CROSS)readelf
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS = -DBR_SYSROOT='"$(STAGING_SUBDIR)"'
 
 ifeq ($(filter $(HOST_DIR)/%,$(TOOLCHAIN_EXTERNAL_BIN)),)
 # TOOLCHAIN_EXTERNAL_BIN points outside HOST_DIR => absolute path
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += \
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += \
        -DBR_CROSS_PATH_ABS='"$(TOOLCHAIN_EXTERNAL_BIN)"'
 else
 # TOOLCHAIN_EXTERNAL_BIN points inside HOST_DIR => relative path
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += \
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += \
        -DBR_CROSS_PATH_REL='"$(TOOLCHAIN_EXTERNAL_BIN:$(HOST_DIR)/%=%)"'
 endif
 
@@ -180,59 +179,54 @@ CC_TARGET_MODE_ := $(call qstrip,$(BR2_GCC_TARGET_MODE))
 # to select the right multilib variant
 ifeq ($(BR2_x86_64),y)
 TOOLCHAIN_EXTERNAL_CFLAGS += -m64
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_64
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_64
 endif
 ifneq ($(CC_TARGET_ARCH_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -march=$(CC_TARGET_ARCH_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ARCH='"$(CC_TARGET_ARCH_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_ARCH='"$(CC_TARGET_ARCH_)"'
 endif
 ifneq ($(CC_TARGET_CPU_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -mcpu=$(CC_TARGET_CPU_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_CPU='"$(CC_TARGET_CPU_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_CPU='"$(CC_TARGET_CPU_)"'
 endif
 ifneq ($(CC_TARGET_ABI_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -mabi=$(CC_TARGET_ABI_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ABI='"$(CC_TARGET_ABI_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_ABI='"$(CC_TARGET_ABI_)"'
 endif
 ifneq ($(CC_TARGET_FPU_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -mfpu=$(CC_TARGET_FPU_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_FPU='"$(CC_TARGET_FPU_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_FPU='"$(CC_TARGET_FPU_)"'
 endif
 ifneq ($(CC_TARGET_FLOAT_ABI_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -mfloat-abi=$(CC_TARGET_FLOAT_ABI_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_FLOAT_ABI='"$(CC_TARGET_FLOAT_ABI_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_FLOAT_ABI='"$(CC_TARGET_FLOAT_ABI_)"'
 endif
 ifneq ($(CC_TARGET_MODE_),)
 TOOLCHAIN_EXTERNAL_CFLAGS += -m$(CC_TARGET_MODE_)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_MODE='"$(CC_TARGET_MODE_)"'
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_MODE='"$(CC_TARGET_MODE_)"'
 endif
 ifeq ($(BR2_BINFMT_FLAT),y)
 TOOLCHAIN_EXTERNAL_CFLAGS += -Wl,-elf2flt
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_BINFMT_FLAT
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_BINFMT_FLAT
 endif
 ifeq ($(BR2_mipsel)$(BR2_mips64el),y)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_MIPS_TARGET_LITTLE_ENDIAN
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_MIPS_TARGET_LITTLE_ENDIAN
 TOOLCHAIN_EXTERNAL_CFLAGS += -EL
 endif
 ifeq ($(BR2_mips)$(BR2_mips64),y)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_MIPS_TARGET_BIG_ENDIAN
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_MIPS_TARGET_BIG_ENDIAN
 TOOLCHAIN_EXTERNAL_CFLAGS += -EB
 endif
 ifeq ($(BR2_arceb),y)
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ARC_TARGET_BIG_ENDIAN
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_ARC_TARGET_BIG_ENDIAN
 TOOLCHAIN_EXTERNAL_CFLAGS += -EB
 endif
-ifneq ($(BR2_TARGET_OPTIMIZATION),)
+
 TOOLCHAIN_EXTERNAL_CFLAGS += $(call qstrip,$(BR2_TARGET_OPTIMIZATION))
-# We create a list like '"-mfoo", "-mbar", "-mbarfoo"' so that each
-# flag is a separate argument when used in execv() by the external
-# toolchain wrapper.
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_ADDITIONAL_CFLAGS='$(foreach f,$(call qstrip,$(BR2_TARGET_OPTIMIZATION)),"$(f)",)'
-endif
 
 ifeq ($(BR2_SOFT_FLOAT),y)
 TOOLCHAIN_EXTERNAL_CFLAGS += -msoft-float
-TOOLCHAIN_EXTERNAL_WRAPPER_ARGS += -DBR_SOFTFLOAT=1
+TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_SOFTFLOAT=1
 endif
 
 # The Linaro ARMhf toolchain expects the libraries in
@@ -696,15 +690,6 @@ define TOOLCHAIN_EXTERNAL_INSTALL_BFIN_FLAT
 endef
 endif
 
-# We use --hash-style=both to increase the compatibility of
-# the generated binary with older platforms, except for MIPS,
-# where the only acceptable hash style is 'sysv'
-ifeq ($(findstring mips,$(HOSTARCH)),mips)
-TOOLCHAIN_EXTERNAL_WRAPPER_HASH_STYLE = sysv
-else
-TOOLCHAIN_EXTERNAL_WRAPPER_HASH_STYLE = both
-endif
-
 # Build toolchain wrapper for preprocessor, C and C++ compiler and setup
 # symlinks for everything else. Skip gdb symlink when we are building our
 # own gdb to prevent two gdb's in output/host/usr/bin.
@@ -715,8 +700,6 @@ endif
 # match the *cc-* pattern. Therefore, an additional case is added for *-ar,
 # *-ranlib and *-nm.
 define TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER
-       $(Q)$(call MESSAGE,"Building ext-toolchain wrapper")
-       $(Q)mkdir -p $(HOST_DIR)/usr/bin
        $(Q)cd $(HOST_DIR)/usr/bin; \
        for i in $(TOOLCHAIN_EXTERNAL_CROSS)*; do \
                base=$${i##*/}; \
@@ -725,7 +708,7 @@ define TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER
                        ln -sf $$(echo $$i | sed 's%^$(HOST_DIR)%../..%') .; \
                        ;; \
                *cc|*cc-*|*++|*++-*|*cpp) \
-                       ln -sf ext-toolchain-wrapper $$base; \
+                       ln -sf toolchain-wrapper $$base; \
                        ;; \
                *gdb|*gdbtui) \
                        if test "$(BR2_PACKAGE_HOST_GDB)" != "y"; then \
@@ -737,10 +720,6 @@ define TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER
                        ;; \
                esac; \
        done
-       $(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_EXTERNAL_WRAPPER_ARGS) \
-               -s -Wl,--hash-style=$(TOOLCHAIN_EXTERNAL_WRAPPER_HASH_STYLE) \
-               toolchain/toolchain-external/ext-toolchain-wrapper.c \
-               -o $(HOST_DIR)/usr/bin/ext-toolchain-wrapper
 endef
 
 # This sed magic is taken from Linux headers_install.sh script.
@@ -779,6 +758,8 @@ define TOOLCHAIN_EXTERNAL_FIXUP_UCLIBCNG_LDSO
        fi
 endef
 
+TOOLCHAIN_EXTERNAL_BUILD_CMDS = $(TOOLCHAIN_BUILD_WRAPPER)
+
 define TOOLCHAIN_EXTERNAL_INSTALL_STAGING_CMDS
        $(TOOLCHAIN_EXTERNAL_INSTALL_SYSROOT_LIBS)
        $(TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER)
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
new file mode 100644 (file)
index 0000000..ac40dec
--- /dev/null
@@ -0,0 +1,258 @@
+/**
+ * Buildroot wrapper for toolchains. This simply executes the real toolchain
+ * with a number of arguments (sysroot/arch/..) hardcoded, to ensure the
+ * toolchain uses the correct configuration.
+ * The hardcoded path arguments are defined relative to the actual location
+ * of the binary.
+ *
+ * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ * (C) 2011 Daniel Nyström <daniel.nystrom@timeterminal.se>
+ * (C) 2012 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
+ * (C) 2013 Spenser Gilliland <spenser@gillilanding.com>
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static char path[PATH_MAX];
+static char sysroot[PATH_MAX];
+
+/**
+ * GCC errors out with certain combinations of arguments (examples are
+ * -mfloat-abi={hard|soft} and -m{little|big}-endian), so we have to ensure
+ * that we only pass the predefined one to the real compiler if the inverse
+ * option isn't in the argument list.
+ * This specifies the worst case number of extra arguments we might pass
+ * Currently, we have:
+ *     -mfloat-abi=
+ *     -march=
+ *     -mcpu=
+ */
+#define EXCLUSIVE_ARGS 3
+
+static char *predef_args[] = {
+       path,
+       "--sysroot", sysroot,
+#ifdef BR_ABI
+       "-mabi=" BR_ABI,
+#endif
+#ifdef BR_FPU
+       "-mfpu=" BR_FPU,
+#endif
+#ifdef BR_SOFTFLOAT
+       "-msoft-float",
+#endif /* BR_SOFTFLOAT */
+#ifdef BR_MODE
+       "-m" BR_MODE,
+#endif
+#ifdef BR_64
+       "-m64",
+#endif
+#ifdef BR_BINFMT_FLAT
+       "-Wl,-elf2flt",
+#endif
+#ifdef BR_MIPS_TARGET_LITTLE_ENDIAN
+       "-EL",
+#endif
+#if defined(BR_MIPS_TARGET_BIG_ENDIAN) || defined(BR_ARC_TARGET_BIG_ENDIAN)
+       "-EB",
+#endif
+#ifdef BR_ADDITIONAL_CFLAGS
+       BR_ADDITIONAL_CFLAGS
+#endif
+};
+
+static void check_unsafe_path(const char *path, int paranoid)
+{
+       char **c;
+       static char *unsafe_paths[] = {
+               "/lib", "/usr/include", "/usr/lib", "/usr/local/include", "/usr/local/lib", NULL,
+       };
+
+       for (c = unsafe_paths; *c != NULL; c++) {
+               if (!strncmp(path, *c, strlen(*c))) {
+                       fprintf(stderr, "%s: %s: unsafe header/library path used in cross-compilation: '%s'\n",
+                               program_invocation_short_name,
+                               paranoid ? "ERROR" : "WARNING", path);
+                       if (paranoid)
+                               exit(1);
+                       continue;
+               }
+       }
+}
+
+int main(int argc, char **argv)
+{
+       char **args, **cur;
+       char *relbasedir, *absbasedir;
+       char *progpath = argv[0];
+       char *basename;
+       char *env_debug;
+       char *paranoid_wrapper;
+       int paranoid;
+       int ret, i, count = 0, debug;
+
+       /* Calculate the relative paths */
+       basename = strrchr(progpath, '/');
+       if (basename) {
+               *basename = '\0';
+               basename++;
+               relbasedir = malloc(strlen(progpath) + 7);
+               if (relbasedir == NULL) {
+                       perror(__FILE__ ": malloc");
+                       return 2;
+               }
+               sprintf(relbasedir, "%s/../..", argv[0]);
+               absbasedir = realpath(relbasedir, NULL);
+       } else {
+               basename = progpath;
+               absbasedir = malloc(PATH_MAX + 1);
+               ret = readlink("/proc/self/exe", absbasedir, PATH_MAX);
+               if (ret < 0) {
+                       perror(__FILE__ ": readlink");
+                       return 2;
+               }
+               absbasedir[ret] = '\0';
+               for (i = ret; i > 0; i--) {
+                       if (absbasedir[i] == '/') {
+                               absbasedir[i] = '\0';
+                               if (++count == 3)
+                                       break;
+                       }
+               }
+       }
+       if (absbasedir == NULL) {
+               perror(__FILE__ ": realpath");
+               return 2;
+       }
+
+       /* Fill in the relative paths */
+#ifdef BR_CROSS_PATH_REL
+       ret = snprintf(path, sizeof(path), "%s/" BR_CROSS_PATH_REL "/%s", absbasedir, basename);
+#else /* BR_CROSS_PATH_ABS */
+       ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s", basename);
+#endif
+       if (ret >= sizeof(path)) {
+               perror(__FILE__ ": overflow");
+               return 3;
+       }
+       ret = snprintf(sysroot, sizeof(sysroot), "%s/" BR_SYSROOT, absbasedir);
+       if (ret >= sizeof(sysroot)) {
+               perror(__FILE__ ": overflow");
+               return 3;
+       }
+
+       cur = args = malloc(sizeof(predef_args) +
+                           (sizeof(char *) * (argc + EXCLUSIVE_ARGS)));
+       if (args == NULL) {
+               perror(__FILE__ ": malloc");
+               return 2;
+       }
+
+       /* start with predefined args */
+       memcpy(cur, predef_args, sizeof(predef_args));
+       cur += sizeof(predef_args) / sizeof(predef_args[0]);
+
+#ifdef BR_FLOAT_ABI
+       /* add float abi if not overridden in args */
+       for (i = 1; i < argc; i++) {
+               if (!strncmp(argv[i], "-mfloat-abi=", strlen("-mfloat-abi=")) ||
+                   !strcmp(argv[i], "-msoft-float") ||
+                   !strcmp(argv[i], "-mhard-float"))
+                       break;
+       }
+
+       if (i == argc)
+               *cur++ = "-mfloat-abi=" BR_FLOAT_ABI;
+#endif
+
+#if defined(BR_ARCH) || \
+    defined(BR_CPU)
+       /* Add our -march/cpu flags, but only if none of
+        * -march/mtune/mcpu are already specified on the commandline
+        */
+       for (i = 1; i < argc; i++) {
+               if (!strncmp(argv[i], "-march=", strlen("-march=")) ||
+                   !strncmp(argv[i], "-mtune=", strlen("-mtune=")) ||
+                   !strncmp(argv[i], "-mcpu=",  strlen("-mcpu=" )))
+                       break;
+       }
+       if (i == argc) {
+#ifdef BR_ARCH
+               *cur++ = "-march=" BR_ARCH;
+#endif
+#ifdef BR_CPU
+               *cur++ = "-mcpu=" BR_CPU;
+#endif
+       }
+#endif /* ARCH || CPU */
+
+       paranoid_wrapper = getenv("BR_COMPILER_PARANOID_UNSAFE_PATH");
+       if (paranoid_wrapper && strlen(paranoid_wrapper) > 0)
+               paranoid = 1;
+       else
+               paranoid = 0;
+
+       /* Check for unsafe library and header paths */
+       for (i = 1; i < argc; i++) {
+
+               /* Skip options that do not start with -I and -L */
+               if (strncmp(argv[i], "-I", 2) && strncmp(argv[i], "-L", 2))
+                       continue;
+
+               /* We handle two cases: first the case where -I/-L and
+                * the path are separated by one space and therefore
+                * visible as two separate options, and then the case
+                * where they are stuck together forming one single
+                * option.
+                */
+               if (argv[i][2] == '\0') {
+                       i++;
+                       if (i == argc)
+                               continue;
+                       check_unsafe_path(argv[i], paranoid);
+               } else {
+                       check_unsafe_path(argv[i] + 2, paranoid);
+               }
+       }
+
+       /* append forward args */
+       memcpy(cur, &argv[1], sizeof(char *) * (argc - 1));
+       cur += argc - 1;
+
+       /* finish with NULL termination */
+       *cur = NULL;
+
+       /* Debug the wrapper to see actual arguments passed to
+        * the compiler:
+        * unset, empty, or 0: do not trace
+        * set to 1          : trace all arguments on a single line
+        * set to 2          : trace one argument per line
+        */
+       if ((env_debug = getenv("BR2_DEBUG_WRAPPER"))) {
+               debug = atoi(env_debug);
+               if (debug > 0) {
+                       fprintf(stderr, "Toolchain wrapper executing:");
+                       for (i = 0; args[i]; i++)
+                               fprintf(stderr, "%s'%s'",
+                                       (debug == 2) ? "\n    " : " ", args[i]);
+                       fprintf(stderr, "\n");
+               }
+       }
+
+       if (execv(path, args))
+               perror(path);
+
+       free(args);
+
+       return 2;
+}
diff --git a/toolchain/toolchain-wrapper.mk b/toolchain/toolchain-wrapper.mk
new file mode 100644 (file)
index 0000000..899947d
--- /dev/null
@@ -0,0 +1,26 @@
+# This file contains the definition of the toolchain wrapper build commands
+
+# We use --hash-style=both to increase the compatibility of the generated
+# binary with older platforms, except for MIPS, where the only acceptable
+# hash style is 'sysv'
+ifeq ($(findstring mips,$(HOSTARCH)),mips)
+TOOLCHAIN_WRAPPER_HASH_STYLE = sysv
+else
+TOOLCHAIN_WRAPPER_HASH_STYLE = both
+endif
+
+TOOLCHAIN_WRAPPER_ARGS = $($(PKG)_TOOLCHAIN_WRAPPER_ARGS)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_SYSROOT='"$(STAGING_SUBDIR)"'
+
+# We create a list like '"-mfoo", "-mbar", "-mbarfoo"' so that each flag is a
+# separate argument when used in execv() by the toolchain wrapper.
+TOOLCHAIN_WRAPPER_ARGS += -DBR_ADDITIONAL_CFLAGS='$(foreach f,$(call qstrip,$(BR2_TARGET_OPTIMIZATION)),"$(f)",)'
+
+# For simplicity, build directly into the install location
+define TOOLCHAIN_BUILD_WRAPPER
+       $(Q)mkdir -p $(HOST_DIR)/usr/bin
+       $(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_WRAPPER_ARGS) \
+               -s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
+               toolchain/toolchain-wrapper.c \
+               -o $(HOST_DIR)/usr/bin/toolchain-wrapper
+endef