char *stats_file = NULL;
// Whether the output is a precompiled header.
-static bool output_is_precompiled_header = false;
+bool output_is_precompiled_header = false;
// Profile generation / usage information.
static char *profile_dir = NULL;
return;
}
+ // We can't trust the objects based on running the preprocessor
+ // when the output is precompiled headers, as the hash does not
+ // include the mtime of each included header, breaking compilation
+ // with clang when the precompiled header is used after touching
+ // one of the included files.
+ if (output_is_precompiled_header && mode == FROMCACHE_CPP_MODE) {
+ cc_log("Not using preprocessed cached object for precompiled header");
+ return;
+ }
+
struct stat st;
if (stat(cached_obj, &st) != 0) {
cc_log("Object file %s not in cache", cached_obj);
// ccache.c
extern time_t time_of_compilation;
+extern bool output_is_precompiled_header;
void block_signals(void);
void unblock_signals(void);
bool cc_process_args(struct args *args, struct args **preprocessor_args,
return 0;
}
+ // Clang stores the mtime of the included files in the precompiled header,
+ // and will error out if that header is later used without rebuilding.
+ if (output_is_precompiled_header && fi->mtime != st->mtime) {
+ cc_log("Precompiled header includes %s, which has a new mtime", path);
+ return 0;
+ }
+
if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
if (fi->mtime == st->mtime && fi->ctime == st->ctime) {
cc_log("mtime/ctime hit for %s", path);
test_failed "pch.gch missing"
fi
+ # -------------------------------------------------------------------------
+ TEST "Create .gch, include file mtime changed"
+
+ backdate test.h
+ cat <<EOF >pch2.h
+ #include <stdlib.h>
+ #include "test.h"
+EOF
+
+ # Make sure time_of_compilation is at least one second larger than the ctime
+ # of the test.h include, otherwise we might not cache its ctime/mtime.
+ sleep 1
+
+ CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 1
+
+ touch test.h
+ sleep 1
+
+ CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
+ expect_stat 'cache hit (direct)' 0
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 2
+
+ $UNCACHED_COMPILE $SYSROOT -c -include pch2.h pch2.c
+ if [ ! -f pch2.o ]; then
+ test_failed "pch.o missing"
+ fi
+
+ CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines time_macros" $CCACHE_COMPILE $SYSROOT -c pch2.h
+ expect_stat 'cache hit (direct)' 1
+ expect_stat 'cache hit (preprocessed)' 0
+ expect_stat 'cache miss' 2
+
# -------------------------------------------------------------------------
TEST "Use .gch, no -fpch-preprocess, -include, no sloppiness"