From b278cefd1c653d031de1004f4254756861f3f75b Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Thu, 11 Apr 2024 17:25:39 -0500 Subject: [PATCH] SCons: Silence msvc output without hiding errors --- platform/windows/detect.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 196beb423f47..9aa32a7b2dbf 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -202,9 +202,7 @@ def get_opts(): BoolVariable("use_asan", "Use address sanitizer (ASAN)", False), BoolVariable("debug_crt", "Compile with MSVC's debug CRT (/MDd)", False), BoolVariable("incremental_link", "Use MSVC incremental linking. May increase or decrease build times.", False), - BoolVariable( - "silence_msvc", "Silence MSVC's stdout to decrease output log bloat. May hide error messages.", False - ), + BoolVariable("silence_msvc", "Silence MSVC's cl/link stdout bloat, redirecting any errors to stderr.", True), ("angle_libs", "Path to the ANGLE static libraries", ""), # Direct3D 12 support. ( @@ -398,16 +396,32 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config): env["MAXLINELENGTH"] = 8192 # Windows Vista and beyond, so always applicable. if env["silence_msvc"]: - env.Prepend(CCFLAGS=[">", "NUL"]) - env.Prepend(LINKFLAGS=[">", "NUL"]) + from tempfile import mkstemp + + old_spawn = env["SPAWN"] + + def spawn_capture(sh, escape, cmd, args, env): + # We only care about cl/link, process everything else as normal. + if args[0] not in ["cl", "link"]: + return old_spawn(sh, escape, cmd, args, env) - # "> NUL" fails if using a tempfile, circumvent by removing the argument altogether. - old_esc_func = env["TEMPFILEARGESCFUNC"] + tmp_stdout, tmp_stdout_name = mkstemp() + os.close(tmp_stdout) + args.append(f">{tmp_stdout_name}") + ret = old_spawn(sh, escape, cmd, args, env) + + try: + with open(tmp_stdout_name, "rt", encoding=sys.stdout.encoding) as tmp_stdout: + # First line is always bloat, subsequent lines are always errors. This filter sends + # either just the errors to stderr, or an empty string to effectively do nothing. + sys.stderr.write("".join(tmp_stdout.readlines()[1:])) + os.remove(tmp_stdout_name) + except OSError: + pass - def trim_nul(arg): - return "" if arg in [">", "NUL"] else old_esc_func(arg) + return ret - env["TEMPFILEARGESCFUNC"] = trim_nul + env["SPAWN"] = spawn_capture if env["debug_crt"]: # Always use dynamic runtime, static debug CRT breaks thread_local.