]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Correctly handle direct mode hit, missing object file and differing cpp hash
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 5 Dec 2009 13:09:21 +0000 (14:09 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Tue, 5 Jan 2010 17:53:02 +0000 (18:53 +0100)
ccache.c
hashutil.c
hashutil.h
manifest.h

index 98926853b8fe4e2259d65e3d71d3f80bd04af6c7..ce78850b6a105bc1195d12876c760de1916d3463 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -1402,6 +1402,7 @@ static void ccache(int argc, char *argv[])
        time_t t;
        struct tm *tm;
        int put_object_in_manifest = 0;
+       struct file_hash *object_hash_from_manifest = NULL;
 
        t = time(NULL);
        tm = localtime(&t);
@@ -1469,6 +1470,9 @@ static void ccache(int argc, char *argv[])
                         * so don't readd it later.
                         */
                        put_object_in_manifest = 0;
+
+                       object_hash_from_manifest = object_hash;
+                       object_hash = NULL;
                } else {
                        /* Add object to manifest later. */
                        put_object_in_manifest = 1;
@@ -1481,6 +1485,31 @@ static void ccache(int argc, char *argv[])
         */
        find_hash(stripped_args, FINDHASH_CPP_MODE);
 
+       if (object_hash_from_manifest
+           && !file_hashes_equal(object_hash_from_manifest, object_hash)) {
+               /*
+                * The hash from manifest differs from the hash of the
+                * preprocessor output. This could be because:
+                *
+                * - The preprocessor produces different output for the same
+                *   input (not likely).
+                * - There's a bug in ccache (maybe incorrect handling of
+                *   compiler arguments).
+                * - The user has used a different CCACHE_BASEDIR (most
+                *   likely).
+                *
+                * The best thing here would probably be to remove the hash
+                * entry from the manifest. For now, we use a simpler method:
+                * just remove the manifest file.
+                */
+               cc_log("Hash from manifest doesn't match preprocessor output\n");
+               cc_log("Likely reason: different CCACHE_BASEDIRs used\n");
+               cc_log("Removing manifest as a safety measure\n");
+               unlink(manifest_path);
+
+               put_object_in_manifest = 1;
+       }
+
        /* if we can return from cache at this point then do */
        from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest);
 
index 5989f769baf80faec0e4bda4be937fc62b8834ef..3e4921647dfb066f4cdc51feb8c53de471c49b12 100644 (file)
@@ -12,3 +12,9 @@ int strings_equal(void *str1, void *str2)
 {
        return strcmp((const char *)str1, (const char *)str2) == 0;
 }
+
+int file_hashes_equal(struct file_hash *fh1, struct file_hash *fh2)
+{
+       return memcmp(fh1->hash, fh2->hash, 16) == 0
+               && fh1->size == fh2->size;
+}
index 2fdd63e2faaeba0b841f4a46fc4ceabf7efb276f..e562519ed25c67ce050d23f61f0dd84e4047ce2d 100644 (file)
@@ -1,7 +1,16 @@
 #ifndef HASHUTIL_H
 #define HASHUTIL_H
 
+#include <inttypes.h>
+
+struct file_hash
+{
+       uint8_t hash[16];
+       uint32_t size;
+};
+
 unsigned int hash_from_string(void *str);
 int strings_equal(void *str1, void *str2);
+int file_hashes_equal(struct file_hash *fh1, struct file_hash *fh2);
 
 #endif
index b80014e8e60170aad4ed32b85f9fe8d37e28c534..f6e9a4a6394d3653e940de645337862cd7068a6f 100644 (file)
@@ -1,15 +1,9 @@
 #ifndef MANIFEST_H
 #define MANIFEST_H
 
-#include <inttypes.h>
+#include "hashutil.h"
 #include "hashtable.h"
 
-struct file_hash
-{
-       uint8_t hash[16];
-       uint32_t size;
-};
-
 struct file_hash *manifest_get(const char *manifest_path);
 int manifest_put(const char *manifest_path, struct file_hash *object_hash,
                  struct hashtable *included_files);