mirror of
https://github.com/reactos/ccache.git
synced 2025-02-21 11:30:29 +00:00
Add support for running a custom command to identify the compiler
This commit is contained in:
parent
0e828cb8b9
commit
18cc772aa6
43
MANUAL.txt
43
MANUAL.txt
@ -211,6 +211,32 @@ cases you won't need any of these as the defaults will be fine.
|
||||
compiler's source has not changed, or if the compiler only has changes that
|
||||
don't affect code generation). You should only use the *none* setting if
|
||||
you know what you are doing.
|
||||
_a command string_::
|
||||
Hash the standard output and standard error output of the specified
|
||||
command. The command is passed to +/bin/sh+ for execution. You can use
|
||||
``$compiler'' in the command string to refer to the compiler. Example
|
||||
commands:
|
||||
+
|
||||
--
|
||||
* +$compiler -v+
|
||||
* +$compiler -dumpmachine && $compiler -dumpversion+
|
||||
|
||||
You should make sure that the specified command is as fast as possible since it
|
||||
will be run once for each ccache invocation.
|
||||
|
||||
Identifying the compiler using a command is useful if you want to avoid cache
|
||||
misses when the compiler has been rebuilt but not changed.
|
||||
|
||||
Another case is when the compiler (as seen by ccache) actually isn't the real
|
||||
compiler but another compiler wrapper -- in that case, the default *mtime*
|
||||
method will hash the mtime and size of the other compiler wrapper, which means
|
||||
that ccache won't be able to detect a compiler upgrade. Using a suitable
|
||||
command to identify the compiler is thus safer, but it's also slower, so you
|
||||
should consider continue using the *mtime* method in combination with
|
||||
*CCACHE_PREFIX* if possible. See
|
||||
<<_using_ccache_with_other_compiler_wrappers,USING CCACHE WITH OTHER COMPILER
|
||||
WRAPPERS>>.
|
||||
--
|
||||
--
|
||||
|
||||
*CCACHE_CPP2*::
|
||||
@ -572,17 +598,20 @@ environment variable *CCACHE_PREFIX* to the name of the wrapper (e.g. *distcc*)
|
||||
and ccache will prefix the command line with the specified command when running
|
||||
the compiler.
|
||||
|
||||
It is not recommended to use the form *ccache anotherwrapper compiler args* as
|
||||
the compilation command. It's also not recommended to use the masquerading
|
||||
technique for the other compiler wrapper. The reason is that ccache will in
|
||||
both cases hash the mtime of the other wrapper instead of the real compiler
|
||||
(see the *CCACHE_COMPILERCHECK* option), which means that:
|
||||
Unless you set *CCACHE_COMPILERCHECK* to a suitable command (see the
|
||||
description of that configuration option), it is not recommended to use the
|
||||
form *ccache anotherwrapper compiler args* as the compilation command. It's
|
||||
also not recommended to use the masquerading technique for the other compiler
|
||||
wrapper. The reason is that by default, ccache will in both cases hash the
|
||||
mtime and size of the other wrapper instead of the real compiler, which means
|
||||
that:
|
||||
|
||||
* Compiler upgrades will not be detected properly.
|
||||
* The cached results will not be shared between compilations with and without
|
||||
the other wrapper.
|
||||
* ccache will needlessly invoke the other wrapper when running the
|
||||
preprocessor.
|
||||
|
||||
Another minor thing is that if *CCACHE_PREFIX* is not used, ccache will
|
||||
needlessly invoke the other wrapper when running the preprocessor.
|
||||
|
||||
|
||||
Bugs
|
||||
|
40
ccache.c
40
ccache.c
@ -32,6 +32,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
@ -914,10 +915,47 @@ calculate_common_hash(struct args *args, struct mdfour *hash)
|
||||
} else if (str_eq(compilercheck, "content")) {
|
||||
hash_delimiter(hash, "cc_content");
|
||||
hash_file(hash, args->argv[0]);
|
||||
} else { /* mtime */
|
||||
} else if (str_eq(compilercheck, "mtime")) {
|
||||
hash_delimiter(hash, "cc_mtime");
|
||||
hash_int(hash, st.st_size);
|
||||
hash_int(hash, st.st_mtime);
|
||||
} else { /* command string */
|
||||
char buf[8192];
|
||||
static char compiler_env[1024];
|
||||
size_t n;
|
||||
char *command;
|
||||
FILE *f;
|
||||
int status;
|
||||
|
||||
cc_log("Running compiler check command: %s", compilercheck);
|
||||
snprintf(compiler_env, sizeof(compiler_env),
|
||||
"compiler=%s", orig_args->argv[0]);
|
||||
putenv(compiler_env);
|
||||
command = format("{ %s ; } </dev/null 2>&1", compilercheck);
|
||||
f = popen(command, "r");
|
||||
free(command);
|
||||
if (!f) {
|
||||
stats_update(STATS_COMPCHECK);
|
||||
fatal("Compiler check popen failed");
|
||||
}
|
||||
hash_delimiter(hash, "cc_command");
|
||||
while (1) {
|
||||
n = fread(buf, 1, sizeof(buf), f);
|
||||
hash_buffer(hash, buf, n);
|
||||
if (n < sizeof(buf)) {
|
||||
if (feof(f)) {
|
||||
break;
|
||||
} else {
|
||||
stats_update(STATS_COMPCHECK);
|
||||
fatal("Failed reading from compiler check command");
|
||||
}
|
||||
}
|
||||
}
|
||||
status = pclose(f);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
stats_update(STATS_COMPCHECK);
|
||||
fatal("Compiler check command returned %d", WEXITSTATUS(status));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
1
ccache.h
1
ccache.h
@ -52,6 +52,7 @@ enum stats {
|
||||
STATS_NOOUTPUT = 23,
|
||||
STATS_EMPTYOUTPUT = 24,
|
||||
STATS_BADEXTRAFILE = 25,
|
||||
STATS_COMPCHECK = 26,
|
||||
|
||||
STATS_END
|
||||
};
|
||||
|
6
perf.py
6
perf.py
@ -79,6 +79,7 @@ def test(tmp_dir, options, compiler_args, source_file):
|
||||
fp.close()
|
||||
|
||||
environment = {"CCACHE_DIR": ccache_dir, "PATH": environ["PATH"]}
|
||||
environment["CCACHE_COMPILERCHECK"] = options.compilercheck
|
||||
if options.compression:
|
||||
environment["CCACHE_COMPRESS"] = "1"
|
||||
if options.hardlink:
|
||||
@ -204,6 +205,9 @@ def main(argv):
|
||||
op.add_option(
|
||||
"--ccache",
|
||||
help="location of ccache (default: %s)" % DEFAULT_CCACHE)
|
||||
op.add_option(
|
||||
"--compilercheck",
|
||||
help="specify compilercheck (default: mtime)")
|
||||
op.add_option(
|
||||
"--compression",
|
||||
help="use compression",
|
||||
@ -236,6 +240,7 @@ def main(argv):
|
||||
action="store_true")
|
||||
op.set_defaults(
|
||||
ccache=DEFAULT_CCACHE,
|
||||
compilercheck="mtime",
|
||||
directory=DEFAULT_DIRECTORY,
|
||||
times=DEFAULT_TIMES)
|
||||
(options, args) = op.parse_args(argv[1:])
|
||||
@ -259,6 +264,7 @@ def main(argv):
|
||||
print "Compilation command: %s -c -o %s.o" % (
|
||||
" ".join(args),
|
||||
splitext(argv[-1])[0])
|
||||
print "Compilercheck:", options.compilercheck
|
||||
print "Compression:", on_off(options.compression)
|
||||
print "Hardlink:", on_off(options.hardlink)
|
||||
print "Nostats:", on_off(options.nostats)
|
||||
|
1
stats.c
1
stats.c
@ -71,6 +71,7 @@ static struct {
|
||||
{ STATS_MISSING, "cache file missing ", NULL, 0 },
|
||||
{ STATS_ARGS, "bad compiler arguments ", NULL, 0 },
|
||||
{ STATS_SOURCELANG, "unsupported source language ", NULL, 0 },
|
||||
{ STATS_COMPCHECK, "compiler check failed ", NULL, 0 },
|
||||
{ STATS_CONFTEST, "autoconf compile/link ", NULL, 0 },
|
||||
{ STATS_UNSUPPORTED, "unsupported compiler option ", NULL, 0 },
|
||||
{ STATS_OUTSTDOUT, "output to stdout ", NULL, 0 },
|
||||
|
26
test.sh
26
test.sh
@ -388,6 +388,32 @@ EOF
|
||||
checkstat 'cache hit (preprocessed)' 2
|
||||
checkstat 'cache miss' 1
|
||||
|
||||
testname="compilercheck=command"
|
||||
$CCACHE -z >/dev/null
|
||||
backdate compiler.sh
|
||||
CCACHE_COMPILERCHECK='echo $compiler' $CCACHE ./compiler.sh -c test1.c
|
||||
checkstat 'cache hit (preprocessed)' 0
|
||||
checkstat 'cache miss' 1
|
||||
echo "# Compiler upgrade" >>compiler.sh
|
||||
CCACHE_COMPILERCHECK="echo ./compiler.sh" $CCACHE ./compiler.sh -c test1.c
|
||||
checkstat 'cache hit (preprocessed)' 1
|
||||
checkstat 'cache miss' 1
|
||||
CCACHE_COMPILERCHECK='echo bar >&2' $CCACHE ./compiler.sh -c test1.c
|
||||
checkstat 'cache hit (preprocessed)' 1
|
||||
checkstat 'cache miss' 2
|
||||
CCACHE_COMPILERCHECK='read x; echo -n b >&2; echo ar >&2' $CCACHE ./compiler.sh -c test1.c
|
||||
checkstat 'cache hit (preprocessed)' 2
|
||||
checkstat 'cache miss' 2
|
||||
|
||||
testname="compilercheck=unknown_command"
|
||||
$CCACHE -z >/dev/null
|
||||
backdate compiler.sh
|
||||
CCACHE_COMPILERCHECK="unknown_command" $CCACHE ./compiler.sh -c test1.c 2>/dev/null
|
||||
if [ "$?" -eq 0 ]; then
|
||||
test_failed "Expected failure running unknown_command to verify compiler but was success"
|
||||
fi
|
||||
checkstat 'compiler check failed' 1
|
||||
|
||||
testname="no object file"
|
||||
cat <<'EOF' >test_no_obj.c
|
||||
int test_no_obj;
|
||||
|
11
util.c
11
util.c
@ -140,16 +140,7 @@ fatal(const char *format, ...)
|
||||
vsnprintf(msg, sizeof(msg), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (cache_logfile) {
|
||||
if (!logfile) {
|
||||
logfile = fopen(cache_logfile, "a");
|
||||
}
|
||||
if (logfile) {
|
||||
fprintf(logfile, "[%-5d] FATAL: %s\n", (int)getpid(), msg);
|
||||
fflush(logfile);
|
||||
}
|
||||
}
|
||||
|
||||
cc_log("FATAL: %s", msg);
|
||||
fprintf(stderr, "ccache: FATAL: %s\n", msg);
|
||||
|
||||
exit(1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user