diff options
author | Arnout Vandecappelle <arnout@mind.be> | 2015-10-04 13:28:41 +0100 |
---|---|---|
committer | Peter Korsgaard <peter@korsgaard.com> | 2015-10-04 18:22:19 +0200 |
commit | f6ae24379b551cbfc6447b25a241ffa76d366ddc (patch) | |
tree | 16214940d57b612b6cd35d8859bff1cf2dac857a /toolchain/toolchain-wrapper.c | |
parent | ad9c7ee554bb8b6f69429e8d1585d0555a42f06c (diff) |
toolchain-external: move wrapper to toolchain directory
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>
Diffstat (limited to 'toolchain/toolchain-wrapper.c')
-rw-r--r-- | toolchain/toolchain-wrapper.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c new file mode 100644 index 000000000..ac40decd5 --- /dev/null +++ b/toolchain/toolchain-wrapper.c @@ -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; +} |