[libcxx] adds an include-what-you-use (IWYU) mapping file
This makes it possible for programmers to run IWYU and get more accurate
standard library inclusions. Prior to this commit, the following program
would be transformed thusly:
```cpp
// Before
#include <algorithm>
#include <vector>
void f() {
auto v = std::vector{0, 1};
std::find(std::ranges::begin(v), std::ranges::end(v), 0);
}
```
```cpp
// After
#include <__algorithm/find.h>
#include <__ranges/access.h>
#include <vector>
...
```
There are two ways to fix this issue: to use [comment pragmas](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md)
on every private include, or to write a canonical [mapping file](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUMappings.md)
that provides the tool with a manual on how libc++ is laid out. Due to
the complexity of libc++, this commit opts for the latter, to maximise
correctness and minimise developer burden.
To mimimise developer updates to the file, it makes use of wildcards
that match everything within listed subdirectories. A script has also
been added to ensure that the mapping is always fresh in CI, and makes
the process a single step.
Finally, documentation has been added to inform users that IWYU is
supported, and what they need to do in order to leverage the mapping
file.
Closes #56937.
Differential Revision: https://reviews.llvm.org/D138189
2022-11-17 07:36:37 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
2024-04-22 08:45:02 -04:00
|
|
|
import argparse
|
2024-01-16 13:45:05 -05:00
|
|
|
import libcxx.header_information
|
|
|
|
import os
|
|
|
|
import pathlib
|
|
|
|
import re
|
2024-04-22 08:45:02 -04:00
|
|
|
import sys
|
2024-01-16 13:45:05 -05:00
|
|
|
import typing
|
|
|
|
|
|
|
|
def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]:
|
|
|
|
ignore = [
|
2024-10-24 00:17:37 +02:00
|
|
|
"__cxx03/.+",
|
2024-01-16 13:45:05 -05:00
|
|
|
"__debug_utils/.+",
|
|
|
|
"__fwd/get[.]h",
|
2024-04-15 10:30:00 -04:00
|
|
|
"__pstl/.+",
|
2024-01-16 13:45:05 -05:00
|
|
|
"__support/.+",
|
2024-04-10 20:34:58 +02:00
|
|
|
"__utility/private_constructor_tag.h",
|
2024-01-16 13:45:05 -05:00
|
|
|
]
|
|
|
|
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"]
|
2024-05-28 07:22:06 -04:00
|
|
|
elif re.match("__configuration/.+", header) or header == "__config":
|
|
|
|
return ["version"]
|
2024-01-16 13:45:05 -05:00
|
|
|
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"]
|
2024-01-30 08:35:15 -05:00
|
|
|
elif re.match("(__thread/support[.]h)|(__thread/support/.+)", header):
|
2024-01-16 13:45:05 -05:00
|
|
|
return ["atomic", "mutex", "semaphore", "thread"]
|
|
|
|
elif header == "__tree":
|
|
|
|
return ["map", "set"]
|
2024-09-06 12:11:20 -04:00
|
|
|
elif header == "__fwd/byte.h":
|
|
|
|
return ["cstddef"]
|
2024-01-16 13:45:05 -05:00
|
|
|
elif header == "__fwd/pair.h":
|
|
|
|
return ["utility"]
|
|
|
|
elif header == "__fwd/subrange.h":
|
|
|
|
return ["ranges"]
|
2024-02-29 10:48:23 -05:00
|
|
|
elif re.match("__fwd/(fstream|ios|istream|ostream|sstream|streambuf)[.]h", header):
|
|
|
|
return ["iosfwd"]
|
2024-01-16 13:45:05 -05:00
|
|
|
# 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
|
2023-05-17 11:09:29 +02:00
|
|
|
|
2024-04-22 08:45:02 -04:00
|
|
|
|
|
|
|
def main(argv: typing.List[str]):
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument(
|
|
|
|
"-o",
|
|
|
|
help="File to output the IWYU mappings into",
|
|
|
|
type=argparse.FileType("w"),
|
|
|
|
required=True,
|
|
|
|
dest="output",
|
|
|
|
)
|
|
|
|
args = parser.parse_args(argv)
|
|
|
|
|
2024-01-16 13:45:05 -05:00
|
|
|
mappings = [] # Pairs of (header, public_header)
|
|
|
|
for header in libcxx.header_information.all_headers:
|
2024-10-22 09:18:58 -04:00
|
|
|
public_headers = IWYU_mapping(str(header))
|
2024-01-16 13:45:05 -05:00
|
|
|
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")
|
|
|
|
|
2024-04-22 08:45:02 -04:00
|
|
|
args.output.write("[\n")
|
|
|
|
for header, public in sorted(mappings):
|
|
|
|
args.output.write(
|
|
|
|
f' {{ include: [ "<{header}>", "private", "<{public}>", "public" ] }},\n'
|
|
|
|
)
|
|
|
|
args.output.write("]\n")
|
[libcxx] adds an include-what-you-use (IWYU) mapping file
This makes it possible for programmers to run IWYU and get more accurate
standard library inclusions. Prior to this commit, the following program
would be transformed thusly:
```cpp
// Before
#include <algorithm>
#include <vector>
void f() {
auto v = std::vector{0, 1};
std::find(std::ranges::begin(v), std::ranges::end(v), 0);
}
```
```cpp
// After
#include <__algorithm/find.h>
#include <__ranges/access.h>
#include <vector>
...
```
There are two ways to fix this issue: to use [comment pragmas](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md)
on every private include, or to write a canonical [mapping file](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUMappings.md)
that provides the tool with a manual on how libc++ is laid out. Due to
the complexity of libc++, this commit opts for the latter, to maximise
correctness and minimise developer burden.
To mimimise developer updates to the file, it makes use of wildcards
that match everything within listed subdirectories. A script has also
been added to ensure that the mapping is always fresh in CI, and makes
the process a single step.
Finally, documentation has been added to inform users that IWYU is
supported, and what they need to do in order to leverage the mapping
file.
Closes #56937.
Differential Revision: https://reviews.llvm.org/D138189
2022-11-17 07:36:37 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2024-04-22 08:45:02 -04:00
|
|
|
main(sys.argv[1:])
|