diff options
Diffstat (limited to 'test/libcxx/test/config.py')
-rw-r--r-- | test/libcxx/test/config.py | 709 |
1 files changed, 709 insertions, 0 deletions
diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py new file mode 100644 index 000000000000..09fbf66dbba0 --- /dev/null +++ b/test/libcxx/test/config.py @@ -0,0 +1,709 @@ +import importlib +import locale +import os +import platform +import pkgutil +import re +import shlex +import sys + +import lit.Test # pylint: disable=import-error,no-name-in-module +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.executor import * +from libcxx.test.tracing import * + +def loadSiteConfig(lit_config, config, param_name, env_name): + # We haven't loaded the site specific configuration (the user is + # probably trying to run on a test file directly, and either the site + # configuration hasn't been created by the build system, or we are in an + # out-of-tree build situation). + site_cfg = lit_config.params.get(param_name, + os.environ.get(env_name)) + if not site_cfg: + lit_config.warning('No site specific configuration file found!' + ' Running the tests in the default configuration.') + elif not os.path.isfile(site_cfg): + lit_config.fatal( + "Specified site configuration file does not exist: '%s'" % + site_cfg) + else: + lit_config.note('using site specific configuration at %s' % site_cfg) + ld_fn = lit_config.load_config + + # Null out the load_config function so that lit.site.cfg doesn't + # recursively load a config even if it tries. + # TODO: This is one hell of a hack. Fix it. + def prevent_reload_fn(*args, **kwargs): + pass + lit_config.load_config = prevent_reload_fn + 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.libcxx_src_root = None + self.libcxx_obj_root = None + self.cxx_library_root = None + self.abi_library_root = None + self.env = {} + self.use_target = False + self.use_system_cxx_lib = False + self.use_clang_verify = False + self.long_tests = None + self.execute_external = False + + def get_lit_conf(self, name, default=None): + val = self.lit_config.params.get(name, None) + if val is None: + val = getattr(self.config, name, None) + if val is None: + val = default + return val + + def get_lit_bool(self, name, default=None): + conf = self.get_lit_conf(name) + if conf is None: + return default + if conf.lower() in ('1', 'true'): + return True + if conf.lower() in ('', '0', 'false'): + return False + self.lit_config.fatal( + "parameter '{}' should be true or false".format(name)) + + def configure(self): + self.configure_executor() + self.configure_target_info() + self.configure_cxx() + self.configure_triple() + self.configure_src_root() + self.configure_obj_root() + self.configure_cxx_library_root() + self.configure_use_system_cxx_lib() + self.configure_use_clang_verify() + self.configure_execute_external() + self.configure_ccache() + self.configure_compile_flags() + self.configure_link_flags() + self.configure_env() + self.configure_color_diagnostics() + self.configure_debug_mode() + self.configure_warnings() + self.configure_sanitizer() + self.configure_coverage() + self.configure_substitutions() + self.configure_features() + + def print_config_info(self): + # Print the final compile and link flags. + self.lit_config.note('Using compiler: %s' % self.cxx.path) + self.lit_config.note('Using flags: %s' % self.cxx.flags) + self.lit_config.note('Using compile flags: %s' + % self.cxx.compile_flags) + self.lit_config.note('Using link flags: %s' % self.cxx.link_flags) + # Print as list to prevent "set([...])" from being printed. + self.lit_config.note('Using available_features: %s' % + list(self.config.available_features)) + self.lit_config.note('Using environment: %r' % self.env) + + def get_test_format(self): + return LibcxxTestFormat( + self.cxx, + self.use_clang_verify, + self.execute_external, + self.executor, + exec_env=self.env) + + def configure_executor(self): + exec_str = self.get_lit_conf('executor', "None") + te = eval(exec_str) + if te: + self.lit_config.note("Using executor: %r" % exec_str) + if self.lit_config.useValgrind: + # We have no way of knowing where in the chain the + # ValgrindExecutor is supposed to go. It is likely + # that the user wants it at the end, but we have no + # way of getting at that easily. + selt.lit_config.fatal("Cannot infer how to create a Valgrind " + " executor.") + else: + te = LocalExecutor() + if self.lit_config.useValgrind: + te = ValgrindExecutor(self.lit_config.valgrindArgs, te) + 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) + + def configure_cxx(self): + # Gather various compiler parameters. + cxx = self.get_lit_conf('cxx_under_test') + + # If no specific cxx_under_test was given, attempt to infer it as + # clang++. + if cxx is None: + clangxx = lit.util.which('clang++', + self.config.environment['PATH']) + if clangxx: + cxx = clangxx + self.lit_config.note( + "inferred cxx_under_test as: %r" % cxx) + if not cxx: + self.lit_config.fatal('must specify user parameter cxx_under_test ' + '(e.g., --param=cxx_under_test=clang++)') + self.cxx = CXXCompiler(cxx) + cxx_type = self.cxx.type + if cxx_type is not None: + assert self.cxx.version is not None + maj_v, min_v, _ = self.cxx.version + self.config.available_features.add(cxx_type) + self.config.available_features.add('%s-%s.%s' % ( + cxx_type, maj_v, min_v)) + + def configure_src_root(self): + self.libcxx_src_root = self.get_lit_conf( + 'libcxx_src_root', os.path.dirname(self.config.test_source_root)) + + def configure_obj_root(self): + self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root') + + def configure_cxx_library_root(self): + self.cxx_library_root = self.get_lit_conf('cxx_library_root', + self.libcxx_obj_root) + + def configure_use_system_cxx_lib(self): + # This test suite supports testing against either the system library or + # the locally built one; the former mode is useful for testing ABI + # compatibility between the current headers and a shipping dynamic + # library. + self.use_system_cxx_lib = self.get_lit_bool('use_system_cxx_lib') + if self.use_system_cxx_lib is None: + # Default to testing against the locally built libc++ library. + self.use_system_cxx_lib = False + self.lit_config.note( + "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib) + + def configure_use_clang_verify(self): + '''If set, run clang with -verify on failing tests.''' + self.use_clang_verify = self.get_lit_bool('use_clang_verify') + if self.use_clang_verify is None: + # NOTE: We do not test for the -verify flag directly because + # -verify will always exit with non-zero on an empty file. + self.use_clang_verify = self.cxx.hasCompileFlag( + ['-Xclang', '-verify-ignore-unexpected']) + self.lit_config.note( + "inferred use_clang_verify as: %r" % self.use_clang_verify) + + 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. + 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' + # 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', + use_lit_shell_default) + self.execute_external = not use_lit_shell + + def configure_ccache(self): + use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None + use_ccache = self.get_lit_bool('use_ccache', use_ccache_default) + if use_ccache: + self.cxx.use_ccache = True + self.lit_config.note('enabling ccache') + + def configure_features(self): + additional_features = self.get_lit_conf('additional_features') + if additional_features: + for f in additional_features.split(','): + self.config.available_features.add(f.strip()) + + # 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 + # libc++ as were shipped with a particular triple. + if self.use_system_cxx_lib: + self.config.available_features.add( + 'with_system_cxx_lib=%s' % self.config.target_triple) + + # 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') + if self.long_tests is None: + # Default to running long tests. + self.long_tests = True + self.lit_config.note( + "inferred long_tests as: %r" % self.long_tests) + + if self.long_tests: + self.config.available_features.add('long_tests') + + # Run a compile test for the -fsized-deallocation flag. This is needed + # in test/std/language.support/support.dynamic/new.delete + if self.cxx.hasCompileFlag('-fsized-deallocation'): + self.config.available_features.add('fsized-deallocation') + + def configure_compile_flags(self): + no_default_flags = self.get_lit_bool('no_default_flags', False) + if not no_default_flags: + self.configure_default_compile_flags() + # Configure extra flags + compile_flags_str = self.get_lit_conf('compile_flags', '') + self.cxx.compile_flags += shlex.split(compile_flags_str) + + def configure_default_compile_flags(self): + # 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') + 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'] + # 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() + 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') + if sysroot: + self.cxx.flags += ['--sysroot', sysroot] + gcc_toolchain = self.get_lit_conf('gcc_toolchain') + if gcc_toolchain: + self.cxx.flags += ['-gcc-toolchain', gcc_toolchain] + if self.use_target: + self.cxx.flags += ['-target', self.config.target_triple] + + def configure_compile_flags_header_includes(self): + 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')] + libcxx_headers = self.get_lit_conf( + 'libcxx_headers', os.path.join(self.libcxx_src_root, 'include')) + if not os.path.isdir(libcxx_headers): + self.lit_config.fatal("libcxx_headers='%s' is not a directory." + % libcxx_headers) + self.cxx.compile_flags += ['-I' + libcxx_headers] + + def configure_compile_flags_exceptions(self): + enable_exceptions = self.get_lit_bool('enable_exceptions', True) + if not enable_exceptions: + self.config.available_features.add('libcpp-no-exceptions') + self.cxx.compile_flags += ['-fno-exceptions'] + + def configure_compile_flags_rtti(self): + enable_rtti = self.get_lit_bool('enable_rtti', True) + if not enable_rtti: + 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_link_flags(self): + no_default_flags = self.get_lit_bool('no_default_flags', False) + if not no_default_flags: + self.cxx.link_flags += ['-nodefaultlibs'] + + # Configure library path + self.configure_link_flags_cxx_library_path() + self.configure_link_flags_abi_library_path() + + # Configure libraries + self.configure_link_flags_cxx_library() + self.configure_link_flags_abi_library() + self.configure_extra_library_flags() + + link_flags_str = self.get_lit_conf('link_flags', '') + self.cxx.link_flags += shlex.split(link_flags_str) + + def configure_link_flags_cxx_library_path(self): + libcxx_library = self.get_lit_conf('libcxx_library') + # Configure libc++ library paths. + if libcxx_library is not None: + # Check that the given value for libcxx_library is valid. + if not os.path.isfile(libcxx_library): + self.lit_config.fatal( + "libcxx_library='%s' is not a valid file." % + libcxx_library) + if self.use_system_cxx_lib: + self.lit_config.fatal( + "Conflicting options: 'libcxx_library' cannot be used " + "with 'use_system_cxx_lib=true'") + self.cxx.link_flags += ['-Wl,-rpath,' + + os.path.dirname(libcxx_library)] + elif not self.use_system_cxx_lib and self.cxx_library_root: + self.cxx.link_flags += ['-L' + self.cxx_library_root, + '-Wl,-rpath,' + self.cxx_library_root] + + def configure_link_flags_abi_library_path(self): + # Configure ABI library paths. + self.abi_library_root = self.get_lit_conf('abi_library_path') + if self.abi_library_root: + self.cxx.link_flags += ['-L' + self.abi_library_root, + '-Wl,-rpath,' + self.abi_library_root] + + def configure_link_flags_cxx_library(self): + libcxx_library = self.get_lit_conf('libcxx_library') + if libcxx_library: + self.cxx.link_flags += [libcxx_library] + else: + self.cxx.link_flags += ['-lc++'] + + def configure_link_flags_abi_library(self): + cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi') + if cxx_abi == 'libstdc++': + self.cxx.link_flags += ['-lstdc++'] + 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': + self.cxx.link_flags += ['-lc++abi'] + elif cxx_abi == 'libcxxrt': + self.cxx.link_flags += ['-lcxxrt'] + elif cxx_abi == 'none': + pass + else: + self.lit_config.fatal( + '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) + + def configure_color_diagnostics(self): + use_color = self.get_lit_conf('color_diagnostics') + if use_color is None: + use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS') + if use_color is None: + return + if use_color != '': + self.lit_config.fatal('Invalid value for color_diagnostics "%s".' + % use_color) + color_flag = '-fdiagnostics-color=always' + # Check if the compiler supports the color diagnostics flag. Issue a + # warning if it does not since color diagnostics have been requested. + if not self.cxx.hasCompileFlag(color_flag): + self.lit_config.warning( + 'color diagnostics have been requested but are not supported ' + 'by the compiler') + else: + self.cxx.flags += [color_flag] + + def configure_debug_mode(self): + debug_level = self.get_lit_conf('debug_level', None) + if not debug_level: + return + if debug_level not in ['0', '1']: + self.lit_config.fatal('Invalid value for debug_level "%s".' + % debug_level) + self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level] + + 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'] + + def configure_sanitizer(self): + san = self.get_lit_conf('use_sanitizer', '').strip() + if san: + # Search for llvm-symbolizer along the compiler path first + # and then along the PATH env variable. + symbolizer_search_paths = os.environ.get('PATH', '') + cxx_path = lit.util.which(self.cxx.path) + if cxx_path is not None: + symbolizer_search_paths = ( + os.path.dirname(cxx_path) + + os.pathsep + symbolizer_search_paths) + llvm_symbolizer = lit.util.which('llvm-symbolizer', + 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: + self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer + self.config.available_features.add('asan') + self.config.available_features.add('sanitizer-new-delete') + elif san == 'Memory' or san == 'MemoryWithOrigins': + self.cxx.flags += ['-fsanitize=memory'] + if san == 'MemoryWithOrigins': + self.cxx.compile_flags += [ + '-fsanitize-memory-track-origins'] + if llvm_symbolizer is not None: + self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer + self.config.available_features.add('msan') + self.config.available_features.add('sanitizer-new-delete') + elif san == 'Undefined': + self.cxx.flags += ['-fsanitize=undefined', + '-fno-sanitize=vptr,function', + '-fno-sanitize-recover'] + self.cxx.compile_flags += ['-O3'] + self.config.available_features.add('ubsan') + elif san == 'Thread': + self.cxx.flags += ['-fsanitize=thread'] + self.config.available_features.add('tsan') + self.config.available_features.add('sanitizer-new-delete') + else: + self.lit_config.fatal('unsupported value for ' + 'use_sanitizer: {0}'.format(san)) + + def configure_coverage(self): + self.generate_coverage = self.get_lit_bool('generate_coverage', False) + if self.generate_coverage: + self.cxx.flags += ['-g', '--coverage'] + self.cxx.compile_flags += ['-O0'] + + def configure_substitutions(self): + sub = self.config.substitutions + # Configure compiler substitions + sub.append(('%cxx', self.cxx.path)) + # Configure flags substitutions + flags_str = ' '.join(self.cxx.flags) + compile_flags_str = ' '.join(self.cxx.compile_flags) + link_flags_str = ' '.join(self.cxx.link_flags) + all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str) + sub.append(('%flags', flags_str)) + sub.append(('%compile_flags', compile_flags_str)) + sub.append(('%link_flags', link_flags_str)) + sub.append(('%all_flags', all_flags)) + # Add compile and link shortcuts + compile_str = (self.cxx.path + ' -o %t.o %s -c ' + flags_str + + compile_flags_str) + link_str = (self.cxx.path + ' -o %t.exe %t.o ' + flags_str + + link_flags_str) + assert type(link_str) is str + build_str = self.cxx.path + ' -o %t.exe %s ' + all_flags + sub.append(('%compile', compile_str)) + sub.append(('%link', link_str)) + sub.append(('%build', build_str)) + # Configure exec prefix substitutions. + exec_env_str = 'env ' if len(self.env) != 0 else '' + for k, v in self.env.items(): + exec_env_str += ' %s=%s' % (k, v) + # Configure run env substitution. + exec_str = '' + if self.lit_config.useValgrind: + exec_str = ' '.join(self.lit_config.valgrindArgs) + exec_env_str + sub.append(('%exec', exec_str)) + # Configure run shortcut + sub.append(('%run', exec_str + ' %t.exe')) + # Configure not program substitions + not_py = os.path.join(self.libcxx_src_root, 'utils', 'not', 'not.py') + not_str = '%s %s' % (sys.executable, not_py) + sub.append(('not', not_str)) + + def configure_triple(self): + # Get or infer the target triple. + self.config.target_triple = self.get_lit_conf('target_triple') + self.use_target = bool(self.config.target_triple) + # If no target triple was given, try to infer it from the compiler + # under test. + if not self.use_target: + target_triple = self.cxx.getTriple() + # Drop sub-major version components from the triple, because the + # current XFAIL handling expects exact matches for feature checks. + # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14 + # The 5th group handles triples greater than 3 parts + # (ex x86_64-pc-linux-gnu). + target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)', + r'\1-\2-\3\5', target_triple) + # linux-gnu is needed in the triple to properly identify linuxes + # that use GLIBC. Handle redhat and opensuse triples as special + # cases and append the missing `-gnu` portion. + if (target_triple.endswith('redhat-linux') or + target_triple.endswith('suse-linux')): + target_triple += '-gnu' + self.config.target_triple = target_triple + self.lit_config.note( + "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) |