On Friday 29 of November 2013, Lubos Lunak wrote: > Hello, > > the attached patch adds ccache support for compiler color diagnostics > (also reported by somebody as #10075).
Ping? Any "official" comments on the patch? I've been using the patch for half a year by now without problems. > > Clang automatically uses colors for output automatically if used in > terminal. Ccache's redirecting to a file disables this. GCC 4.8 has got a > similar support, except that it apparently requires also $GCC_COLORS or an > explicit option. > > The patch detects if the compiler would use colors if used without ccache > and explicitly forces an option to achieve this. Note that I do not have > GCC 4.8 here, so I tested with Clang's alias and the GCC_COLORS support is > done based on documentation. > > Caveats: > > - GCC developers decided to roll their own name for the option when > introducing it. Clang has an alias for the GCC way, but versions predating > that obviously can't support it, so it's necessary to detect the compiler. > As ccache doesn't do that (and I don't find it worth much effort, as it > can't be 100% reliable anyway), the code merely guesses from the binary > name. If the compiler used will be e.g. the 'cc' symlink, there'll be no > colors. No big deal. > > - Since the stderr is different, obviously compiling with and without > colors has different results as well. That means that such a compile > is "duplicated". It's hopefully not such a common case, although it's > perfectly possible. I don't know if it's worth the effort to try to be > smart here. A possibly simple improvement could be to search the cache with > and without the option set and if stderr is empty, reuse the result > regardless of the option. I'm not quite sure where exactly this should > happen in the code. > > I expect it'd make sense to add $CCACHE_NOCOLORS to disable this support? > > I can also create manpage section for this color support, but I first > wanted to check here with the code. -- Lubos Lunak
From cacb14929748ae93eacefcfa194aa93689d217eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <l.lu...@centrum.cz> Date: Fri, 29 Nov 2013 12:14:03 +0100 Subject: [PATCH] support compiler color diagnostics if possible Clang and GCC (starting with 4.9) support color output if possible, but since ccache redirects stderr to a file, they detect the output is not a terminal and do not enable colors. Try to detect if colors would be used and force colors explicitly. Caveats: - Compiles with and without colors are considered different from each other (so they are "duplicated"). - GCC decided to roll its own name for the option, so it's necessary to guess which compiler is actually used. --- ccache.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/ccache.c b/ccache.c index c395fad..e122c50 100644 --- a/ccache.c +++ b/ccache.c @@ -1065,6 +1065,24 @@ hash_compiler(struct mdfour *hash, struct stat *st, const char *path, } /* + * 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 @@ calculate_common_hash(struct args *args, struct mdfour *hash) } 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); + } + } } /* @@ -1633,6 +1660,13 @@ is_precompiled_header(const char *path) || str_eq(get_extension(path), ".pth"); } +static bool color_output_possible() +{ + const char* term_env = getenv("TERM"); + + return isatty(STDERR_FILENO) && 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 @@ -1661,6 +1695,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, int argc; char **argv; bool result = true; + bool found_color_diagnostics = false; expanded_args = args_copy(args); stripped_args = args_init(0, NULL); @@ -2017,6 +2052,26 @@ cc_process_args(struct args *args, struct args **preprocessor_args, 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")) { + if (color_output_possible()) { + /* Output is redirected, so color output must be forced. */ + args_add(stripped_args, "-fdiagnostics-color=always"); + cc_log("Automatically forcing colors"); + } + 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 @@ -2307,6 +2362,28 @@ 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_add(stripped_args, "-fcolor-diagnostics"); + cc_log("Automatically enabling colors"); + } else if (compiler_is_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 colors. + */ + 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. */ if (generating_dependencies) { -- 1.8.1.4
_______________________________________________ ccache mailing list ccache@lists.samba.org https://lists.samba.org/mailman/listinfo/ccache