in compiler_gym/envs/llvm/llvm_benchmark.py [0:0]
def get_compiler_includes(compiler: str) -> Iterable[Path]:
"""Run the system compiler in verbose mode on a dummy input to get the
system header search path.
"""
# Create a temporary directory to write the compiled 'binary' to, since
# GNU assembler does not support piping to stdout.
with tempfile.TemporaryDirectory() as d:
try:
with Popen(
[compiler, "-xc++", "-v", "-c", "-", "-o", str(Path(d) / "a.out")],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
universal_newlines=True,
) as process:
_, stderr = process.communicate(input="", timeout=30)
if process.returncode:
raise OSError(
f"Failed to invoke {compiler}. "
f"Is there a working system compiler?\n"
f"Error: {stderr.strip()}"
)
except FileNotFoundError as e:
raise OSError(
f"Failed to invoke {compiler}. "
f"Is there a working system compiler?\n"
f"Error: {e}"
) from e
# Parse the compiler output that matches the conventional output format
# used by clang and GCC:
#
# #include <...> search starts here:
# /path/1
# /path/2
# End of search list
in_search_list = False
for line in stderr.split("\n"):
if in_search_list and line.startswith("End of search list"):
break
elif in_search_list:
# We have an include path to return.
path = Path(line.strip())
yield path
# Compatibility fix for compiling benchmark sources which use the
# '#include <endian.h>' header, which on macOS is located in a
# 'machine/endian.h' directory.
if (path / "machine").is_dir():
yield path / "machine"
elif line.startswith("#include <...> search starts here:"):
in_search_list = True
else:
msg = f"Failed to parse '#include <...>' search paths from {compiler}"
stderr = stderr.strip()
if stderr:
msg += f":\n{stderr}"
raise OSError(msg)