From f7d610985554e52c0ce303675786417c03b11e03 Mon Sep 17 00:00:00 2001 From: Andrew Adams Date: Mon, 24 Aug 2026 15:10:21 -0700 Subject: [PATCH] Only colorize the profiler report when writing to a terminal The report gated ANSI color escapes on the TERM environment variable alone. CI and other redirected environments commonly set TERM=xterm-256color while stdout is a pipe or file, so the escapes were written straight into the captured log as noise. Also require isatty(STDOUT_FILENO) (the report is printed via halide_print, whose default writes to stdout), and honor the NO_COLOR convention. The no-color path already emits plain box-drawing separators, so the table stays well-formed. Co-Authored-By: Claude Opus 4.8 --- src/runtime/profiler_common.cpp | 14 ++++++++++---- src/runtime/runtime_internal.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/runtime/profiler_common.cpp b/src/runtime/profiler_common.cpp index 2384c38f4aca..0d0d27e45593 100644 --- a/src/runtime/profiler_common.cpp +++ b/src/runtime/profiler_common.cpp @@ -513,11 +513,17 @@ ALWAYS_INLINE bool counter_is_approximate(const halide_profiler_func_stats *fs, WEAK void halide_profiler_report_unlocked(void *user_context, halide_profiler_state *s) { StringStreamPrinter<1024> sstr(user_context); - bool support_colors = false; + // Emit ANSI color escapes only when the report is going to an actual + // color-capable terminal. Checking TERM alone isn't enough: CI and other + // redirected environments often set TERM=xterm-256color while stdout is a + // pipe or file, which would splatter escape codes into the captured log. + // The report is printed via halide_print, whose default writes to stdout. + const char *no_color = getenv("NO_COLOR"); const char *term = getenv("TERM"); - if (term && (strstr(term, "color") || strstr(term, "xterm"))) { - support_colors = true; - } + bool support_colors = + !(no_color && no_color[0]) && + term && (strstr(term, "color") || strstr(term, "xterm")) && + isatty(STDOUT_FILENO); // Column-aligned rows are produced from `const char *` templates. A // run of an uppercase marker char is a slot — the marker picks the diff --git a/src/runtime/runtime_internal.h b/src/runtime/runtime_internal.h index fdf951c7dc87..11c63c94b274 100644 --- a/src/runtime/runtime_internal.h +++ b/src/runtime/runtime_internal.h @@ -121,6 +121,7 @@ int fclose(void *); int close(int); size_t fwrite(const void *, size_t, size_t, void *); ssize_t write(int fd, const void *buf, size_t bytes); +int isatty(int fd); int remove(const char *pathname); int ioctl(int fd, unsigned long request, ...); char *strncpy(char *dst, const char *src, size_t n);