kumquat-buildroot/toolchain/toolchain-wrapper.c

343 lines
8.9 KiB
C
Raw Normal View History

/**
* 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>
#ifdef BR_CCACHE
static char ccache_path[PATH_MAX];
#endif
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
toolchain/external: fix wrapper by not passing conflicting flags In our wrapper, we forcibly add the -march=, -mcpu= and-mtune= flags to the actual compiler, this in an attempt to always generate correct and optimised code for the target. But in some cases, the caller knows better than we do, and passes its own set, or subset of those flags. In this case, some may conflict with the ones we pass. The most prominent offender being the Linux kernel. For example, on the ARM Raspberry Pi, the Linux kernel will set the -march=armv6 flag and no -mcpu= flag, but we pass -mcpu=arm1176jzf-s, which conflicts: drivers/scsi/scsi_trace.c:1:0: warning: switch -mcpu=arm1176jzf-s conflicts with -march=armv6 switch (and so for all the files the kernel compiles, pretty messy) (note: arm1176jzf-s is not an armv6, it is an armv6zk. Yeah...) To avoid this situation, we scan our commandline for any occurence of the possibly conflicting flags. If none is found, then we add our owns. If any is found, then we don't add any of our owns. The idea behind this is that we trust the caller to know better than we do what it is doing. Since the biggest, and sole so far, offender is the Linux kernel, then this is a rather safe bet. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Peter Korsgaard <jacmet@uclibc.org> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2014-01-07 23:46:05 +01:00
* Currently, we have:
* -mfloat-abi=
* -march=
* -mcpu=
*/
#define EXCLUSIVE_ARGS 3
static char *predef_args[] = {
#ifdef BR_CCACHE
ccache_path,
#endif
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_OMIT_LOCK_PREFIX
"-Wa,-momit-lock-prefix=yes",
#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
};
struct unsafe_opt_s {
const char *arg;
size_t len;
};
/* Unsafe options are options that specify a potentialy unsafe path,
* that will be checked by check_unsafe_path(), below.
*
* sizeof() on a string literal includes the terminating \0.
*/
#define UNSAFE_OPT(o) { #o, sizeof(#o)-1 }
static const struct unsafe_opt_s unsafe_opts[] = {
UNSAFE_OPT(-I),
UNSAFE_OPT(-idirafter),
UNSAFE_OPT(-iquote),
UNSAFE_OPT(-isystem),
UNSAFE_OPT(-L),
{ NULL, 0 },
};
/* Check if path is unsafe for cross-compilation. Unsafe paths are those
* pointing to the standard native include or library paths.
*
* We print the arguments leading to the failure. For some options, gcc
* accepts the path to be concatenated to the argument (e.g. -I/foo/bar)
* or separated (e.g. -I /foo/bar). In the first case, we need only print
* the argument as it already contains the path (arg_has_path), while in
* the second case we need to print both (!arg_has_path).
*
* If paranoid, exit in error instead of just printing a warning.
*/
static void check_unsafe_path(const char *arg,
const char *path,
int paranoid,
int arg_has_path)
{
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)))
continue;
fprintf(stderr,
"%s: %s: unsafe header/library path used in cross-compilation: '%s%s%s'\n",
program_invocation_short_name,
paranoid ? "ERROR" : "WARNING",
arg,
arg_has_path ? "" : "' '", /* close single-quote, space, open single-quote */
arg_has_path ? "" : path); /* so that arg and path are properly quoted. */
if (paranoid)
exit(1);
}
}
int main(int argc, char **argv)
{
char **args, **cur, **exec_args;
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" BR_CROSS_PATH_SUFFIX, absbasedir, basename);
#elif defined(BR_CROSS_PATH_ABS)
ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s" BR_CROSS_PATH_SUFFIX, basename);
#else
gcc: use toolchain wrapper We have a toolchain wrapper for external toolchain, but it is also beneficial for internal toolchains, for the following reasons: 1. It can make sure that BR2_TARGET_OPTIMIZATION is passed to the compiler even if a package's build system doesn't honor CFLAGS. 2. It allows us to do the unsafe path check (i.e. -I/usr/include) without patching gcc. 3. It makes it simpler to implement building each package with a separate staging directory (per-package staging). 4. It makes it simpler to implement a compiler hash check for ccache. The wrapper is reused from the external toolchain. A third CROSS_PATH_ option is added to the wrapper: in this case, the real executable is in the same directory, with the extension .real. The creation of the simple symlinks is merged with the creation of the wrapper symlinks, otherwise part of the -gcc-ar handling logic would have to be repeated. The complex case-condition could be refactored with the one for the external toolchain, but then it becomes even more complex because they each have special corner cases. For example, the internal toolchain has to handle *.real to avoid creating an extra indirection after host-gcc-{final,initial}-rebuild. Instead of creating the .real files, it would also have been possible to install the internal toolchain in $(HOST_DIR)/opt, similar to what we do for the external toolchain. However, then we would also have to copy things to the sysroot and do more of the magic that the external toolchain is doing. So keeping it in $(HOST_DIR)/usr/bin is much simpler. Note that gcc-initial has to be wrapped as well, because it is used for building libc and we want to apply the same magic when building libc. 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>
2015-10-04 14:28:42 +02:00
ret = snprintf(path, sizeof(path), "%s/usr/bin/%s" BR_CROSS_PATH_SUFFIX, absbasedir, basename);
#endif
if (ret >= sizeof(path)) {
perror(__FILE__ ": overflow");
return 3;
}
#ifdef BR_CCACHE
ret = snprintf(ccache_path, sizeof(ccache_path), "%s/usr/bin/ccache", absbasedir);
if (ret >= sizeof(ccache_path)) {
perror(__FILE__ ": overflow");
return 3;
}
#endif
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
toolchain/external: fix wrapper by not passing conflicting flags In our wrapper, we forcibly add the -march=, -mcpu= and-mtune= flags to the actual compiler, this in an attempt to always generate correct and optimised code for the target. But in some cases, the caller knows better than we do, and passes its own set, or subset of those flags. In this case, some may conflict with the ones we pass. The most prominent offender being the Linux kernel. For example, on the ARM Raspberry Pi, the Linux kernel will set the -march=armv6 flag and no -mcpu= flag, but we pass -mcpu=arm1176jzf-s, which conflicts: drivers/scsi/scsi_trace.c:1:0: warning: switch -mcpu=arm1176jzf-s conflicts with -march=armv6 switch (and so for all the files the kernel compiles, pretty messy) (note: arm1176jzf-s is not an armv6, it is an armv6zk. Yeah...) To avoid this situation, we scan our commandline for any occurence of the possibly conflicting flags. If none is found, then we add our owns. If any is found, then we don't add any of our owns. The idea behind this is that we trust the caller to know better than we do what it is doing. Since the biggest, and sole so far, offender is the Linux kernel, then this is a rather safe bet. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Peter Korsgaard <jacmet@uclibc.org> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2014-01-07 23:46:05 +01:00
#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
toolchain/external: fix wrapper by not passing conflicting flags In our wrapper, we forcibly add the -march=, -mcpu= and-mtune= flags to the actual compiler, this in an attempt to always generate correct and optimised code for the target. But in some cases, the caller knows better than we do, and passes its own set, or subset of those flags. In this case, some may conflict with the ones we pass. The most prominent offender being the Linux kernel. For example, on the ARM Raspberry Pi, the Linux kernel will set the -march=armv6 flag and no -mcpu= flag, but we pass -mcpu=arm1176jzf-s, which conflicts: drivers/scsi/scsi_trace.c:1:0: warning: switch -mcpu=arm1176jzf-s conflicts with -march=armv6 switch (and so for all the files the kernel compiles, pretty messy) (note: arm1176jzf-s is not an armv6, it is an armv6zk. Yeah...) To avoid this situation, we scan our commandline for any occurence of the possibly conflicting flags. If none is found, then we add our owns. If any is found, then we don't add any of our owns. The idea behind this is that we trust the caller to know better than we do what it is doing. Since the biggest, and sole so far, offender is the Linux kernel, then this is a rather safe bet. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Peter Korsgaard <jacmet@uclibc.org> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2014-01-07 23:46:05 +01:00
*/
for (i = 1; i < argc; i++) {
if (!strncmp(argv[i], "-march=", strlen("-march=")) ||
!strncmp(argv[i], "-mtune=", strlen("-mtune=")) ||
toolchain/external: fix wrapper by not passing conflicting flags In our wrapper, we forcibly add the -march=, -mcpu= and-mtune= flags to the actual compiler, this in an attempt to always generate correct and optimised code for the target. But in some cases, the caller knows better than we do, and passes its own set, or subset of those flags. In this case, some may conflict with the ones we pass. The most prominent offender being the Linux kernel. For example, on the ARM Raspberry Pi, the Linux kernel will set the -march=armv6 flag and no -mcpu= flag, but we pass -mcpu=arm1176jzf-s, which conflicts: drivers/scsi/scsi_trace.c:1:0: warning: switch -mcpu=arm1176jzf-s conflicts with -march=armv6 switch (and so for all the files the kernel compiles, pretty messy) (note: arm1176jzf-s is not an armv6, it is an armv6zk. Yeah...) To avoid this situation, we scan our commandline for any occurence of the possibly conflicting flags. If none is found, then we add our owns. If any is found, then we don't add any of our owns. The idea behind this is that we trust the caller to know better than we do what it is doing. Since the biggest, and sole so far, offender is the Linux kernel, then this is a rather safe bet. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Peter Korsgaard <jacmet@uclibc.org> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2014-01-07 23:46:05 +01:00
!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 */
toolchain/external: fix wrapper by not passing conflicting flags In our wrapper, we forcibly add the -march=, -mcpu= and-mtune= flags to the actual compiler, this in an attempt to always generate correct and optimised code for the target. But in some cases, the caller knows better than we do, and passes its own set, or subset of those flags. In this case, some may conflict with the ones we pass. The most prominent offender being the Linux kernel. For example, on the ARM Raspberry Pi, the Linux kernel will set the -march=armv6 flag and no -mcpu= flag, but we pass -mcpu=arm1176jzf-s, which conflicts: drivers/scsi/scsi_trace.c:1:0: warning: switch -mcpu=arm1176jzf-s conflicts with -march=armv6 switch (and so for all the files the kernel compiles, pretty messy) (note: arm1176jzf-s is not an armv6, it is an armv6zk. Yeah...) To avoid this situation, we scan our commandline for any occurence of the possibly conflicting flags. If none is found, then we add our owns. If any is found, then we don't add any of our owns. The idea behind this is that we trust the caller to know better than we do what it is doing. Since the biggest, and sole so far, offender is the Linux kernel, then this is a rather safe bet. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> Cc: Peter Korsgaard <jacmet@uclibc.org> Cc: Arnout Vandecappelle <arnout@mind.be> Cc: Maxime Hadjinlian <maxime.hadjinlian@gmail.com> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2014-01-07 23:46:05 +01:00
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++) {
const struct unsafe_opt_s *opt;
for (opt=unsafe_opts; opt->arg; opt++ ) {
/* Skip any non-unsafe option. */
if (strncmp(argv[i], opt->arg, opt->len))
continue;
/* Handle both cases:
* - path is a separate argument,
* - path is concatenated with option.
*/
if (argv[i][opt->len] == '\0') {
i++;
if (i == argc)
break;
check_unsafe_path(argv[i-1], argv[i], paranoid, 0);
} else
check_unsafe_path(argv[i], argv[i] + opt->len, paranoid, 1);
}
}
/* append forward args */
memcpy(cur, &argv[1], sizeof(char *) * (argc - 1));
cur += argc - 1;
/* finish with NULL termination */
*cur = NULL;
exec_args = args;
#ifdef BR_CCACHE
if (getenv("BR_NO_CCACHE"))
/* Skip the ccache call */
exec_args++;
#endif
/* 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:");
ccache: use mtime for external toolchain, CONF_OPTS for internal toolchain Our current ccache disables hashing of the compiler executable itself, because using the default 'mtime' doesn't work in buildroot: we always rebuild the compiler, so the mtime is always different, so the cache always misses. However, in the current situation, if a user changes the compiler configuration (which would result in the compiler generating different object files than before) and does 'make clean all', ccache may in fact reuse object files from the previous run. This rarely gives problems, because (1) the cache expires quite quickly (it's only 1GB by default), (2) radically changing compiler options will cause cache misses because different header files are used, (3) many compiler changes (e.g. changing -mtune) have little practical effect because the resulting code is usually still compatible, (4) we currently don't use CCACHE_BASEDIR, and almost all object files will contain an absolute path (e.g. in debug info), so when building in a different directory, most of it will miss, (5) we do mostly build test, and many of the potential problems only appear at runtime. Still, when ccache _does_ use the wrong cached object files, the effects are really weird and hard to debug. Also, we want reproducible builds and obviously the above makes builds non-reproducible. So we have a FAQ entry that warns against using ccache and tells the user to clear the cache in case of problems. Now that ccache is called from the toolchain wrapper, it is in fact possible to at least use the 'mtime' compiler hash for the external toolchain and for the host-gcc. Indeed, in this case, the compiler executable comes from a tarball so the mtime will be a good reference for its state. Therefore, the patch (sed script) that changes the default from 'mtime' to 'none' is removed. For the internal toolchain, we can do better by providing a hash of the relevant toolchain options. We are only interested in things that affect the compiler itself, because ccache also processes the header files and it doesn't look at libraries because it doesn't cache the link step, just compilation. Everything that affects the compiler itself can nicely be summarised in $(HOST_GCC_FINAL_CONF_OPTS). Of course, also the compiler source itself is relevant, so the source tarball and all the patches are included in the hash. For this purpose, a new HOST_GCC_XTENSA_OVERLAY_TAR is introduced. The following procedure tests the ccache behaviour: Use this defconfig: BR2_arm=y BR2_CCACHE=y make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" Now make menuconfig, change variant into BR2_cortex_a9 make clean; make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" should be "Cortex-A9" After this commit, it is "Cortex-A9". Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Cc: Danomi Manchego <danomimanchego123@gmail.com> Cc: Károly Kasza <kaszak@gmail.com> Cc: Samuel Martin <s.martin49@gmail.com> Cc: Romain Naour <romain.naour@openwide.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-10-04 17:25:00 +02:00
#ifdef BR_CCACHE_HASH
fprintf(stderr, "%sCCACHE_COMPILERCHECK='string:" BR_CCACHE_HASH "'",
(debug == 2) ? "\n " : " ");
#endif
#ifdef BR_CCACHE_BASEDIR
fprintf(stderr, "%sCCACHE_BASEDIR='" BR_CCACHE_BASEDIR "'",
(debug == 2) ? "\n " : " ");
ccache: use mtime for external toolchain, CONF_OPTS for internal toolchain Our current ccache disables hashing of the compiler executable itself, because using the default 'mtime' doesn't work in buildroot: we always rebuild the compiler, so the mtime is always different, so the cache always misses. However, in the current situation, if a user changes the compiler configuration (which would result in the compiler generating different object files than before) and does 'make clean all', ccache may in fact reuse object files from the previous run. This rarely gives problems, because (1) the cache expires quite quickly (it's only 1GB by default), (2) radically changing compiler options will cause cache misses because different header files are used, (3) many compiler changes (e.g. changing -mtune) have little practical effect because the resulting code is usually still compatible, (4) we currently don't use CCACHE_BASEDIR, and almost all object files will contain an absolute path (e.g. in debug info), so when building in a different directory, most of it will miss, (5) we do mostly build test, and many of the potential problems only appear at runtime. Still, when ccache _does_ use the wrong cached object files, the effects are really weird and hard to debug. Also, we want reproducible builds and obviously the above makes builds non-reproducible. So we have a FAQ entry that warns against using ccache and tells the user to clear the cache in case of problems. Now that ccache is called from the toolchain wrapper, it is in fact possible to at least use the 'mtime' compiler hash for the external toolchain and for the host-gcc. Indeed, in this case, the compiler executable comes from a tarball so the mtime will be a good reference for its state. Therefore, the patch (sed script) that changes the default from 'mtime' to 'none' is removed. For the internal toolchain, we can do better by providing a hash of the relevant toolchain options. We are only interested in things that affect the compiler itself, because ccache also processes the header files and it doesn't look at libraries because it doesn't cache the link step, just compilation. Everything that affects the compiler itself can nicely be summarised in $(HOST_GCC_FINAL_CONF_OPTS). Of course, also the compiler source itself is relevant, so the source tarball and all the patches are included in the hash. For this purpose, a new HOST_GCC_XTENSA_OVERLAY_TAR is introduced. The following procedure tests the ccache behaviour: Use this defconfig: BR2_arm=y BR2_CCACHE=y make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" Now make menuconfig, change variant into BR2_cortex_a9 make clean; make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" should be "Cortex-A9" After this commit, it is "Cortex-A9". Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Cc: Danomi Manchego <danomimanchego123@gmail.com> Cc: Károly Kasza <kaszak@gmail.com> Cc: Samuel Martin <s.martin49@gmail.com> Cc: Romain Naour <romain.naour@openwide.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-10-04 17:25:00 +02:00
#endif
for (i = 0; exec_args[i]; i++)
fprintf(stderr, "%s'%s'",
(debug == 2) ? "\n " : " ", exec_args[i]);
fprintf(stderr, "\n");
}
}
ccache: use mtime for external toolchain, CONF_OPTS for internal toolchain Our current ccache disables hashing of the compiler executable itself, because using the default 'mtime' doesn't work in buildroot: we always rebuild the compiler, so the mtime is always different, so the cache always misses. However, in the current situation, if a user changes the compiler configuration (which would result in the compiler generating different object files than before) and does 'make clean all', ccache may in fact reuse object files from the previous run. This rarely gives problems, because (1) the cache expires quite quickly (it's only 1GB by default), (2) radically changing compiler options will cause cache misses because different header files are used, (3) many compiler changes (e.g. changing -mtune) have little practical effect because the resulting code is usually still compatible, (4) we currently don't use CCACHE_BASEDIR, and almost all object files will contain an absolute path (e.g. in debug info), so when building in a different directory, most of it will miss, (5) we do mostly build test, and many of the potential problems only appear at runtime. Still, when ccache _does_ use the wrong cached object files, the effects are really weird and hard to debug. Also, we want reproducible builds and obviously the above makes builds non-reproducible. So we have a FAQ entry that warns against using ccache and tells the user to clear the cache in case of problems. Now that ccache is called from the toolchain wrapper, it is in fact possible to at least use the 'mtime' compiler hash for the external toolchain and for the host-gcc. Indeed, in this case, the compiler executable comes from a tarball so the mtime will be a good reference for its state. Therefore, the patch (sed script) that changes the default from 'mtime' to 'none' is removed. For the internal toolchain, we can do better by providing a hash of the relevant toolchain options. We are only interested in things that affect the compiler itself, because ccache also processes the header files and it doesn't look at libraries because it doesn't cache the link step, just compilation. Everything that affects the compiler itself can nicely be summarised in $(HOST_GCC_FINAL_CONF_OPTS). Of course, also the compiler source itself is relevant, so the source tarball and all the patches are included in the hash. For this purpose, a new HOST_GCC_XTENSA_OVERLAY_TAR is introduced. The following procedure tests the ccache behaviour: Use this defconfig: BR2_arm=y BR2_CCACHE=y make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" Now make menuconfig, change variant into BR2_cortex_a9 make clean; make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" should be "Cortex-A9" After this commit, it is "Cortex-A9". Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Cc: Danomi Manchego <danomimanchego123@gmail.com> Cc: Károly Kasza <kaszak@gmail.com> Cc: Samuel Martin <s.martin49@gmail.com> Cc: Romain Naour <romain.naour@openwide.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-10-04 17:25:00 +02:00
#ifdef BR_CCACHE_HASH
/* Allow compilercheck to be overridden through the environment */
if (setenv("CCACHE_COMPILERCHECK", "string:" BR_CCACHE_HASH, 0)) {
perror(__FILE__ ": Failed to set CCACHE_COMPILERCHECK");
return 3;
}
#endif
#ifdef BR_CCACHE_BASEDIR
/* Allow compilercheck to be overridden through the environment */
if (setenv("CCACHE_BASEDIR", BR_CCACHE_BASEDIR, 0)) {
perror(__FILE__ ": Failed to set CCACHE_BASEDIR");
return 3;
}
#endif
ccache: use mtime for external toolchain, CONF_OPTS for internal toolchain Our current ccache disables hashing of the compiler executable itself, because using the default 'mtime' doesn't work in buildroot: we always rebuild the compiler, so the mtime is always different, so the cache always misses. However, in the current situation, if a user changes the compiler configuration (which would result in the compiler generating different object files than before) and does 'make clean all', ccache may in fact reuse object files from the previous run. This rarely gives problems, because (1) the cache expires quite quickly (it's only 1GB by default), (2) radically changing compiler options will cause cache misses because different header files are used, (3) many compiler changes (e.g. changing -mtune) have little practical effect because the resulting code is usually still compatible, (4) we currently don't use CCACHE_BASEDIR, and almost all object files will contain an absolute path (e.g. in debug info), so when building in a different directory, most of it will miss, (5) we do mostly build test, and many of the potential problems only appear at runtime. Still, when ccache _does_ use the wrong cached object files, the effects are really weird and hard to debug. Also, we want reproducible builds and obviously the above makes builds non-reproducible. So we have a FAQ entry that warns against using ccache and tells the user to clear the cache in case of problems. Now that ccache is called from the toolchain wrapper, it is in fact possible to at least use the 'mtime' compiler hash for the external toolchain and for the host-gcc. Indeed, in this case, the compiler executable comes from a tarball so the mtime will be a good reference for its state. Therefore, the patch (sed script) that changes the default from 'mtime' to 'none' is removed. For the internal toolchain, we can do better by providing a hash of the relevant toolchain options. We are only interested in things that affect the compiler itself, because ccache also processes the header files and it doesn't look at libraries because it doesn't cache the link step, just compilation. Everything that affects the compiler itself can nicely be summarised in $(HOST_GCC_FINAL_CONF_OPTS). Of course, also the compiler source itself is relevant, so the source tarball and all the patches are included in the hash. For this purpose, a new HOST_GCC_XTENSA_OVERLAY_TAR is introduced. The following procedure tests the ccache behaviour: Use this defconfig: BR2_arm=y BR2_CCACHE=y make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" Now make menuconfig, change variant into BR2_cortex_a9 make clean; make readelf -A output/build/uclibc-1.0.6/libc/signal/signal.os -> Tag_CPU_name: "ARM926EJ-S" should be "Cortex-A9" After this commit, it is "Cortex-A9". Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> Cc: Danomi Manchego <danomimanchego123@gmail.com> Cc: Károly Kasza <kaszak@gmail.com> Cc: Samuel Martin <s.martin49@gmail.com> Cc: Romain Naour <romain.naour@openwide.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-10-04 17:25:00 +02:00
if (execv(exec_args[0], exec_args))
perror(path);
free(args);
return 2;
}