]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add some opt-in sloppiness
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 17 May 2010 20:29:42 +0000 (22:29 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Mon, 17 May 2010 20:29:42 +0000 (22:29 +0200)
NEWS.txt
ccache.c
ccache.h
hashutil.c
manual.txt
test.sh

index 4fbb56aefbeadef4d1e5a52b365c9dd6b2db4e22..878d1fc13b8961f1bb5317730704ec0dab69279c 100644 (file)
--- 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`.
 
index e2386c1f438dab5ade477f548a0054d9eb0d0dc3..c1b3b2c885c9fc3350e77ba99eccc66fc8b0480f 100644 (file)
--- 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);
        }
index 328cf0f56292c130c57991355de2c05f58495118..627973426bec48752b8b92fd4ba79cb36af198c4 100644 (file)
--- 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);
index 7d71e76e93ac48faea98174b313d61bc2ad62f4f..06c03eca0554f9e1e7d3f978af11b5c6aee28206 100644 (file)
@@ -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)
index 53abe5bdaa47cbff2ed6ced3f75bcb3eb854ec20..76cf26b26fd60a4dc7bb73d3bd9d02e888b5c43c 100644 (file)
@@ -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 067a1b15d42f422289b94b9baf23593eacb69782..34a2a2f806ca8188b50b54adc694719ae3fe08cc 100755 (executable)
--- 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 <<EOF >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 <<EOF >file.h
+#define file __FILE__
+int test;
+EOF
+    backdate file.h
+    cat <<EOF >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 <<EOF >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 <<EOF >time.h
+#define time __TIME__
+int test;
+EOF
+    backdate time.h
+    cat <<EOF >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 <<EOF >new.c
+#include "new.h"
+EOF
+    cat <<EOF >new.h
+int test;
+EOF
+    touchy_compiler=touchy-compiler.sh
+    cat <<EOF >$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 <<EOF >new.c
+#include "new.h"
+EOF
+    cat <<EOF >new.h
+int test;
+EOF
+    touchy_compiler=touchy-compiler.sh
+    cat <<EOF >$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