()
| 252 | |
| 253 | |
| 254 | def main() -> int: |
| 255 | if len(sys.argv) < 2: |
| 256 | print("Usage: compile_pch.py <compiler> <args...>", file=sys.stderr) |
| 257 | return 1 |
| 258 | |
| 259 | # Parse command line arguments to find -o and -MF flags |
| 260 | args = sys.argv[1:] |
| 261 | pch_output: Path | None = None |
| 262 | depfile: Path | None = None |
| 263 | |
| 264 | i = 0 |
| 265 | while i < len(args): |
| 266 | if args[i] == "-o" and i + 1 < len(args): |
| 267 | pch_output = Path(args[i + 1]) |
| 268 | i += 2 |
| 269 | elif args[i] == "-MF" and i + 1 < len(args): |
| 270 | depfile = Path(args[i + 1]) |
| 271 | i += 2 |
| 272 | else: |
| 273 | i += 1 |
| 274 | |
| 275 | # Input-hash caching: skip compilation if all input files are unchanged. |
| 276 | # Ninja deletes the depfile after reading it (deps = gcc), so we use a |
| 277 | # saved copy (.d.cache) from the previous successful build. |
| 278 | saved_depfile = Path(str(depfile) + ".cache") if depfile else None |
| 279 | hash_file = Path(str(pch_output) + ".input_hash") if pch_output else None |
| 280 | if pch_output and saved_depfile and hash_file and pch_output.exists(): |
| 281 | if saved_depfile.exists() and hash_file.exists(): |
| 282 | try: |
| 283 | input_files = parse_depfile_inputs(saved_depfile) |
| 284 | if input_files: |
| 285 | current_hash = hash_input_files(input_files) |
| 286 | stored_hash = hash_file.read_text(encoding="utf-8").strip() |
| 287 | if current_hash == stored_hash: |
| 288 | print( |
| 289 | "PCH inputs unchanged (hash match) - skipping compilation", |
| 290 | file=sys.stderr, |
| 291 | ) |
| 292 | return 0 |
| 293 | except KeyboardInterrupt as ki: |
| 294 | handle_keyboard_interrupt(ki) |
| 295 | raise |
| 296 | except Exception as e: |
| 297 | print(f"WARNING: PCH input hash check failed: {e}", file=sys.stderr) |
| 298 | # Continue with normal compilation |
| 299 | |
| 300 | # Run the compiler |
| 301 | result = subprocess.run(args, check=False) |
| 302 | |
| 303 | # Fix the depfile and save caching data if compilation succeeded |
| 304 | if result.returncode == 0 and pch_output and depfile: |
| 305 | try: |
| 306 | fix_depfile(depfile, pch_output) |
| 307 | except KeyboardInterrupt as ki: |
| 308 | handle_keyboard_interrupt(ki) |
| 309 | raise |
| 310 | except Exception as e: |
| 311 | print(f"ERROR fixing PCH depfile: {e}", file=sys.stderr) |
no test coverage detected