Run `cmd` in PROJECT_ROOT, tee output to a per-config log file. Pre-#2938 versions of the script swallowed each build's stdout/stderr, so when a config crashed mid-run (#2935 saw 4 of 10 configs crash on Windows with `extras+.cpp.o` exit 3221225794), there was no way to diagnose wit
(cmd: list[str], log_name: str)
| 263 | |
| 264 | |
| 265 | def _run_with_log(cmd: list[str], log_name: str) -> bool: |
| 266 | """Run `cmd` in PROJECT_ROOT, tee output to a per-config log file. |
| 267 | |
| 268 | Pre-#2938 versions of the script swallowed each build's stdout/stderr, |
| 269 | so when a config crashed mid-run (#2935 saw 4 of 10 configs crash on |
| 270 | Windows with `extras+.cpp.o` exit 3221225794), there was no way to |
| 271 | diagnose without a manual rerun. This wrapper writes the combined |
| 272 | stream to `.build/measure-logs/<log_name>` while also printing it to |
| 273 | the operator's terminal. See #2938. |
| 274 | """ |
| 275 | _LOG_DIR.mkdir(parents=True, exist_ok=True) |
| 276 | log_path = _LOG_DIR / log_name |
| 277 | print(f"measure-opt-ins: $ {' '.join(cmd)}", flush=True) |
| 278 | print( |
| 279 | f"measure-opt-ins: (log: {log_path.relative_to(PROJECT_ROOT).as_posix()})", |
| 280 | flush=True, |
| 281 | ) |
| 282 | with log_path.open("wb") as log_f: |
| 283 | proc = subprocess.Popen( |
| 284 | cmd, cwd=PROJECT_ROOT, stdout=subprocess.PIPE, stderr=subprocess.STDOUT |
| 285 | ) |
| 286 | assert proc.stdout is not None |
| 287 | for chunk in iter(lambda: proc.stdout.read(4096), b""): |
| 288 | log_f.write(chunk) |
| 289 | sys.stdout.buffer.write(chunk) |
| 290 | sys.stdout.buffer.flush() |
| 291 | proc.wait() |
| 292 | return proc.returncode == 0 |
| 293 | |
| 294 | |
| 295 | def run_compile(example: str, config_name: str) -> bool: |