// 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;
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;
}
// 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);
} 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();
}
}
// 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");
// 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++) {
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;
}
}
// 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);
}
// 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;
}
// 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
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.