From: Joel Rosdahl Date: Sat, 21 Aug 2010 14:46:51 +0000 (+0200) Subject: Add support for using precompiled headers if -fpch-preprocess is used X-Git-Tag: v3.1~65 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d8927d46cbf195de51a19d224d9e3ea4e8915c85;p=thirdparty%2Fccache.git Add support for using precompiled headers if -fpch-preprocess is used --- diff --git a/MANUAL.txt b/MANUAL.txt index 366816722..e20c573fb 100644 --- a/MANUAL.txt +++ b/MANUAL.txt @@ -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. diff --git a/ccache.c b/ccache.c index 2242fa3f3..83d134f22 100644 --- 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]); diff --git a/ccache.h b/ccache.h index cb5bb3b85..58f2cd474 100644 --- 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); /* ------------------------------------------------------------------------- */ diff --git a/hashutil.c b/hashutil.c index 1f56db79a..23299d6f7 100644 --- a/hashutil.c +++ b/hashutil.c @@ -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 60a020ab6..e23ccd1cc 100755 --- a/test.sh +++ b/test.sh @@ -1594,6 +1594,64 @@ cleanup_suite() { checkstat 'files in cache' 30 } +pch_suite() { + unset CCACHE_NODIRECT + + cat <pch.c +#include "pch.h" +void *p = NULL; +EOF + cat <pch.h +#include +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`"