1#!/usr/bin/env python 2 3import libcxx.header_information 4import os 5import pathlib 6import re 7import typing 8 9def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]: 10 ignore = [ 11 "__debug_utils/.+", 12 "__fwd/get[.]h", 13 "__pstl/.+", 14 "__support/.+", 15 "__utility/private_constructor_tag.h", 16 ] 17 if any(re.match(pattern, header) for pattern in ignore): 18 return None 19 elif header == "__bits": 20 return ["bits"] 21 elif header in ("__bit_reference", "__fwd/bit_reference.h"): 22 return ["bitset", "vector"] 23 elif header == "__hash_table": 24 return ["unordered_map", "unordered_set"] 25 elif header == "__locale": 26 return ["locale"] 27 elif re.match("__locale_dir/.+", header): 28 return ["locale"] 29 elif re.match("__math/.+", header): 30 return ["cmath"] 31 elif header == "__node_handle": 32 return ["map", "set", "unordered_map", "unordered_set"] 33 elif header == "__split_buffer": 34 return ["deque", "vector"] 35 elif re.match("(__thread/support[.]h)|(__thread/support/.+)", header): 36 return ["atomic", "mutex", "semaphore", "thread"] 37 elif header == "__tree": 38 return ["map", "set"] 39 elif header == "__fwd/pair.h": 40 return ["utility"] 41 elif header == "__fwd/subrange.h": 42 return ["ranges"] 43 elif re.match("__fwd/(fstream|ios|istream|ostream|sstream|streambuf)[.]h", header): 44 return ["iosfwd"] 45 # Handle remaining forward declaration headers 46 elif re.match("__fwd/(.+)[.]h", header): 47 return [re.match("__fwd/(.+)[.]h", header).group(1)] 48 # Handle detail headers for things like <__algorithm/foo.h> 49 elif re.match("__(.+?)/.+", header): 50 return [re.match("__(.+?)/.+", header).group(1)] 51 else: 52 return None 53 54def main(): 55 mappings = [] # Pairs of (header, public_header) 56 for header in libcxx.header_information.all_headers: 57 public_headers = IWYU_mapping(header) 58 if public_headers is not None: 59 mappings.extend((header, public) for public in public_headers) 60 61 # Validate that we only have valid public header names -- otherwise the mapping above 62 # needs to be updated. 63 for header, public in mappings: 64 if public not in libcxx.header_information.public_headers: 65 raise RuntimeError(f"{header}: Header {public} is not a valid header") 66 67 with open(libcxx.header_information.include / "libcxx.imp", "w") as f: 68 f.write("[\n") 69 for header, public in sorted(mappings): 70 f.write( 71 f' {{ include: [ "<{header}>", "private", "<{public}>", "public" ] }},\n' 72 ) 73 f.write("]\n") 74 75if __name__ == "__main__": 76 main() 77