]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Add support for using precompiled headers if -fpch-preprocess is used
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 21 Aug 2010 14:46:51 +0000 (16:46 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 21 Aug 2010 14:46:51 +0000 (16:46 +0200)
MANUAL.txt
ccache.c
ccache.h
hashutil.c
test.sh

index 366816722ffabd026a0ec1559a5241a7fa81c2d0..e20c573fb6c132c7b74a99ee1bef823fd64dd5a3 100644 (file)
@@ -548,6 +548,24 @@ The drawbacks of using *CCACHE_BASEDIR* are:
   ``cd'' command in GDB.
 
 
+Precompiled headers
+-------------------
+
+ccache has support for GCC's precompiled headers. However, you currently have
+to do two things to make it work:
+
+* You must add the *-fpch-preprocess* option when compiling, as this option
+  makes it possible for ccache to correctly detect the header file in the
+  preprocessor output. If you don't do this, either the non-preprocessed
+  version of the header file will be used (if available) or ccache will fall
+  back to running the real compiler and increase the statistics counter
+  ``preprocessor error'' (if the non-preprocessed header file is not
+  available).
+* You must set *CCACHE_SLOPPINESS* to *time_macros*. The reason is that ccache
+  can't tell whether *\_\_TIME\__* or *\_\_DATE__* is used when using a
+  precompiled header.
+
+
 Sharing a cache
 ---------------
 
@@ -710,8 +728,6 @@ problems and what may be done to increase the hit rate:
 * If ``multiple source files'' has been incremented, it's an indication that
   the compiler has been invoked on several source code files at once. ccache
   doesn't support that. Compile the source code files separately if possible.
-* If ``preprocessor error'' has been incremented, one possible reason is that
-  precompiled headers are being used. ccache currently doesn't handle that.
 * If ``unsupported compiler option'' has been incremented, enable debug logging
   and check which option was rejected.
 
index 2242fa3f36009440be3da83c687cbd930605b521..83d134f22bfc367f44c3213fa58fe144949f21c7 100644 (file)
--- a/ccache.c
+++ b/ccache.c
@@ -371,20 +371,27 @@ remember_include_file(char *path, size_t path_len)
                cc_log("Include file %s too new", path);
                goto failure;
        }
-       if (st.st_size > 0) {
-               data = x_fmmap(path, &st.st_size, "include file");
-               if (data == (char *)-1) {
-                       goto failure;
-               }
-               source = data;
-       } else {
-               source = "";
-       }
 
        hash_start(&fhash);
-       result = hash_source_code_string(&fhash, source, st.st_size, path);
-       if (result & HASH_SOURCE_CODE_ERROR || result & HASH_SOURCE_CODE_FOUND_TIME) {
-               goto failure;
+
+       if (is_precompiled_header(path)) {
+               hash_file(&fhash, path);
+       } else {
+               if (st.st_size > 0) {
+                       data = x_fmmap(path, &st.st_size, "include file");
+                       if (data == (char *)-1) {
+                               goto failure;
+                       }
+                       source = data;
+               } else {
+                       source = "";
+               }
+
+               result = hash_source_code_string(&fhash, source, st.st_size, path);
+               if (result & HASH_SOURCE_CODE_ERROR
+                   || result & HASH_SOURCE_CODE_FOUND_TIME) {
+                       goto failure;
+               }
        }
 
        h = x_malloc(sizeof(*h));
@@ -462,6 +469,7 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
                 *
                 *   # N "file"
                 *   # N "file" N
+                *   #pragma GCC pch_preprocess "file"
                 *
                 * HP's compiler:
                 *
@@ -473,6 +481,9 @@ process_preprocessed_file(struct mdfour *hash, const char *path)
                if (q[0] == '#'
                        /* GCC: */
                    && ((q[1] == ' ' && q[2] >= '0' && q[2] <= '9')
+                       /* GCC precompiled header: */
+                       || (q[1] == 'p'
+                           && str_startswith(&q[2], "ragma GCC pch_preprocess "))
                        /* HP: */
                        || (q[1] == 'l' && q[2] == 'i' && q[3] == 'n' && q[4] == 'e'
                            && q[5] == ' '))
@@ -1292,6 +1303,12 @@ find_compiler(int argc, char **argv)
        orig_args->argv[0] = compiler;
 }
 
+int
+is_precompiled_header(const char *path)
+{
+       return str_eq(get_extension(path), ".gch");
+}
+
 /*
  * Process the compiler options into options suitable for passing to the
  * preprocessor and the real compiler. The preprocessor options don't include
@@ -1371,6 +1388,15 @@ cc_process_args(struct args *orig_args, struct args **preprocessor_args,
                        }
                }
 
+               if (str_eq(argv[i], "-fpch-preprocess")
+                   && !(sloppiness & SLOPPY_TIME_MACROS)) {
+                       cc_log("You have to specify \"time_macros\" sloppiness when using"
+                              " -fpch-preprocess");
+                       stats_update(STATS_UNSUPPORTED);
+                       result = 0;
+                       goto out;
+               }
+
                /* we must have -c */
                if (str_eq(argv[i], "-c")) {
                        args_add(stripped_args, argv[i]);
index cb5bb3b852011c96feea38fda8ec28755af770bd..58f2cd4745302bfbe003048886defbc89f3d40bb 100644 (file)
--- a/ccache.h
+++ b/ccache.h
@@ -222,6 +222,7 @@ void lockfile_release(const char *path);
 int cc_process_args(struct args *orig_args, struct args **preprocessor_args,
                     struct args **compiler_args);
 void cc_reset(void);
+int is_precompiled_header(const char *path);
 
 /* ------------------------------------------------------------------------- */
 
index 1f56db79a2aa191b21886d45e0a39b7905009a28..23299d6f7072e440bc347ed07d9e7874c3a98c11 100644 (file)
@@ -219,14 +219,22 @@ hash_source_code_file(struct mdfour *hash, const char *path)
                return HASH_SOURCE_CODE_OK;
        }
 
-       data = x_fmmap(path, &st.st_size, "source code file");
-       if (data == (void *)-1) {
-               return HASH_SOURCE_CODE_ERROR;
-       }
+       if (is_precompiled_header(path)) {
+               if (hash_file(hash, path)) {
+                       return HASH_SOURCE_CODE_OK;
+               } else {
+                       return HASH_SOURCE_CODE_ERROR;
+               }
+       } else {
+               data = x_fmmap(path, &st.st_size, "source code file");
+               if (data == (void *)-1) {
+                       return HASH_SOURCE_CODE_ERROR;
+               }
 
-       result = hash_source_code_string(hash, data, st.st_size, path);
-       x_munmap(data, st.st_size);
-       return result;
+               result = hash_source_code_string(hash, data, st.st_size, path);
+               x_munmap(data, st.st_size);
+               return result;
+       }
 }
 
 int
diff --git a/test.sh b/test.sh
index 60a020ab610c27574a653cdcff2f384e39bfb15d..e23ccd1ccdd05332352465f1250866c2d9d081f2 100755 (executable)
--- a/test.sh
+++ b/test.sh
@@ -1594,6 +1594,64 @@ cleanup_suite() {
     checkstat 'files in cache' 30
 }
 
+pch_suite() {
+    unset CCACHE_NODIRECT
+
+    cat <<EOF >pch.c
+#include "pch.h"
+void *p = NULL;
+EOF
+    cat <<EOF >pch.h
+#include <stdlib.h>
+EOF
+
+    if ! $COMPILER pch.h 2>/dev/null; then
+        return
+    fi
+
+    ##################################################################
+    # Tests for using a .gch.
+
+    rm -f pch.h
+    backdate pch.h.gch
+
+    testname="no -fpch-preprocess"
+    $CCACHE -z >/dev/null
+    $CCACHE $COMPILER -c pch.c 2>/dev/null
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 0
+    checkstat 'preprocessor error' 1
+
+    testname="-fpch-preprocess, no sloppy time macros"
+    $CCACHE -z >/dev/null
+    $CCACHE $COMPILER -c -fpch-preprocess pch.c
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 0
+    checkstat 'unsupported compiler option' 1
+
+    testname="-fpch-preprocess, sloppy time macros"
+    $CCACHE -z >/dev/null
+    CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 1
+    CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+    checkstat 'cache hit (direct)' 1
+    checkstat 'cache hit (preprocessed)' 0
+    checkstat 'cache miss' 1
+
+    testname="-fpch-preprocess, file changed, direct mode"
+    $CCACHE -z >/dev/null
+    echo "updated" >>pch.h.gch # GCC seems to cope with this...
+    backdate pch.h.gch
+    CCACHE_SLOPPINESS=time_macros $CCACHE $COMPILER -c -fpch-preprocess pch.c
+    checkstat 'cache hit (direct)' 0
+    checkstat 'cache hit (preprocessed)' 1
+    checkstat 'cache miss' 0
+}
+
 ######################################################################
 # main program
 
@@ -1642,6 +1700,7 @@ compression
 readonly
 extrafiles
 cleanup
+pch
 "
 
 host_os="`uname -s`"