``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
---------------
* 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.
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));
*
* # N "file"
* # N "file" N
+ * #pragma GCC pch_preprocess "file"
*
* HP's compiler:
*
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] == ' '))
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
}
}
+ 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]);
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);
/* ------------------------------------------------------------------------- */
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
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
readonly
extrafiles
cleanup
+pch
"
host_os="`uname -s`"