From: Joel Rosdahl Date: Sun, 11 Mar 2018 08:19:52 +0000 (+0100) Subject: Don’t apply Clang workaround for PCH dependencies for other compilers X-Git-Tag: v3.4.2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=058771c571d0ca76e47b58824413ed59216d6f0f;p=thirdparty%2Fccache.git Don’t apply Clang workaround for PCH dependencies for other compilers Closes #235. --- diff --git a/doc/NEWS.adoc b/doc/NEWS.adoc index 75324208b..c71921795 100644 --- a/doc/NEWS.adoc +++ b/doc/NEWS.adoc @@ -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 ------------ diff --git a/src/ccache.c b/src/ccache.c index 860929cb3..afa7adc5d 100644 --- a/src/ccache.c +++ b/src/ccache.c @@ -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. diff --git a/src/ccache.h b/src/ccache.h index dec11fa21..b4df27217 100644 --- a/src/ccache.h +++ b/src/ccache.h @@ -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 diff --git a/src/manifest.c b/src/manifest.c index 5cd3ead2a..02df21958 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -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; }