mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-16 05:10:32 +00:00

This simplifies the IWYU generation script by treating everything as a file, instead of dealing with directories and files separately. This has the downside that the `libcxx.imp` file is a lot larger than it used to be, however we now have the flexibility of mapping files under detail directories to different public headers. For example, this allows us to map <__fwd/subrange.h> to <ranges> but <__fwd/pair.h> to <utility>. This patch also adds basic validation to ensure that we never map a header to a public header that doesn't exist. We may still be missing some mappings or we may be mapping to incorrect headers, but we won't be mapping to headers that downright don't exist. Fixes #63346
75 lines
2.5 KiB
Python
75 lines
2.5 KiB
Python
#!/usr/bin/env python
|
|
|
|
import libcxx.header_information
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import typing
|
|
|
|
def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]:
|
|
ignore = [
|
|
"__debug_utils/.+",
|
|
"__fwd/get[.]h",
|
|
"__support/.+",
|
|
]
|
|
if any(re.match(pattern, header) for pattern in ignore):
|
|
return None
|
|
elif header == "__bits":
|
|
return ["bits"]
|
|
elif header in ("__bit_reference", "__fwd/bit_reference.h"):
|
|
return ["bitset", "vector"]
|
|
elif header == "__hash_table":
|
|
return ["unordered_map", "unordered_set"]
|
|
elif header == "__locale":
|
|
return ["locale"]
|
|
elif re.match("__locale_dir/.+", header):
|
|
return ["locale"]
|
|
elif re.match("__math/.+", header):
|
|
return ["cmath"]
|
|
elif header == "__node_handle":
|
|
return ["map", "set", "unordered_map", "unordered_set"]
|
|
elif header == "__split_buffer":
|
|
return ["deque", "vector"]
|
|
elif header == "__threading_support":
|
|
return ["atomic", "mutex", "semaphore", "thread"]
|
|
elif header == "__tree":
|
|
return ["map", "set"]
|
|
elif header == "__fwd/hash.h":
|
|
return ["functional"]
|
|
elif header == "__fwd/pair.h":
|
|
return ["utility"]
|
|
elif header == "__fwd/subrange.h":
|
|
return ["ranges"]
|
|
# Handle remaining forward declaration headers
|
|
elif re.match("__fwd/(.+)[.]h", header):
|
|
return [re.match("__fwd/(.+)[.]h", header).group(1)]
|
|
# Handle detail headers for things like <__algorithm/foo.h>
|
|
elif re.match("__(.+?)/.+", header):
|
|
return [re.match("__(.+?)/.+", header).group(1)]
|
|
else:
|
|
return None
|
|
|
|
def main():
|
|
mappings = [] # Pairs of (header, public_header)
|
|
for header in libcxx.header_information.all_headers:
|
|
public_headers = IWYU_mapping(header)
|
|
if public_headers is not None:
|
|
mappings.extend((header, public) for public in public_headers)
|
|
|
|
# Validate that we only have valid public header names -- otherwise the mapping above
|
|
# needs to be updated.
|
|
for header, public in mappings:
|
|
if public not in libcxx.header_information.public_headers:
|
|
raise RuntimeError(f"{header}: Header {public} is not a valid header")
|
|
|
|
with open(libcxx.header_information.include / "libcxx.imp", "w") as f:
|
|
f.write("[\n")
|
|
for header, public in sorted(mappings):
|
|
f.write(
|
|
f' {{ include: [ "<{header}>", "private", "<{public}>", "public" ] }},\n'
|
|
)
|
|
f.write("]\n")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|