diff --git a/src/IRPrinter.cpp b/src/IRPrinter.cpp index bb5938fbd745..3a4caa581a66 100644 --- a/src/IRPrinter.cpp +++ b/src/IRPrinter.cpp @@ -561,7 +561,10 @@ IRPrinter::IRPrinter(ostream &s) int val = std::atoi(opt); use_colors = val != 0; } else { - use_colors = supports_ansi(stream); + // Respect NO_COLOR in addition to whether we're writing to a + // terminal, matching the profiler report's color gate. + const char *no_color = getenv("NO_COLOR"); + use_colors = !(no_color && no_color[0]) && supports_ansi(stream); } if (use_colors) { ansi = true; diff --git a/src/LLVM_Runtime_Linker.cpp b/src/LLVM_Runtime_Linker.cpp index dc612a15ddd7..2f90ec424f8c 100644 --- a/src/LLVM_Runtime_Linker.cpp +++ b/src/LLVM_Runtime_Linker.cpp @@ -826,7 +826,7 @@ void add_underscore_to_posix_call(llvm::CallInst *call, llvm::Function *fn, llvm * of mcjit, so we just rewrite uses of these functions to include an * underscore. */ void add_underscores_to_posix_calls_on_windows(llvm::Module *m) { - string posix_fns[] = {"vsnprintf", "open", "close", "write", "fileno"}; + string posix_fns[] = {"vsnprintf", "open", "close", "write", "fileno", "isatty"}; string *posix_fns_begin = posix_fns; string *posix_fns_end = posix_fns + sizeof(posix_fns) / sizeof(posix_fns[0]); diff --git a/src/runtime/profiler_common.cpp b/src/runtime/profiler_common.cpp index 2384c38f4aca..40e105f812e3 100644 --- a/src/runtime/profiler_common.cpp +++ b/src/runtime/profiler_common.cpp @@ -513,10 +513,24 @@ 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; - const char *term = getenv("TERM"); - if (term && (strstr(term, "color") || strstr(term, "xterm"))) { - support_colors = true; + // Decide whether to emit ANSI color escapes. HL_COLORS, if set, is an + // explicit override matching IRPrinter: "0" forces colors off, anything + // else on. Otherwise honor NO_COLOR and auto-detect a 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. + bool support_colors; + const char *hl_colors = getenv("HL_COLORS"); + if (hl_colors) { + support_colors = atoi(hl_colors) != 0; + } else { + const char *no_color = getenv("NO_COLOR"); + const char *term = getenv("TERM"); + 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 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);