diff options
Diffstat (limited to 'test/libcxx/test/config.py')
-rw-r--r-- | test/libcxx/test/config.py | 294 |
1 files changed, 115 insertions, 179 deletions
diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py index 09fbf66dbba0..fefbf01ad450 100644 --- a/test/libcxx/test/config.py +++ b/test/libcxx/test/config.py @@ -1,4 +1,3 @@ -import importlib import locale import os import platform @@ -12,6 +11,7 @@ import lit.util # pylint: disable=import-error,no-name-in-module from libcxx.test.format import LibcxxTestFormat from libcxx.compiler import CXXCompiler +from libcxx.test.target_info import make_target_info from libcxx.test.executor import * from libcxx.test.tracing import * @@ -42,13 +42,13 @@ def loadSiteConfig(lit_config, config, param_name, env_name): ld_fn(config, site_cfg) lit_config.load_config = ld_fn - class Configuration(object): # pylint: disable=redefined-outer-name def __init__(self, lit_config, config): self.lit_config = lit_config self.config = config self.cxx = None + self.project_obj_root = None self.libcxx_src_root = None self.libcxx_obj_root = None self.cxx_library_root = None @@ -141,13 +141,7 @@ class Configuration(object): self.executor = te def configure_target_info(self): - default = "libcxx.test.target_info.LocalTI" - info_str = self.get_lit_conf('target_info', default) - mod_path, _, info = info_str.rpartition('.') - mod = importlib.import_module(mod_path) - self.target_info = getattr(mod, info)() - if info_str != default: - self.lit_config.note("inferred target_info as: %r" % info_str) + self.target_info = make_target_info(self) def configure_cxx(self): # Gather various compiler parameters. @@ -179,7 +173,14 @@ class Configuration(object): 'libcxx_src_root', os.path.dirname(self.config.test_source_root)) def configure_obj_root(self): + self.project_obj_root = self.get_lit_conf('project_obj_root') self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root') + if not self.libcxx_obj_root and self.project_obj_root is not None: + possible_root = os.path.join(self.project_obj_root, 'projects', 'libcxx') + if os.path.isdir(possible_root): + self.libcxx_obj_root = possible_root + else: + self.libcxx_obj_root = self.project_obj_root def configure_cxx_library_root(self): self.cxx_library_root = self.get_lit_conf('cxx_library_root', @@ -211,13 +212,12 @@ class Configuration(object): def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the - # default value. Otherwise we default to internal on Windows and - # external elsewhere, as bash on Windows is usually very slow. + # default value. Otherwise we ask the target_info. use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL') if use_lit_shell_default is not None: use_lit_shell_default = use_lit_shell_default != '0' else: - use_lit_shell_default = sys.platform == 'win32' + use_lit_shell_default = self.target_info.use_lit_shell_default() # Check for the command line parameter using the default value if it is # not present. use_lit_shell = self.get_lit_bool('use_lit_shell', @@ -236,63 +236,10 @@ class Configuration(object): if additional_features: for f in additional_features.split(','): self.config.available_features.add(f.strip()) + self.target_info.add_locale_features(self.config.available_features) - # Figure out which of the required locales we support - locales = { - 'Darwin': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'FreeBSD': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'Linux': { - 'en_US.UTF-8': 'en_US.UTF-8', - 'cs_CZ.ISO8859-2': 'cs_CZ.ISO-8859-2', - 'fr_FR.UTF-8': 'fr_FR.UTF-8', - 'fr_CA.ISO8859-1': 'fr_CA.ISO-8859-1', - 'ru_RU.UTF-8': 'ru_RU.UTF-8', - 'zh_CN.UTF-8': 'zh_CN.UTF-8', - }, - 'Windows': { - 'en_US.UTF-8': 'English_United States.1252', - 'cs_CZ.ISO8859-2': 'Czech_Czech Republic.1250', - 'fr_FR.UTF-8': 'French_France.1252', - 'fr_CA.ISO8859-1': 'French_Canada.1252', - 'ru_RU.UTF-8': 'Russian_Russia.1251', - 'zh_CN.UTF-8': 'Chinese_China.936', - }, - } - - target_system = self.target_info.system() target_platform = self.target_info.platform() - if target_system in locales: - default_locale = locale.setlocale(locale.LC_ALL) - for feature, loc in locales[target_system].items(): - try: - locale.setlocale(locale.LC_ALL, loc) - self.config.available_features.add( - 'locale.{0}'.format(feature)) - except locale.Error: - self.lit_config.warning('The locale {0} is not supported by ' - 'your platform. Some tests will be ' - 'unsupported.'.format(loc)) - locale.setlocale(locale.LC_ALL, default_locale) - else: - # Warn that the user doesn't get any free XFAILs for locale issues - self.lit_config.warning("No locales entry for target_system: %s" % - target_system) - # Write an "available feature" that combines the triple when # use_system_cxx_lib is enabled. This is so that we can easily write # XFAIL markers for tests that are known to fail with versions of @@ -304,17 +251,6 @@ class Configuration(object): # Insert the platform name into the available features as a lower case. self.config.available_features.add(target_platform) - # Some linux distributions have different locale data than others. - # Insert the distributions name and name-version into the available - # features to allow tests to XFAIL on them. - if target_platform == 'linux': - name = self.target_info.platform_name() - ver = self.target_info.platform_ver() - if name: - self.config.available_features.add(name) - if name and ver: - self.config.available_features.add('%s-%s' % (name, ver)) - # Simulator testing can take a really long time for some of these tests # so add a feature check so we can REQUIRES: long_tests in them self.long_tests = self.get_lit_bool('long_tests') @@ -344,38 +280,33 @@ class Configuration(object): # Try and get the std version from the command line. Fall back to # default given in lit.site.cfg is not present. If default is not # present then force c++11. - std = self.get_lit_conf('std', 'c++11') + std = self.get_lit_conf('std') + if not std: + # Choose the newest possible language dialect if none is given. + possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03'] + for s in possible_stds: + if self.cxx.hasCompileFlag('-std=%s' % s): + std = s + self.lit_config.note( + 'inferred language dialect as: %s' % std) + break + if not std: + self.lit_config.fatal( + 'Failed to infer a supported language dialect from one of %r' + % possible_stds) self.cxx.compile_flags += ['-std={0}'.format(std)] self.config.available_features.add(std) # Configure include paths self.cxx.compile_flags += ['-nostdinc++'] self.configure_compile_flags_header_includes() - if self.target_info.platform() == 'linux': - self.cxx.compile_flags += ['-D__STDC_FORMAT_MACROS', - '-D__STDC_LIMIT_MACROS', - '-D__STDC_CONSTANT_MACROS'] + self.target_info.add_cxx_compile_flags(self.cxx.compile_flags) # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() - self.configure_compile_flags_no_global_filesystem_namespace() - self.configure_compile_flags_no_stdin() - self.configure_compile_flags_no_stdout() + self.configure_compile_flags_abi_version() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] - # Configure threading features. - enable_threads = self.get_lit_bool('enable_threads', True) - enable_monotonic_clock = self.get_lit_bool('enable_monotonic_clock', - True) - if not enable_threads: - self.configure_compile_flags_no_threads() - if not enable_monotonic_clock: - self.configure_compile_flags_no_monotonic_clock() - elif not enable_monotonic_clock: - self.lit_config.fatal('enable_monotonic_clock cannot be false when' - ' enable_threads is true.') - self.configure_compile_flags_no_thread_unsafe_c_functions() - # Use verbose output for better errors self.cxx.flags += ['-v'] sysroot = self.get_lit_conf('sysroot') @@ -391,6 +322,7 @@ class Configuration(object): support_path = os.path.join(self.libcxx_src_root, 'test/support') self.cxx.compile_flags += ['-I' + support_path] self.cxx.compile_flags += ['-include', os.path.join(support_path, 'nasty_macros.hpp')] + self.configure_config_site_header() libcxx_headers = self.get_lit_conf( 'libcxx_headers', os.path.join(self.libcxx_src_root, 'include')) if not os.path.isdir(libcxx_headers): @@ -398,6 +330,56 @@ class Configuration(object): % libcxx_headers) self.cxx.compile_flags += ['-I' + libcxx_headers] + def configure_config_site_header(self): + # Check for a possible __config_site in the build directory. We + # use this if it exists. + if self.libcxx_obj_root is None: + return + config_site_header = os.path.join(self.libcxx_obj_root, '__config_site') + if not os.path.isfile(config_site_header): + return + contained_macros = self.parse_config_site_and_add_features( + config_site_header) + self.lit_config.note('Using __config_site header %s with macros: %r' + % (config_site_header, contained_macros)) + # FIXME: This must come after the call to + # 'parse_config_site_and_add_features(...)' in order for it to work. + self.cxx.compile_flags += ['-include', config_site_header] + + def parse_config_site_and_add_features(self, header): + """ parse_config_site_and_add_features - Deduce and add the test + features that that are implied by the #define's in the __config_site + header. Return a dictionary containing the macros found in the + '__config_site' header. + """ + # Parse the macro contents of __config_site by dumping the macros + # using 'c++ -dM -E' and filtering the predefines. + predefines = self.cxx.dumpMacros() + macros = self.cxx.dumpMacros(header) + feature_macros_keys = set(macros.keys()) - set(predefines.keys()) + feature_macros = {} + for k in feature_macros_keys: + feature_macros[k] = macros[k] + # We expect the header guard to be one of the definitions + assert '_LIBCPP_CONFIG_SITE' in feature_macros + del feature_macros['_LIBCPP_CONFIG_SITE'] + # The __config_site header should be non-empty. Otherwise it should + # have never been emitted by CMake. + assert len(feature_macros) > 0 + # Transform each macro name into the feature name used in the tests. + # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads + for m in feature_macros: + if m == '_LIBCPP_ABI_VERSION': + self.config.available_features.add('libcpp-abi-version-v%s' + % feature_macros[m]) + continue + assert m.startswith('_LIBCPP_HAS_') or m == '_LIBCPP_ABI_UNSTABLE' + m = m.lower()[1:].replace('_', '-') + self.config.available_features.add(m) + return feature_macros + + + def configure_compile_flags_exceptions(self): enable_exceptions = self.get_lit_bool('enable_exceptions', True) if not enable_exceptions: @@ -410,43 +392,16 @@ class Configuration(object): self.config.available_features.add('libcpp-no-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] - def configure_compile_flags_no_global_filesystem_namespace(self): - enable_global_filesystem_namespace = self.get_lit_bool( - 'enable_global_filesystem_namespace', True) - if not enable_global_filesystem_namespace: - self.config.available_features.add( - 'libcpp-has-no-global-filesystem-namespace') - self.cxx.compile_flags += [ - '-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE'] - - def configure_compile_flags_no_stdin(self): - enable_stdin = self.get_lit_bool('enable_stdin', True) - if not enable_stdin: - self.config.available_features.add('libcpp-has-no-stdin') - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDIN'] - - def configure_compile_flags_no_stdout(self): - enable_stdout = self.get_lit_bool('enable_stdout', True) - if not enable_stdout: - self.config.available_features.add('libcpp-has-no-stdout') - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDOUT'] - - def configure_compile_flags_no_threads(self): - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS'] - self.config.available_features.add('libcpp-has-no-threads') - - def configure_compile_flags_no_thread_unsafe_c_functions(self): - enable_thread_unsafe_c_functions = self.get_lit_bool( - 'enable_thread_unsafe_c_functions', True) - if not enable_thread_unsafe_c_functions: - self.cxx.compile_flags += [ - '-D_LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS'] - self.config.available_features.add( - 'libcpp-has-no-thread-unsafe-c-functions') - - def configure_compile_flags_no_monotonic_clock(self): - self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK'] - self.config.available_features.add('libcpp-has-no-monotonic-clock') + def configure_compile_flags_abi_version(self): + abi_version = self.get_lit_conf('abi_version', '').strip() + abi_unstable = self.get_lit_bool('abi_unstable') + # Only add the ABI version when it is non-default. + # FIXME(EricWF): Get the ABI version from the "__config_site". + if abi_version and abi_version != '1': + self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version] + if abi_unstable: + self.config.available_features.add('libcpp-abi-unstable') + self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE'] def configure_link_flags(self): no_default_flags = self.get_lit_bool('no_default_flags', False) @@ -505,9 +460,7 @@ class Configuration(object): elif cxx_abi == 'libsupc++': self.cxx.link_flags += ['-lsupc++'] elif cxx_abi == 'libcxxabi': - # Don't link libc++abi explicitly on OS X because the symbols - # should be available in libc++ directly. - if self.target_info.platform() != 'darwin': + if self.target_info.allow_cxxabi_link(): self.cxx.link_flags += ['-lc++abi'] elif cxx_abi == 'libcxxrt': self.cxx.link_flags += ['-lcxxrt'] @@ -518,26 +471,7 @@ class Configuration(object): 'C++ ABI setting %s unsupported for tests' % cxx_abi) def configure_extra_library_flags(self): - enable_threads = self.get_lit_bool('enable_threads', True) - llvm_unwinder = self.get_lit_bool('llvm_unwinder', False) - target_platform = self.target_info.platform() - if target_platform == 'darwin': - self.cxx.link_flags += ['-lSystem'] - elif target_platform == 'linux': - if not llvm_unwinder: - self.cxx.link_flags += ['-lgcc_eh'] - self.cxx.link_flags += ['-lc', '-lm'] - if enable_threads: - self.cxx.link_flags += ['-lpthread'] - self.cxx.link_flags += ['-lrt'] - if llvm_unwinder: - self.cxx.link_flags += ['-lunwind', '-ldl'] - else: - self.cxx.link_flags += ['-lgcc_s'] - elif target_platform.startswith('freebsd'): - self.cxx.link_flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt'] - else: - self.lit_config.fatal("unrecognized system: %r" % target_platform) + self.target_info.add_cxx_link_flags(self.cxx.link_flags) def configure_color_diagnostics(self): use_color = self.get_lit_conf('color_diagnostics') @@ -570,14 +504,28 @@ class Configuration(object): def configure_warnings(self): enable_warnings = self.get_lit_bool('enable_warnings', False) if enable_warnings: - self.cxx.compile_flags += ['-Wsystem-headers', '-Wall', '-Werror'] - if ('clang' in self.config.available_features or - 'apple-clang' in self.config.available_features): - self.cxx.compile_flags += ['-Wno-user-defined-literals'] + self.cxx.compile_flags += [ + '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', + '-Wall', '-Werror' + ] + self.cxx.addWarningFlagIfSupported('-Wno-attributes') + self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move') + self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions') + self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals') + # TODO(EricWF) Remove the unused warnings once the test suite + # compiles clean with them. + self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') + self.cxx.addWarningFlagIfSupported('-Wno-unused-variable') + std = self.get_lit_conf('std', None) + if std in ['c++98', 'c++03']: + # The '#define static_assert' provided by libc++ in C++03 mode + # causes an unused local typedef whenever it is used. + self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') def configure_sanitizer(self): san = self.get_lit_conf('use_sanitizer', '').strip() if san: + self.target_info.add_sanitizer_features(san, self.config.available_features) # Search for llvm-symbolizer along the compiler path first # and then along the PATH env variable. symbolizer_search_paths = os.environ.get('PATH', '') @@ -590,8 +538,6 @@ class Configuration(object): symbolizer_search_paths) # Setup the sanitizer compile flags self.cxx.flags += ['-g', '-fno-omit-frame-pointer'] - if self.target_info.platform() == 'linux': - self.cxx.link_flags += ['-ldl'] if san == 'Address': self.cxx.flags += ['-fsanitize=address'] if llvm_symbolizer is not None: @@ -620,6 +566,10 @@ class Configuration(object): else: self.lit_config.fatal('unsupported value for ' 'use_sanitizer: {0}'.format(san)) + san_lib = self.get_lit_conf('sanitizer_library') + if san_lib: + self.cxx.link_flags += [ + san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)] def configure_coverage(self): self.generate_coverage = self.get_lit_bool('generate_coverage', False) @@ -692,18 +642,4 @@ class Configuration(object): "inferred target_triple as: %r" % self.config.target_triple) def configure_env(self): - if self.target_info.platform() == 'darwin': - library_paths = [] - # Configure the library path for libc++ - libcxx_library = self.get_lit_conf('libcxx_library') - if self.use_system_cxx_lib: - pass - elif libcxx_library: - library_paths += [os.path.dirname(libcxx_library)] - elif self.cxx_library_root: - library_paths += [self.cxx_library_root] - # Configure the abi library path - if self.abi_library_root: - library_paths += [self.abi_library_root] - if library_paths: - self.env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths) + self.target_info.configure_env(self.env) |