Re: Support for color diagnostics

Lubos Lunak <[email protected]>
Newsgroups gmane.comp.compilers.ccache
Message-ID <[email protected]>
On Tuesday 18 of February 2014, interfaSys Sàrl wrote:
> Hello,
>
> I've just tested the patch with a patched gcc48 with -fdiagnostics-color
> support on FreeBSD 9 and it works with one exception.
>
> GCC's documentations says:
> "‘auto’ means to use color only when the standard error is a terminal"
>
> So, if my understanding is correct, this means that, when using
> -fdiagnostics-color=auto , I should be seeing colours when using the
> terminal and indeed, that's the normal behaviour when ccache falls back to
> the compiler (I see colours).
>
> With that patch, I don't see the colours in auto mode. It only works in
> always mode.

 I see. How about this patch?

-- 
 Lubos Lunak

_______________________________________________
ccache mailing list
[email protected]
https://lists.samba.org/mailman/listinfo/ccache
0001-support-compiler-color-diagnostics-if-possible.patch (text/x-diff, 4.6 KB)
From cacb14929748ae93eacefcfa194aa93689d217eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.