Extract C++ stdlib include paths from the compiler. This queries the compiler for its default include search paths and returns them as a list of -I flags for IWYU.
(compiler_path: str)
| 69 | |
| 70 | |
| 71 | def get_compiler_include_paths(compiler_path: str) -> list[str]: |
| 72 | """ |
| 73 | Extract C++ stdlib include paths from the compiler. |
| 74 | |
| 75 | This queries the compiler for its default include search paths |
| 76 | and returns them as a list of -I flags for IWYU. |
| 77 | """ |
| 78 | fast_compiler = _resolve_fast_native_cxx(compiler_path) |
| 79 | try: |
| 80 | # Query compiler for its include paths |
| 81 | # Using -E (preprocess only), -x c++ (C++ mode), -v (verbose), - (stdin) |
| 82 | result = subprocess.run( |
| 83 | [fast_compiler, "-E", "-x", "c++", "-v", "-"], |
| 84 | input="", |
| 85 | capture_output=True, |
| 86 | text=True, |
| 87 | timeout=10, |
| 88 | ) |
| 89 | |
| 90 | # Parse stderr for include paths |
| 91 | # Format: |
| 92 | # #include <...> search starts here: |
| 93 | # /path/to/include1 |
| 94 | # /path/to/include2 |
| 95 | # End of search list. |
| 96 | paths: list[str] = [] |
| 97 | in_includes = False |
| 98 | |
| 99 | for line in result.stderr.splitlines(): |
| 100 | if "#include <...> search starts here:" in line: |
| 101 | in_includes = True |
| 102 | continue |
| 103 | if "End of search list" in line: |
| 104 | break |
| 105 | if in_includes: |
| 106 | path = line.strip() |
| 107 | # Verify path exists and is a directory |
| 108 | if path and Path(path).exists() and Path(path).is_dir(): |
| 109 | paths.append(f"-I{path}") |
| 110 | |
| 111 | return paths |
| 112 | except KeyboardInterrupt as ki: |
| 113 | handle_keyboard_interrupt(ki) |
| 114 | raise # MUST re-raise KeyboardInterrupt to allow user to stop execution |
| 115 | except Exception as e: |
| 116 | print( |
| 117 | f"Warning: Failed to extract compiler include paths: {e}", file=sys.stderr |
| 118 | ) |
| 119 | return [] |
| 120 | |
| 121 | |
| 122 | def main(): |
no test coverage detected