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

Reply via email to