From eb5d9bd3beb546b968f81875ee858c4a9eb1c86a Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Mon, 17 May 2010 22:29:42 +0200 Subject: [PATCH] Add some opt-in sloppiness --- NEWS.txt | 3 ++ ccache.c | 53 +++++++++++++++++--- ccache.h | 4 ++ hashutil.c | 4 ++ manual.txt | 12 +++++ test.sh | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 208 insertions(+), 8 deletions(-) diff --git a/NEWS.txt b/NEWS.txt index 4fbb56aef..878d1fc13 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -77,6 +77,9 @@ New features and improvements - Messages printed to the debug log (specified by `CCACHE_LOGFILE`) have been improved. + - You can relax some checks that ccache does in direct mode by setting + `CCACHE_SLOPPINESS`. See the manual for more information. + - `CCACHE_TEMPDIR` no longer needs to be on the same filesystem as `CCACHE_DIR`. diff --git a/ccache.c b/ccache.c index e2386c1f4..c1b3b2c88 100644 --- a/ccache.c +++ b/ccache.c @@ -133,6 +133,9 @@ static char *manifest_path; */ static time_t time_of_compilation; +/* Bitmask of SLOPPY_*. */ +unsigned sloppiness = 0; + /* * Files included by the preprocessor and their hashes/sizes. Key: file path. * Value: struct file_hash. @@ -330,7 +333,8 @@ static void remember_include_file(char *path, size_t path_len) /* Ignore directory, typically $PWD. */ goto ignore; } - if (st.st_mtime >= time_of_compilation) { + if (!(sloppiness & SLOPPY_INCLUDE_FILE_MTIME) + && st.st_mtime >= time_of_compilation) { cc_log("Include file %s too new", path); goto failure; } @@ -910,13 +914,15 @@ static struct file_hash *calculate_object_hash( } if (direct_mode) { - /* - * The source code file or an include file may contain - * __FILE__, so make sure that the hash is unique for the file - * name. - */ - hash_delimiter(hash, "inputfile"); - hash_string(hash, input_file); + if (!(sloppiness & SLOPPY_FILE_MACRO)) { + /* + * The source code file or an include file may contain + * __FILE__, so make sure that the hash is unique for + * the file name. + */ + hash_delimiter(hash, "inputfile"); + hash_string(hash, input_file); + } hash_delimiter(hash, "sourcecode"); result = hash_source_code_file(hash, input_file); @@ -1617,6 +1623,35 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args, *compiler_args = stripped_args; } +static unsigned parse_sloppiness(char *p) +{ + unsigned result = 0; + char *word, *q; + + if (!p) { + return result; + } + p = x_strdup(p); + q = p; + while ((word = strtok(q, ", "))) { + if (strcmp(word, "file_macro") == 0) { + cc_log("Being sloppy about __FILE__"); + result |= SLOPPY_FILE_MACRO; + } + if (strcmp(word, "include_file_mtime") == 0) { + cc_log("Being sloppy about include file mtime"); + result |= SLOPPY_INCLUDE_FILE_MTIME; + } + if (strcmp(word, "time_macros") == 0) { + cc_log("Being sloppy about __DATE__ and __TIME__"); + result |= SLOPPY_TIME_MACROS; + } + q = NULL; + } + free(p); + return result; +} + /* the main ccache driver function */ static void ccache(int argc, char *argv[]) { @@ -1636,6 +1671,8 @@ static void ccache(int argc, char *argv[]) cc_log("=== CCACHE STARTED ========================================="); + sloppiness = parse_sloppiness(getenv("CCACHE_SLOPPINESS")); + if (base_dir) { cc_log("Base directory: %s", base_dir); } diff --git a/ccache.h b/ccache.h index 328cf0f56..627973426 100644 --- a/ccache.h +++ b/ccache.h @@ -55,6 +55,10 @@ enum stats { STATS_END }; +#define SLOPPY_INCLUDE_FILE_MTIME 1 +#define SLOPPY_FILE_MACRO 2 +#define SLOPPY_TIME_MACROS 4 + void hash_start(struct mdfour *md); void hash_delimiter(struct mdfour *md, const char* type); void hash_string(struct mdfour *md, const char *s); diff --git a/hashutil.c b/hashutil.c index 7d71e76e9..06c03eca0 100644 --- a/hashutil.c +++ b/hashutil.c @@ -64,6 +64,7 @@ hash_source_code_string( char hashbuf[64]; size_t hashbuflen = 0; int result = HASH_SOURCE_CODE_OK; + extern unsigned sloppiness; p = str; end = str + len; @@ -159,6 +160,9 @@ hash_source_code_string( end: hash_buffer(hash, hashbuf, hashbuflen); + if (sloppiness & SLOPPY_TIME_MACROS) { + return 0; + } if (result & HASH_SOURCE_CODE_FOUND_DATE) { /* * Make sure that the hash sum changes if the (potential) diff --git a/manual.txt b/manual.txt index 53abe5bda..76cf26b26 100644 --- a/manual.txt +++ b/manual.txt @@ -299,6 +299,18 @@ cases you won't need any of these as the defaults will be fine. This forces ccache to not use any cached results, even if it finds them. New results are still cached, but existing cache entries are ignored. +*CCACHE_SLOPPINESS*:: + + By default, ccache tries to give as few false cache hits as possible. + However, in certain situations it's possible that you know things that + ccache can't take for granted. The *CCACHE_SLOPPINESS* environment variable + makes it possible to tell ccache to relax some checks in order to increase + the hit rate. The value should be a comma-separated string with options. + Available options are: *file_macro* (ignore *\_\_FILE\__* being present in + the source), *include_file_mtime* (don't check the modification time of + include files in direct mode) and *time_macros* (ignore *\_\_DATE\__* and + *\_\_TIME__* being present in the source code). + *CCACHE_TEMPDIR*:: The *CCACHE_TEMPDIR* environment variable specifies where ccache will put diff --git a/test.sh b/test.sh index 067a1b15d..34a2a2f80 100755 --- a/test.sh +++ b/test.sh @@ -53,6 +53,7 @@ unset CCACHE_PATH unset CCACHE_PREFIX unset CCACHE_READONLY unset CCACHE_RECACHE +unset CCACHE_SLOPPINESS unset CCACHE_TEMPDIR unset CCACHE_UMASK unset CCACHE_UNIFY @@ -837,6 +838,51 @@ EOF checkstat 'cache hit (preprocessed)' 0 checkstat 'cache miss' 2 + ################################################################## + # Check that direct mode ignores __FILE__ if sloppiness is specified. + testname="__FILE__ in source file, sloppy" + $CCACHE -Cz >/dev/null + cat <file.c +#define file __FILE__ +int test; +EOF + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c $PWD/file.c + checkstat 'cache hit (direct)' 2 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + + testname="__FILE__ in include file, sloppy" + $CCACHE -Cz >/dev/null + cat <file.h +#define file __FILE__ +int test; +EOF + backdate file.h + cat <file_h.c +#include "file.h" +EOF + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file_h.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c file_h.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + mv file_h.c file2_h.c + CCACHE_SLOPPINESS=file_macro $CCACHE $COMPILER -c $PWD/file2_h.c + checkstat 'cache hit (direct)' 2 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + ################################################################## # Check that we never get direct hits when __TIME__ is used. testname="__TIME__ in source file" @@ -873,6 +919,100 @@ EOF checkstat 'cache hit (preprocessed)' 1 checkstat 'cache miss' 1 + ################################################################## + # Check that direct mode ignores __TIME__ when sloppiness is specified. + testname="__TIME__ in source file, sloppy" + $CCACHE -Cz >/dev/null + cat <time.c +#define time __TIME__ +int test; +EOF + CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + + testname="__TIME__ in include time, sloppy" + $CCACHE -Cz >/dev/null + cat <time.h +#define time __TIME__ +int test; +EOF + backdate time.h + cat <time_h.c +#include "time.h" +EOF + CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time_h.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c time_h.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + + ################################################################## + # Check that a too new include file turns off direct mode. + testname="too new include file" + $CCACHE -Cz >/dev/null + cat <new.c +#include "new.h" +EOF + cat <new.h +int test; +EOF + touchy_compiler=touchy-compiler.sh + cat <$touchy_compiler +#!/bin/sh +CCACHE_DISABLE=1 # If $COMPILER happens to be a ccache symlink... +export CCACHE_DISABLE +[ x\$2 = "x-E" ] && touch \$3 # Be sure that mtime >= time_of_compilation +exec $COMPILER "\$@" +EOF + chmod +x $touchy_compiler + + $CCACHE ./$touchy_compiler -c new.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + $CCACHE ./$touchy_compiler -c new.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 1 + checkstat 'cache miss' 1 + + ################################################################## + # Check that include file mtime is ignored when sloppiness is specified. + testname="too new include file, sloppy" + $CCACHE -Cz >/dev/null + cat <new.c +#include "new.h" +EOF + cat <new.h +int test; +EOF + touchy_compiler=touchy-compiler.sh + cat <$touchy_compiler +#!/bin/sh +CCACHE_DISABLE=1 # If $COMPILER happens to be a ccache symlink... +export CCACHE_DISABLE +[ x\$2 = "x-E" ] && touch \$3 # Be sure that mtime >= time_of_compilation +exec $COMPILER "\$@" +EOF + chmod +x $touchy_compiler + + CCACHE_SLOPPINESS=include_file_mtime $CCACHE ./$touchy_compiler -c new.c + checkstat 'cache hit (direct)' 0 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + CCACHE_SLOPPINESS=include_file_mtime $CCACHE ./$touchy_compiler -c new.c + checkstat 'cache hit (direct)' 1 + checkstat 'cache hit (preprocessed)' 0 + checkstat 'cache miss' 1 + ################################################################## # Reset things. CCACHE_NODIRECT=1 -- 2.47.2