aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-08-29 02:13:00 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-08-29 02:13:00 +0200
commitf0b7196db8c4dd34c4b2247943e4dac44864b89c (patch)
tree2f8106ec3532a69a627fe6539b539d8bd61783b5
parentb527b31bb74ead51260f5bcf7915e6678943993e (diff)
Add diagnostics color support on Windows (GH issue #312)
Note that currently this has to be enabled with an explicit --diag-color option. In the future the plan is to enable it by default if supported.
-rw-r--r--libbuild2/cc/common.cxx47
-rw-r--r--libbuild2/diagnostics.cxx40
-rw-r--r--libbuild2/utility.hxx6
3 files changed, 66 insertions, 27 deletions
diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx
index 07a4d48..2f428c3 100644
--- a/libbuild2/cc/common.cxx
+++ b/libbuild2/cc/common.cxx
@@ -1618,9 +1618,35 @@ namespace build2
{
case compiler_class::msvc:
{
- // Note: see init_diag logic if enabling anything here (probably
- // need an "override disable" mode or some such).
+ // MSVC has the /diagnostics: option which has an undocumented value
+ // `color`. It's unclear from which version of MSVC this value is
+ // supported, but it works in 17.0, so let's start from there.
//
+ // Note that there is currently no way to disable color in the MSVC
+ // diagnostics specifically (the /diagnostics:* option values are
+ // cumulative and there doesn't seem to be a `color-` value). This
+ // is probably not a big deal since one can just disable the color
+ // globally (--no-diag-color).
+ //
+ // Note that clang-cl appears to use -fansi-escape-codes. See GH
+ // issue #312 for background.
+ //
+ if (show_diag_color ())
+ {
+ if (cvariant.empty () &&
+ (cmaj > 19 || (cmaj == 19 && cmin >= 30)))
+ {
+ // Check for the prefix in case /diagnostics:color- gets added
+ // eventually.
+ //
+ if (!find_option_prefixes ({"/diagnostics:color",
+ "-diagnostics:color"}, args))
+ {
+ args.push_back ("/diagnostics:color");
+ }
+ }
+ }
+
break;
}
case compiler_class::gcc:
@@ -1628,13 +1654,18 @@ namespace build2
// Enable/disable diagnostics color unless a custom option is
// specified.
//
- // Supported from GCC 4.9 and (at least) from Clang 3.5. Clang
- // supports -f[no]color-diagnostics in addition to the GCC's
- // spelling.
+ // Supported from GCC 4.9 (8.1 on Windows) and (at least) from Clang
+ // 3.5. Clang supports -f[no]color-diagnostics in addition to the
+ // GCC's spelling.
//
- if (ctype == compiler_type::gcc ? cmaj > 4 || (cmaj == 4 && cmin >= 9) :
- ctype == compiler_type::clang ? cmaj > 3 || (cmaj == 3 && cmin >= 5) :
- false)
+ if (
+#ifndef _WIN32
+ ctype == compiler_type::gcc ? cmaj > 4 || (cmaj == 4 && cmin >= 9) :
+#else
+ ctype == compiler_type::gcc ? cmaj > 8 || (cmaj == 8 && cmin >= 1) :
+#endif
+ ctype == compiler_type::clang ? cmaj > 3 || (cmaj == 3 && cmin >= 5) :
+ false)
{
if (!(find_option_prefix ("-fdiagnostics-color", args) ||
find_option ("-fno-diagnostics-color", args) ||
diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx
index e164f10..4a46756 100644
--- a/libbuild2/diagnostics.cxx
+++ b/libbuild2/diagnostics.cxx
@@ -3,9 +3,10 @@
#include <libbuild2/diagnostics.hxx>
-#include <cstring> // strcmp(), strchr(), memcpy()
+#include <cstring> // strchr(), memcpy()
#include <cstdlib> // getenv()
+#include <libbutl/fdstream.hxx> // fdterm_color()
#include <libbutl/process-io.hxx>
#include <libbuild2/scope.hxx>
@@ -30,7 +31,7 @@ namespace build2
bool diag_no_line = false;
bool diag_no_column = false;
- optional<const char*> stderr_term = nullopt;
+ bool stderr_term = false;
bool stderr_term_color = false;
void
@@ -50,29 +51,38 @@ namespace build2
diag_color_option = c;
diag_no_line = nl;
diag_no_column = nc;
+ stderr_term = st;
if (st)
{
- stderr_term = std::getenv ("TERM");
-
- stderr_term_color =
+ // @@ TMP: eventually we want to enable on Windows by default.
+ //
#ifdef _WIN32
- // For now we disable color on Windows since it's unclear if/where/how
- // it is supported. Maybe one day someone will figure this out.
+ if (c && *c)
+ {
+#endif
+ stderr_term_color = fdterm_color (stderr_fd (), !c || *c /* enable */);
+
+ // If the user specified --diag-color on POSIX we will trust the color
+ // is supported (e.g., wrong TERM value, etc).
//
- false
+ if (!stderr_term_color && c && *c)
+ {
+#ifdef _WIN32
+ fail << "unable to enable diagnostics color support for stderr";
#else
- // This test was lifted from GCC (Emacs shell sets TERM=dumb).
- //
- *stderr_term != nullptr && strcmp (*stderr_term, "dumb") != 0
+ stderr_term_color = true;
+#endif
+ }
+
+#ifdef _WIN32
+ }
+ else
+ stderr_term_color = false;
#endif
- ;
}
else
- {
- stderr_term = nullopt;
stderr_term_color = false;
- }
}
// Stream verbosity.
diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx
index 43cb904..f37fc54 100644
--- a/libbuild2/utility.hxx
+++ b/libbuild2/utility.hxx
@@ -149,11 +149,9 @@ namespace build2
LIBBUILD2_SYMEXPORT extern bool diag_no_line; // --no-line
LIBBUILD2_SYMEXPORT extern bool diag_no_column; // --no-column
- // If stderr is not a terminal, then the value is absent (so can be used as
- // bool). Otherwise, it is the value of the TERM environment variable (which
- // can be NULL).
+ // True if stderr is a terminal.
//
- LIBBUILD2_SYMEXPORT extern optional<const char*> stderr_term;
+ LIBBUILD2_SYMEXPORT extern bool stderr_term;
// True if the color can be used on the stderr terminal.
//