forked from OSchip/llvm-project
214 lines
6.9 KiB
Python
Executable File
214 lines
6.9 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
import glob
|
|
import os
|
|
import posixpath
|
|
import re
|
|
|
|
|
|
def get_libcxx_paths():
|
|
utils_path = os.path.dirname(os.path.abspath(__file__))
|
|
script_name = os.path.basename(__file__)
|
|
assert os.path.exists(utils_path)
|
|
src_root = os.path.dirname(utils_path)
|
|
include_path = os.path.join(src_root, 'include')
|
|
assert os.path.exists(include_path)
|
|
libcxx_test_path = os.path.join(src_root, 'test', 'libcxx')
|
|
assert os.path.exists(libcxx_test_path)
|
|
return script_name, src_root, include_path, libcxx_test_path
|
|
|
|
|
|
script_name, source_root, include_path, libcxx_test_path = get_libcxx_paths()
|
|
|
|
header_markup = {
|
|
"atomic": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"barrier": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"future": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"latch": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"mutex": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"semaphore": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"shared_mutex": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
"thread": ["ifndef _LIBCPP_HAS_NO_THREADS"],
|
|
|
|
"experimental/filesystem": ["ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY"],
|
|
"filesystem": ["ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY"],
|
|
"format": ["ifndef _LIBCPP_HAS_NO_INCOMPLETE_FORMAT"],
|
|
|
|
"clocale": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"codecvt": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"fstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"iomanip": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"ios": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"iostream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"istream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"locale.h": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"locale": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"ostream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"ranges": ["ifndef _LIBCPP_HAS_NO_INCOMPLETE_RANGES"],
|
|
"regex": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"sstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"streambuf": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
"strstream": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
|
|
"wctype.h": ["ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS"],
|
|
"cwctype": ["ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS"],
|
|
"cwchar": ["ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS"],
|
|
"wchar.h": ["ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS"],
|
|
|
|
"experimental/coroutine": ["if defined(__cpp_coroutines)"],
|
|
"experimental/regex": ["ifndef _LIBCPP_HAS_NO_LOCALIZATION"],
|
|
}
|
|
|
|
allowed_extensions = ['', '.h']
|
|
indent_width = 4
|
|
|
|
|
|
begin_pattern = """\
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// BEGIN-GENERATED-HEADERS
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
"""
|
|
|
|
warning_note = """\
|
|
// WARNING: This test was generated by {script_name}
|
|
// and should not be edited manually.
|
|
|
|
""".format(script_name=script_name)
|
|
|
|
end_pattern = """\
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// END-GENERATED-HEADERS
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
"""
|
|
|
|
generated_part_pattern = re.compile(re.escape(begin_pattern) + ".*" + re.escape(end_pattern),
|
|
re.MULTILINE | re.DOTALL)
|
|
|
|
headers_template = """\
|
|
// Top level headers
|
|
{top_level_headers}
|
|
|
|
// experimental headers
|
|
#if __cplusplus >= 201103L
|
|
{experimental_headers}
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
// extended headers
|
|
{extended_headers}
|
|
"""
|
|
|
|
|
|
def should_keep_header(p, exclusions=None):
|
|
if os.path.isdir(p):
|
|
return False
|
|
|
|
if exclusions:
|
|
relpath = os.path.relpath(p, include_path)
|
|
relpath = posixpath.join(*os.path.split(relpath))
|
|
if relpath in exclusions:
|
|
return False
|
|
|
|
return os.path.splitext(p)[1] in allowed_extensions
|
|
|
|
|
|
def produce_include(relpath, indent_level, post_include=None):
|
|
relpath = posixpath.join(*os.path.split(relpath))
|
|
template = "{preambule}#{indentation}include <{include}>{post_include}{postambule}"
|
|
|
|
base_indentation = ' '*(indent_width * indent_level)
|
|
next_indentation = base_indentation + ' '*(indent_width)
|
|
post_include = "\n{}".format(post_include) if post_include else ''
|
|
|
|
markup = header_markup.get(relpath, None)
|
|
if markup:
|
|
preambule = '#{indentation}{directive}\n'.format(
|
|
directive=markup[0],
|
|
indentation=base_indentation,
|
|
)
|
|
postambule = '\n#{indentation}endif'.format(
|
|
indentation=base_indentation,
|
|
)
|
|
indentation = next_indentation
|
|
else:
|
|
preambule = ''
|
|
postambule = ''
|
|
indentation = base_indentation
|
|
|
|
return template.format(
|
|
include=relpath,
|
|
post_include=post_include,
|
|
preambule=preambule,
|
|
postambule=postambule,
|
|
indentation=indentation,
|
|
)
|
|
|
|
|
|
def produce_headers(path_parts, indent_level, post_include=None, exclusions=None):
|
|
pattern = os.path.join(*path_parts, '[a-z]*')
|
|
|
|
files = sorted(glob.glob(pattern, recursive=False))
|
|
|
|
include_headers = [
|
|
produce_include(os.path.relpath(p, include_path),
|
|
indent_level, post_include=post_include)
|
|
for p in files
|
|
if should_keep_header(p, exclusions)
|
|
]
|
|
|
|
return '\n'.join(include_headers)
|
|
|
|
|
|
def produce_top_level_headers(post_include=None, exclusions=None):
|
|
return produce_headers([include_path], 0, post_include=post_include, exclusions=exclusions)
|
|
|
|
|
|
def produce_experimental_headers(post_include=None, exclusions=None):
|
|
return produce_headers([include_path, 'experimental'], 1, post_include=post_include, exclusions=exclusions)
|
|
|
|
|
|
def produce_extended_headers(post_include=None, exclusions=None):
|
|
return produce_headers([include_path, 'ext'], 0, post_include=post_include, exclusions=exclusions)
|
|
|
|
|
|
def replace_generated_headers(test_path, test_str):
|
|
with open(test_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
preambule = begin_pattern + '\n// clang-format off\n\n' + warning_note
|
|
postambule = '\n// clang-format on\n\n' + end_pattern
|
|
content = generated_part_pattern.sub(
|
|
preambule + test_str + postambule, content)
|
|
|
|
with open(test_path, 'w', newline='\n') as f:
|
|
f.write(content)
|
|
|
|
|
|
def produce_test(test_filename, exclusions=None, post_include=None):
|
|
test_str = headers_template.format(
|
|
top_level_headers=produce_top_level_headers(
|
|
post_include=post_include,
|
|
exclusions=exclusions,
|
|
),
|
|
experimental_headers=produce_experimental_headers(
|
|
post_include=post_include,
|
|
),
|
|
extended_headers=produce_extended_headers(
|
|
post_include=post_include,
|
|
),
|
|
)
|
|
|
|
replace_generated_headers(os.path.join(
|
|
libcxx_test_path, test_filename), test_str)
|
|
|
|
|
|
def main():
|
|
produce_test('double_include.sh.cpp')
|
|
produce_test('min_max_macros.compile.pass.cpp',
|
|
post_include='TEST_MACROS();')
|
|
produce_test('no_assert_include.compile.pass.cpp',
|
|
exclusions=['cassert'])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|