--- ccache.c +++ ccache.c @@ -1065,6 +1065,24 @@ } /* + * Note that these compiler checks are unreliable, so nothing should hard-depend on them. + */ + +static bool compiler_is_clang() +{ + const char* name = strrchr( orig_args->argv[ 0 ], '/' ); + name = name ? name + 1 : orig_args->argv[ 0 ]; + return strstr( name, "clang" ) != NULL; +} + +static bool compiler_is_gcc() +{ + const char* name = strrchr(orig_args->argv[ 0 ], '/' ); + name = name ? name + 1 : orig_args->argv[ 0 ]; + return strstr(name, "gcc") != NULL || strstr(name, "g++") != NULL; +} + +/* * Update a hash sum with information common for the direct and preprocessor * modes. */ @@ -1128,6 +1146,15 @@ } free(p); } + + /* Possibly hash GCC_COLORS (for color diagnostics). */ + if (compiler_is_gcc()) { + const char* gcc_colors = getenv("GCC_COLORS"); + if (gcc_colors != NULL) { + hash_delimiter(hash,"gcccolors"); + hash_string(hash, gcc_colors); + } + } } /* @@ -1626,6 +1653,13 @@ || str_eq(get_extension(path), ".pth"); } +static bool color_output_possible() +{ + const char* term_env = getenv("TERM"); + + return term_env && strcasecmp(term_env, "DUMB") != 0; +} + /* * Process the compiler options into options suitable for passing to the * preprocessor and the real compiler. The preprocessor options don't include @@ -1654,6 +1688,7 @@ int argc; char **argv; bool result = true; + bool found_color_diagnostics = false; expanded_args = args_copy(args); stripped_args = args_init(0, NULL); @@ -2010,6 +2045,27 @@ free(arg); } + if (str_eq(argv[i], "-fcolor-diagnostics") + || str_eq(argv[i], "-fno-color-diagnostics") + || str_eq(argv[i], "-fdiagnostics-color") + || str_eq(argv[i], "-fdiagnostics-color=always") + || str_eq(argv[i], "-fno-diagnostics-color") + || str_eq(argv[i], "-fdiagnostics-color=never")) { + args_add(stripped_args, argv[i]); + found_color_diagnostics = true; + continue; + } + if (str_eq(argv[i], "-fdiagnostics-color=auto")) { + + /* auto means to use colours only when standard error is a terminal */ + if (color_output_possible()) { + /* Since the condition is verified, we force the colour output */ + args_add(stripped_args, "-fdiagnostics-color"); + found_color_diagnostics = true; + } + continue; + } + /* * Options taking an argument that we may want to rewrite to relative paths * to get better hit rate. A secondary effect is that paths in the standard @@ -2298,6 +2354,28 @@ args_add(cpp_args, explicit_language); } + /* + * 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_add(stripped_args, "-fcolor-diagnostics"); + cc_log("Automatically enabling colors"); + } else if (compiler_is_gcc()) { + /* + * GCC has colour support since 4.9. Adding the option to an + * earlier version of GCC will make the compiler fail. + * This test enables colours if GCC_COLORS is present in the + * environment, but does not check if diagnostics-color is available. + */ + if (getenv("GCC_COLORS") != NULL && getenv("GCC_COLORS")[ 0 ] != '\0') { + args_add(stripped_args, "-fdiagnostics-color"); + cc_log("Automatically enabling colors"); + } + } + } + /* * Add flags for dependency generation only to the preprocessor command line. */