]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Don’t apply Clang workaround for PCH dependencies for other compilers
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 11 Mar 2018 08:19:52 +0000 (09:19 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sun, 11 Mar 2018 08:19:52 +0000 (09:19 +0100)
Closes #235.

doc/NEWS.adoc
src/ccache.c
src/ccache.h
src/manifest.c

index 75324208b4d4a4c030880cee165c7ecc353e4dde..c71921795606cee1cfebe3a90a26a470ddac27fd 100644 (file)
@@ -14,6 +14,10 @@ Bug fixes
 
 - Fixed build failure when using the bundled zlib sources.
 
+- ccache 3.3.5 added a workaround for not triggering Clang errors when a
+  precompiled header's dependency has an updated timestamp (but identical
+  content). That workaround is now only applied when the compiler is Clang.
+
 
 ccache 3.4.1
 ------------
index 860929cb3a410228ae80448e0873f7d212d6c62e..afa7adc5dfb9054755233101a6903198e4b830e9 100644 (file)
@@ -216,6 +216,10 @@ char *stats_file = NULL;
 // Whether the output is a precompiled header.
 bool output_is_precompiled_header = false;
 
+// Compiler guessing is currently only based on the compiler name, so nothing
+// should hard-depend on it if possible.
+enum guessed_compiler guessed_compiler = GUESSED_UNKNOWN;
+
 // Profile generation / usage information.
 static char *profile_dir = NULL;
 static bool profile_use = false;
@@ -469,41 +473,20 @@ clean_up_internal_tempdir(void)
        closedir(dir);
 }
 
-// Note that these compiler checks are unreliable, so nothing should
-// hard-depend on them.
-
-static bool
-compiler_is_clang(struct args *args)
-{
-       char *name = basename(args->argv[0]);
-       bool result = strstr(name, "clang") != NULL;
-       free(name);
-       return result;
-}
-
-static bool
-compiler_is_gcc(struct args *args)
-{
-       char *name = basename(args->argv[0]);
-       bool result = strstr(name, "gcc") || strstr(name, "g++");
-       free(name);
-       return result;
-}
-
-static bool
-compiler_is_nvcc(struct args *args)
-{
-       char *name = basename(args->argv[0]);
-       bool result = strstr(name, "nvcc") != NULL;
-       free(name);
-       return result;
-}
-
-static bool
-compiler_is_pump(struct args *args)
+static enum guessed_compiler
+guess_compiler(const char *path)
 {
-       char *name = basename(args->argv[0]);
-       bool result = str_eq(name, "pump") || str_eq(name, "distcc-pump");
+       char *name = basename(path);
+       enum guessed_compiler result = GUESSED_UNKNOWN;
+       if (strstr(name, "clang")) {
+               result = GUESSED_CLANG;
+       } else if (strstr(name, "gcc") || strstr(name, "g++")) {
+               result = GUESSED_GCC;
+       } else if (strstr(name, "nvcc")) {
+               result = GUESSED_NVCC;
+       } else if (str_eq(name, "pump") || str_eq(name, "distcc-pump")) {
+               result = GUESSED_PUMP;
+       }
        free(name);
        return result;
 }
@@ -1225,7 +1208,7 @@ to_cache(struct args *args)
 
        // distcc-pump outputs lines like this:
        // __________Using # distcc servers in pump mode
-       if (st.st_size != 0 && !compiler_is_pump(args)) {
+       if (st.st_size != 0 && guessed_compiler != GUESSED_PUMP) {
                cc_log("Compiler produced stdout");
                stats_update(STATS_STDOUT);
                tmp_unlink(tmp_stdout);
@@ -1437,7 +1420,7 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash)
        } else {
                hash_delimiter(hash, "cpp");
                if (!process_preprocessed_file(hash, path_stdout,
-                                              compiler_is_pump(args))) {
+                                              guessed_compiler == GUESSED_PUMP)) {
                        stats_update(STATS_ERROR);
                        failed();
                }
@@ -1674,7 +1657,7 @@ calculate_common_hash(struct args *args, struct mdfour *hash)
        }
 
        // Possibly hash GCC_COLORS (for color diagnostics).
-       if (compiler_is_gcc(args)) {
+       if (guessed_compiler == GUESSED_GCC) {
                const char *gcc_colors = getenv("GCC_COLORS");
                if (gcc_colors) {
                        hash_delimiter(hash, "gcccolors");
@@ -1698,7 +1681,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode)
 
        // clang will emit warnings for unused linker flags, so we shouldn't skip
        // those arguments.
-       int is_clang = compiler_is_clang(args);
+       int is_clang = guessed_compiler == GUESSED_CLANG;
 
        // First the arguments.
        for (int i = 1; i < args->argc; i++) {
@@ -1949,13 +1932,17 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest)
                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");
+       // If we're using Clang, we can't trust a precompiled header object based on
+       // running the preprocessor since clang will produce a fatal error when the
+       // precompiled header is used and one of the included files has an updated
+       // timestamp:
+       //
+       //     file 'foo.h' has been modified since the precompiled header 'foo.pch'
+       //     was built
+       if (guessed_compiler == GUESSED_CLANG
+           && output_is_precompiled_header
+           && mode == FROMCACHE_CPP_MODE) {
+               cc_log("Not considering cached precompiled header in preprocessor mode");
                return;
        }
 
@@ -2232,8 +2219,8 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                }
 
                // Handle cuda "-optf" and "--options-file" argument.
-               if ((str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file"))
-                   && compiler_is_nvcc(args)) {
+               if (guessed_compiler == GUESSED_NVCC
+                   && (str_eq(argv[i], "-optf") || str_eq(argv[i], "--options-file"))) {
                        if (i == argc - 1) {
                                cc_log("Expected argument after %s", argv[i]);
                                stats_update(STATS_ARGS);
@@ -2369,7 +2356,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
                }
 
                // Alternate form of -o with no space. Nvcc does not support this.
-               if (str_startswith(argv[i], "-o") && !compiler_is_nvcc(args)) {
+               if (str_startswith(argv[i], "-o") && guessed_compiler != GUESSED_NVCC) {
                        output_obj = make_relative_path(x_strdup(&argv[i][2]));
                        continue;
                }
@@ -2984,12 +2971,12 @@ cc_process_args(struct args *args, struct args **preprocessor_args,
        // Since output is redirected, compilers will not color their output by
        // default, so force it explicitly if it would be otherwise done.
        if (!found_color_diagnostics && color_output_possible()) {
-               if (compiler_is_clang(args)) {
+               if (guessed_compiler == GUESSED_CLANG) {
                        if (!str_eq(actual_language, "assembler")) {
                                args_add(stripped_args, "-fcolor-diagnostics");
                                cc_log("Automatically enabling colors");
                        }
-               } else if (compiler_is_gcc(args)) {
+               } else if (guessed_compiler == GUESSED_GCC) {
                        // GCC has it since 4.9, but that'd require detecting what GCC version is
                        // used for the actual compile. However it requires also GCC_COLORS to be
                        // set (and not empty), so use that for detecting if GCC would use
@@ -3309,6 +3296,8 @@ ccache(int argc, char *argv[])
 
        conf->limit_multiple = MIN(MAX(conf->limit_multiple, 0.0), 1.0);
 
+       guessed_compiler = guess_compiler(orig_args->argv[0]);
+
        // Arguments (except -E) to send to the preprocessor.
        struct args *preprocessor_args;
        // Arguments to send to the real compiler.
index dec11fa21d720cc2ca80275420b60465c5dd3b44..b4df272174d30457023c53326f1394fa4778cf05 100644 (file)
@@ -58,6 +58,16 @@ enum stats {
        STATS_END
 };
 
+enum guessed_compiler {
+       GUESSED_CLANG,
+       GUESSED_GCC,
+       GUESSED_NVCC,
+       GUESSED_PUMP,
+       GUESSED_UNKNOWN
+};
+
+extern enum guessed_compiler guessed_compiler;
+
 #define SLOPPY_INCLUDE_FILE_MTIME 1
 #define SLOPPY_INCLUDE_FILE_CTIME 2
 #define SLOPPY_FILE_MACRO 4
index 5cd3ead2ad76c9cda88e68c8d7201580f083b601..02df219585037065b82de38af2ef964368998f4f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009-2016 Joel Rosdahl
+// Copyright (C) 2009-2018 Joel Rosdahl
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
@@ -383,7 +383,9 @@ verify_object(struct conf *conf, struct manifest *mf, struct object *obj,
 
                // 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) {
+               if (guessed_compiler == GUESSED_CLANG
+                   && output_is_precompiled_header
+                   && fi->mtime != st->mtime) {
                        cc_log("Precompiled header includes %s, which has a new mtime", path);
                        return 0;
                }