|
@@ -1,634 +1,15 @@
|
|
|
-# -*- Python -*- vim: set syntax=python tabstop=4 expandtab cc=80:
|
|
|
-
|
|
|
+# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
|
|
# Configuration file for the 'lit' test runner.
|
|
|
-
|
|
|
-import errno
|
|
|
-import locale
|
|
|
import os
|
|
|
-import platform
|
|
|
-import re
|
|
|
-import shlex
|
|
|
-import signal
|
|
|
-import subprocess
|
|
|
-import sys
|
|
|
-import tempfile
|
|
|
-import time
|
|
|
-
|
|
|
-import lit.Test
|
|
|
-import lit.formats
|
|
|
-import lit.util
|
|
|
-
|
|
|
-class LibcxxTestFormat(lit.formats.FileBasedTest):
|
|
|
- """
|
|
|
- Custom test format handler for use with the test format use by libc++.
|
|
|
-
|
|
|
- Tests fall into two categories:
|
|
|
- FOO.pass.cpp - Executable test which should compile, run, and exit with
|
|
|
- code 0.
|
|
|
- FOO.fail.cpp - Negative test case which is expected to fail compilation.
|
|
|
- """
|
|
|
-
|
|
|
- def __init__(self, cxx_under_test, use_verify_for_fail,
|
|
|
- cpp_flags, ld_flags, exec_env,
|
|
|
- use_ccache=False):
|
|
|
- self.cxx_under_test = cxx_under_test
|
|
|
- self.use_verify_for_fail = use_verify_for_fail
|
|
|
- self.cpp_flags = list(cpp_flags)
|
|
|
- self.ld_flags = list(ld_flags)
|
|
|
- self.exec_env = dict(exec_env)
|
|
|
- self.use_ccache = use_ccache
|
|
|
-
|
|
|
- def execute(self, test, lit_config):
|
|
|
- while True:
|
|
|
- try:
|
|
|
- return self._execute(test, lit_config)
|
|
|
- except OSError, oe:
|
|
|
- if oe.errno != errno.ETXTBSY:
|
|
|
- raise
|
|
|
- time.sleep(0.1)
|
|
|
-
|
|
|
- def _execute(self, test, lit_config):
|
|
|
- # Extract test metadata from the test file.
|
|
|
- requires = []
|
|
|
- unsupported = []
|
|
|
- use_verify = False
|
|
|
- with open(test.getSourcePath()) as f:
|
|
|
- for ln in f:
|
|
|
- if 'XFAIL:' in ln:
|
|
|
- items = ln[ln.index('XFAIL:') + 6:].split(',')
|
|
|
- test.xfails.extend([s.strip() for s in items])
|
|
|
- elif 'REQUIRES:' in ln:
|
|
|
- items = ln[ln.index('REQUIRES:') + 9:].split(',')
|
|
|
- requires.extend([s.strip() for s in items])
|
|
|
- elif 'UNSUPPORTED:' in ln:
|
|
|
- items = ln[ln.index('UNSUPPORTED:') + 12:].split(',')
|
|
|
- unsupported.extend([s.strip() for s in items])
|
|
|
- elif 'USE_VERIFY' in ln and self.use_verify_for_fail:
|
|
|
- use_verify = True
|
|
|
- elif not ln.strip().startswith("//") and ln.strip():
|
|
|
- # Stop at the first non-empty line that is not a C++
|
|
|
- # comment.
|
|
|
- break
|
|
|
-
|
|
|
- # Check that we have the required features.
|
|
|
- #
|
|
|
- # FIXME: For now, this is cribbed from lit.TestRunner, to avoid
|
|
|
- # introducing a dependency there. What we more ideally would like to do
|
|
|
- # is lift the "requires" handling to be a core lit framework feature.
|
|
|
- missing_required_features = [f for f in requires
|
|
|
- if f not in test.config.available_features]
|
|
|
- if missing_required_features:
|
|
|
- return (lit.Test.UNSUPPORTED,
|
|
|
- "Test requires the following features: %s" % (
|
|
|
- ', '.join(missing_required_features),))
|
|
|
-
|
|
|
- unsupported_features = [f for f in unsupported
|
|
|
- if f in test.config.available_features]
|
|
|
- if unsupported_features:
|
|
|
- return (lit.Test.UNSUPPORTED,
|
|
|
- "Test is unsupported with the following features: %s" % (
|
|
|
- ', '.join(unsupported_features),))
|
|
|
-
|
|
|
- # Evaluate the test.
|
|
|
- return self._evaluate_test(test, use_verify, lit_config)
|
|
|
-
|
|
|
- def _make_report(self, cmd, out, err, rc):
|
|
|
- report = "Command: %s\n" % cmd
|
|
|
- report += "Exit Code: %d\n" % rc
|
|
|
- if out:
|
|
|
- report += "Standard Output:\n--\n%s--\n" % out
|
|
|
- if err:
|
|
|
- report += "Standard Error:\n--\n%s--\n" % err
|
|
|
- report += '\n'
|
|
|
- return cmd, report, rc
|
|
|
-
|
|
|
- def _compile(self, output_path, source_path, use_verify=False):
|
|
|
- cmd = [self.cxx_under_test, '-c', '-o', output_path, source_path]
|
|
|
- cmd += self.cpp_flags
|
|
|
- if use_verify:
|
|
|
- cmd += ['-Xclang', '-verify']
|
|
|
- if self.use_ccache:
|
|
|
- cmd = ['ccache'] + cmd
|
|
|
- out, err, rc = lit.util.executeCommand(cmd)
|
|
|
- return cmd, out, err, rc
|
|
|
-
|
|
|
- def _link(self, exec_path, object_path):
|
|
|
- cmd = [self.cxx_under_test, '-o', exec_path, object_path]
|
|
|
- cmd += self.cpp_flags + self.ld_flags
|
|
|
- out, err, rc = lit.util.executeCommand(cmd)
|
|
|
- return cmd, out, err, rc
|
|
|
-
|
|
|
- def _compile_and_link(self, exec_path, source_path):
|
|
|
- object_file = tempfile.NamedTemporaryFile(suffix=".o", delete=False)
|
|
|
- object_path = object_file.name
|
|
|
- object_file.close()
|
|
|
- try:
|
|
|
- cmd, out, err, rc = self._compile(object_path, source_path)
|
|
|
- if rc != 0:
|
|
|
- return cmd, out, err, rc
|
|
|
- return self._link(exec_path, object_path)
|
|
|
- finally:
|
|
|
- try:
|
|
|
- os.remove(object_path)
|
|
|
- except:
|
|
|
- pass
|
|
|
-
|
|
|
- def _build(self, exec_path, source_path, compile_only=False,
|
|
|
- use_verify=False):
|
|
|
- if compile_only:
|
|
|
- cmd, out, err, rc = self._compile(exec_path, source_path, use_verify)
|
|
|
- else:
|
|
|
- assert not use_verify
|
|
|
- cmd, out, err, rc = self._compile_and_link(exec_path, source_path)
|
|
|
- return self._make_report(cmd, out, err, rc)
|
|
|
-
|
|
|
- def _clean(self, exec_path):
|
|
|
- os.remove(exec_path)
|
|
|
-
|
|
|
- def _run(self, exec_path, lit_config, in_dir=None):
|
|
|
- cmd = []
|
|
|
- if self.exec_env:
|
|
|
- cmd.append('env')
|
|
|
- cmd.extend('%s=%s' % (name, value)
|
|
|
- for name,value in self.exec_env.items())
|
|
|
- cmd.append(exec_path)
|
|
|
- if lit_config.useValgrind:
|
|
|
- cmd = lit_config.valgrindArgs + cmd
|
|
|
- out, err, rc = lit.util.executeCommand(cmd, cwd=in_dir)
|
|
|
- return self._make_report(cmd, out, err, rc)
|
|
|
-
|
|
|
- def _evaluate_test(self, test, use_verify, lit_config):
|
|
|
- name = test.path_in_suite[-1]
|
|
|
- source_path = test.getSourcePath()
|
|
|
- source_dir = os.path.dirname(source_path)
|
|
|
-
|
|
|
- # Check what kind of test this is.
|
|
|
- assert name.endswith('.pass.cpp') or name.endswith('.fail.cpp')
|
|
|
- expected_compile_fail = name.endswith('.fail.cpp')
|
|
|
-
|
|
|
- # If this is a compile (failure) test, build it and check for failure.
|
|
|
- if expected_compile_fail:
|
|
|
- cmd, report, rc = self._build('/dev/null', source_path,
|
|
|
- compile_only=True,
|
|
|
- use_verify=use_verify)
|
|
|
- expected_rc = 0 if use_verify else 1
|
|
|
- if rc == expected_rc:
|
|
|
- return lit.Test.PASS, ""
|
|
|
- else:
|
|
|
- return lit.Test.FAIL, report + 'Expected compilation to fail!\n'
|
|
|
- else:
|
|
|
- exec_file = tempfile.NamedTemporaryFile(suffix="exe", delete=False)
|
|
|
- exec_path = exec_file.name
|
|
|
- exec_file.close()
|
|
|
-
|
|
|
- try:
|
|
|
- cmd, report, rc = self._build(exec_path, source_path)
|
|
|
- compile_cmd = cmd
|
|
|
- if rc != 0:
|
|
|
- report += "Compilation failed unexpectedly!"
|
|
|
- return lit.Test.FAIL, report
|
|
|
-
|
|
|
- cmd, report, rc = self._run(exec_path, lit_config,
|
|
|
- source_dir)
|
|
|
- if rc != 0:
|
|
|
- report = "Compiled With: %s\n%s" % (compile_cmd, report)
|
|
|
- report += "Compiled test failed unexpectedly!"
|
|
|
- return lit.Test.FAIL, report
|
|
|
- finally:
|
|
|
- try:
|
|
|
- # Note that cleanup of exec_file happens in `_clean()`. If
|
|
|
- # you override this, cleanup is your reponsibility.
|
|
|
- self._clean(exec_path)
|
|
|
- except:
|
|
|
- pass
|
|
|
- return lit.Test.PASS, ""
|
|
|
-
|
|
|
-
|
|
|
-class Configuration(object):
|
|
|
- def __init__(self, lit_config, config):
|
|
|
- self.lit_config = lit_config
|
|
|
- self.config = config
|
|
|
- self.cxx = None
|
|
|
- self.src_root = None
|
|
|
- self.obj_root = None
|
|
|
- self.library_root = None
|
|
|
- self.env = {}
|
|
|
- self.compile_flags = []
|
|
|
- self.link_flags = []
|
|
|
- self.use_system_lib = False
|
|
|
- self.use_clang_verify = False
|
|
|
- self.use_ccache = False
|
|
|
-
|
|
|
- if platform.system() not in ('Darwin', 'FreeBSD', 'Linux'):
|
|
|
- self.lit_config.fatal("unrecognized system")
|
|
|
-
|
|
|
- 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
|
|
|
+import site
|
|
|
|
|
|
- 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))
|
|
|
+site.addsitedir(os.path.dirname(__file__))
|
|
|
|
|
|
- def configure(self):
|
|
|
- self.configure_cxx()
|
|
|
- self.probe_cxx()
|
|
|
- self.configure_triple()
|
|
|
- self.configure_src_root()
|
|
|
- self.configure_obj_root()
|
|
|
- self.configure_library_root()
|
|
|
- self.configure_use_system_lib()
|
|
|
- self.configure_use_clang_verify()
|
|
|
- self.configure_ccache()
|
|
|
- self.configure_env()
|
|
|
- self.configure_compile_flags()
|
|
|
- self.configure_link_flags()
|
|
|
- self.configure_sanitizer()
|
|
|
- self.configure_features()
|
|
|
- # Print the final compile and link flags.
|
|
|
- self.lit_config.note('Using compile flags: %s' % self.compile_flags)
|
|
|
- self.lit_config.note('Using link flags: %s' % self.link_flags)
|
|
|
- # Print as list to prevent "set([...])" from being printed.
|
|
|
- self.lit_config.note('Using available_features: %s' %
|
|
|
- list(self.config.available_features))
|
|
|
|
|
|
- def get_test_format(self):
|
|
|
- return LibcxxTestFormat(
|
|
|
- self.cxx,
|
|
|
- self.use_clang_verify,
|
|
|
- cpp_flags=self.compile_flags,
|
|
|
- ld_flags=self.link_flags,
|
|
|
- exec_env=self.env,
|
|
|
- use_ccache=self.use_ccache)
|
|
|
-
|
|
|
- def configure_cxx(self):
|
|
|
- # Gather various compiler parameters.
|
|
|
- self.cxx = self.get_lit_conf('cxx_under_test')
|
|
|
-
|
|
|
- # If no specific cxx_under_test was given, attempt to infer it as
|
|
|
- # clang++.
|
|
|
- if self.cxx is None:
|
|
|
- clangxx = lit.util.which('clang++',
|
|
|
- self.config.environment['PATH'])
|
|
|
- if clangxx:
|
|
|
- self.cxx = clangxx
|
|
|
- self.lit_config.note(
|
|
|
- "inferred cxx_under_test as: %r" % self.cxx)
|
|
|
- if not self.cxx:
|
|
|
- self.lit_config.fatal('must specify user parameter cxx_under_test '
|
|
|
- '(e.g., --param=cxx_under_test=clang++)')
|
|
|
-
|
|
|
- def probe_cxx(self):
|
|
|
- # Dump all of the predefined macros
|
|
|
- dump_macro_cmd = [self.cxx, '-dM', '-E', '-x', 'c++', '/dev/null']
|
|
|
- out, err, rc = lit.util.executeCommand(dump_macro_cmd)
|
|
|
- if rc != 0:
|
|
|
- self.lit_config.warning('Failed to dump macros for compiler: %s' %
|
|
|
- self.cxx)
|
|
|
- return
|
|
|
- # Create a dict containing all the predefined macros.
|
|
|
- macros = {}
|
|
|
- lines = [l.strip() for l in out.split('\n') if l.strip()]
|
|
|
- for l in lines:
|
|
|
- assert l.startswith('#define ')
|
|
|
- l = l[len('#define '):]
|
|
|
- macro, _, value = l.partition(' ')
|
|
|
- macros[macro] = value
|
|
|
- # Add compiler information to available features.
|
|
|
- compiler_name = None
|
|
|
- major_ver = minor_ver = None
|
|
|
- if '__clang__' in macros.keys():
|
|
|
- compiler_name = 'clang'
|
|
|
- # Treat apple's llvm fork differently.
|
|
|
- if '__apple_build_version__' in macros.keys():
|
|
|
- compiler_name = 'apple-clang'
|
|
|
- major_ver = macros['__clang_major__']
|
|
|
- minor_ver = macros['__clang_minor__']
|
|
|
- elif '__GNUC__' in macros.keys():
|
|
|
- compiler_name = 'gcc'
|
|
|
- major_ver = macros['__GNUC__']
|
|
|
- minor_ver = macros['__GNUC_MINOR__']
|
|
|
- else:
|
|
|
- self.lit_config.warning('Failed to detect compiler for cxx: %s' %
|
|
|
- self.cxx)
|
|
|
- if compiler_name is not None:
|
|
|
- self.config.available_features.add(compiler_name)
|
|
|
- self.config.available_features.add('%s-%s.%s' % (
|
|
|
- compiler_name, major_ver, minor_ver))
|
|
|
-
|
|
|
- def configure_src_root(self):
|
|
|
- self.src_root = self.get_lit_conf(
|
|
|
- 'libcxx_src_root', os.path.dirname(self.config.test_source_root))
|
|
|
-
|
|
|
- def configure_obj_root(self):
|
|
|
- self.obj_root = self.get_lit_conf('libcxx_obj_root', self.src_root)
|
|
|
-
|
|
|
- def configure_library_root(self):
|
|
|
- self.library_root = self.get_lit_conf('libcxx_library_root', self.obj_root)
|
|
|
-
|
|
|
- def configure_use_system_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_lib = self.get_lit_bool('use_system_lib')
|
|
|
- if self.use_system_lib is None:
|
|
|
- # Default to testing against the locally built libc++ library.
|
|
|
- self.use_system_lib = False
|
|
|
- self.lit_config.note(
|
|
|
- "inferred use_system_lib as: %r" % self.use_system_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:
|
|
|
- # TODO: Default this to True when using clang.
|
|
|
- self.use_clang_verify = False
|
|
|
- self.lit_config.note(
|
|
|
- "inferred use_clang_verify as: %r" % self.use_clang_verify)
|
|
|
-
|
|
|
- def configure_ccache(self):
|
|
|
- self.use_ccache = self.get_lit_bool('use_ccache', False)
|
|
|
- if self.use_ccache:
|
|
|
- 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': 'cs_CZ.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',
|
|
|
- },
|
|
|
- }
|
|
|
-
|
|
|
- default_locale = locale.setlocale(locale.LC_ALL)
|
|
|
- for feature, loc in locales[platform.system()].items():
|
|
|
- try:
|
|
|
- locale.setlocale(locale.LC_ALL, loc)
|
|
|
- self.config.available_features.add('locale.{0}'.format(feature))
|
|
|
- except:
|
|
|
- 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)
|
|
|
-
|
|
|
- # Write an "available feature" that combines the triple when
|
|
|
- # use_system_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_lib:
|
|
|
- self.config.available_features.add(
|
|
|
- 'with_system_lib=%s' % self.config.target_triple)
|
|
|
-
|
|
|
- # 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 sys.platform.startswith('linux'):
|
|
|
- name, ver, _ = platform.linux_distribution()
|
|
|
- name = name.lower().strip()
|
|
|
- ver = ver.lower().strip()
|
|
|
- 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')
|
|
|
-
|
|
|
- def configure_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.compile_flags += ['-std={0}'.format(std)]
|
|
|
- self.config.available_features.add(std)
|
|
|
- # Configure include paths
|
|
|
- self.compile_flags += ['-nostdinc++']
|
|
|
- self.compile_flags += ['-I' + self.src_root + '/test/support']
|
|
|
- libcxx_headers = self.get_lit_conf('libcxx_headers',
|
|
|
- self.src_root + '/include')
|
|
|
- if not os.path.isdir(libcxx_headers):
|
|
|
- self.lit_config.fatal("libcxx_headers='%s' is not a directory."
|
|
|
- % libcxx_headers)
|
|
|
- self.compile_flags += ['-I' + libcxx_headers]
|
|
|
- if sys.platform.startswith('linux'):
|
|
|
- self.compile_flags += ['-D__STDC_FORMAT_MACROS',
|
|
|
- '-D__STDC_LIMIT_MACROS',
|
|
|
- '-D__STDC_CONSTANT_MACROS']
|
|
|
- # Configure feature flags.
|
|
|
- enable_exceptions = self.get_lit_bool('enable_exceptions', True)
|
|
|
- if enable_exceptions:
|
|
|
- self.config.available_features.add('exceptions')
|
|
|
- else:
|
|
|
- self.compile_flags += ['-fno-exceptions']
|
|
|
- enable_rtti = self.get_lit_bool('enable_rtti', True)
|
|
|
- if enable_rtti:
|
|
|
- self.config.available_features.add('rtti')
|
|
|
- else:
|
|
|
- self.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
|
|
|
- enable_32bit = self.get_lit_bool('enable_32bit', False)
|
|
|
- if enable_32bit:
|
|
|
- self.compile_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.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS']
|
|
|
- self.config.available_features.add('libcpp-has-no-threads')
|
|
|
- if not enable_monotonic_clock:
|
|
|
- self.compile_flags += ['-D_LIBCPP_HAS_NO_MONOTONIC_CLOCK']
|
|
|
- self.config.available_features.add('libcpp-has-no-monotonic-clock')
|
|
|
- elif not enable_monotonic_clock:
|
|
|
- self.lit_config.fatal('enable_monotonic_clock cannot be false when'
|
|
|
- ' enable_threads is true.')
|
|
|
- # Use verbose output for better errors
|
|
|
- self.compile_flags += ['-v']
|
|
|
- # Configure extra compile flags.
|
|
|
- compile_flags_str = self.get_lit_conf('compile_flags', '')
|
|
|
- self.compile_flags += shlex.split(compile_flags_str)
|
|
|
-
|
|
|
-
|
|
|
- def configure_link_flags(self):
|
|
|
- self.link_flags += ['-nodefaultlibs']
|
|
|
- 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_lib:
|
|
|
- self.lit_config.fatal("Conflicting options: 'libcxx_library'"
|
|
|
- " cannot be used with 'use_system_lib=true'")
|
|
|
- self.link_flags += ['-Wl,-rpath,' + os.path.dirname(libcxx_library)]
|
|
|
- elif not self.use_system_lib:
|
|
|
- self.link_flags += ['-L' + self.library_root,
|
|
|
- '-Wl,-rpath,' + self.library_root]
|
|
|
- # Configure ABI library paths.
|
|
|
- abi_library_path = self.get_lit_conf('abi_library_path', '')
|
|
|
- if abi_library_path:
|
|
|
- self.link_flags += ['-L' + abi_library_path,
|
|
|
- '-Wl,-rpath,' + abi_library_path]
|
|
|
- # Configure libraries
|
|
|
- if libcxx_library:
|
|
|
- self.link_flags += [libcxx_library]
|
|
|
- else:
|
|
|
- self.link_flags += ['-lc++']
|
|
|
- cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
|
|
|
- if cxx_abi == 'libstdc++':
|
|
|
- self.link_flags += ['-lstdc++']
|
|
|
- elif cxx_abi == 'libsupc++':
|
|
|
- self.link_flags += ['-lsupc++']
|
|
|
- elif cxx_abi == 'libcxxabi':
|
|
|
- self.link_flags += ['-lc++abi']
|
|
|
- elif cxx_abi == 'libcxxrt':
|
|
|
- self.link_flags += ['-lcxxrt']
|
|
|
- elif cxx_abi == 'none':
|
|
|
- pass
|
|
|
- else:
|
|
|
- self.lit_config.fatal(
|
|
|
- 'C++ ABI setting %s unsupported for tests' % cxx_abi)
|
|
|
- # Configure extra libraries.
|
|
|
- if sys.platform == 'darwin':
|
|
|
- self.link_flags += ['-lSystem']
|
|
|
- elif sys.platform.startswith('linux'):
|
|
|
- self.link_flags += ['-lgcc_eh', '-lc', '-lm', '-lpthread',
|
|
|
- '-lrt', '-lgcc_s']
|
|
|
- elif sys.platform.startswith('freebsd'):
|
|
|
- self.link_flags += ['-lc', '-lm', '-pthread', '-lgcc_s']
|
|
|
- else:
|
|
|
- self.lit_config.fatal("unrecognized system: %r" % sys.platform)
|
|
|
-
|
|
|
- link_flags_str = self.get_lit_conf('link_flags', '')
|
|
|
- self.link_flags += shlex.split(link_flags_str)
|
|
|
-
|
|
|
-
|
|
|
- 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)
|
|
|
- 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.compile_flags += ['-g', '-fno-omit-frame-pointer']
|
|
|
- if sys.platform.startswith('linux'):
|
|
|
- self.link_flags += ['-ldl']
|
|
|
- if san == 'Address':
|
|
|
- self.compile_flags += ['-fsanitize=address']
|
|
|
- if llvm_symbolizer is not None:
|
|
|
- self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
|
|
- self.config.available_features.add('asan')
|
|
|
- elif san == 'Memory' or san == 'MemoryWithOrigins':
|
|
|
- self.compile_flags += ['-fsanitize=memory']
|
|
|
- if san == 'MemoryWithOrigins':
|
|
|
- self.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')
|
|
|
- elif san == 'Undefined':
|
|
|
- self.compile_flags += ['-fsanitize=undefined',
|
|
|
- '-fno-sanitize=vptr,function',
|
|
|
- '-fno-sanitize-recover', '-O3']
|
|
|
- self.config.available_features.add('ubsan')
|
|
|
- elif san == 'Thread':
|
|
|
- self.compile_flags += ['-fsanitize=thread']
|
|
|
- self.config.available_features.add('tsan')
|
|
|
- else:
|
|
|
- self.lit_config.fatal('unsupported value for '
|
|
|
- 'libcxx_use_san: {0}'.format(san))
|
|
|
-
|
|
|
- def configure_triple(self):
|
|
|
- # Get or infer the target triple.
|
|
|
- self.config.target_triple = self.get_lit_conf('target_triple')
|
|
|
- # If no target triple was given, try to infer it from the compiler
|
|
|
- # under test.
|
|
|
- if not self.config.target_triple:
|
|
|
- target_triple = lit.util.capture(
|
|
|
- [self.cxx, '-dumpmachine']).strip()
|
|
|
- # 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 sys.platform == 'darwin' and not self.use_system_lib:
|
|
|
- libcxx_library = self.get_lit_conf('libcxx_library')
|
|
|
- if libcxx_library:
|
|
|
- library_root = os.path.dirname(libcxx_library)
|
|
|
- else:
|
|
|
- library_root = self.library_root
|
|
|
- self.env['DYLD_LIBRARY_PATH'] = library_root
|
|
|
+# Tell pylint that we know config and lit_config exist somewhere.
|
|
|
+if 'PYLINT_IMPORT' in os.environ:
|
|
|
+ config = object()
|
|
|
+ lit_config = object()
|
|
|
|
|
|
# name: The name of this test suite.
|
|
|
config.name = 'libc++'
|
|
@@ -659,19 +40,21 @@ if config.test_exec_root is None:
|
|
|
# can be placed. This is needed for ShTest.
|
|
|
elif not os.path.isfile(site_cfg):
|
|
|
lit_config.fatal(
|
|
|
- "Specified site configuration file does not exist: '%s'" %
|
|
|
+ "Specified site configuration file does not exist: '%s'" %
|
|
|
site_cfg)
|
|
|
else:
|
|
|
lit_config.note('using site specific configuration at %s' % site_cfg)
|
|
|
lit_config.load_config(config, site_cfg)
|
|
|
raise SystemExit()
|
|
|
|
|
|
-
|
|
|
-cfg_variant = getattr(config, 'configuration_variant', '')
|
|
|
+cfg_variant = getattr(config, 'configuration_variant', 'libcxx')
|
|
|
if cfg_variant:
|
|
|
print 'Using configuration variant: %s' % cfg_variant
|
|
|
|
|
|
-# Construct an object of the type named `<VARIANT>Configuration`.
|
|
|
-configuration = globals()['%sConfiguration' % cfg_variant](lit_config, config)
|
|
|
+# Load the Configuration class from the module name <cfg_variant>.test.config.
|
|
|
+config_module_name = '.'.join([cfg_variant, 'test', 'config'])
|
|
|
+config_module = __import__(config_module_name, fromlist=['Configuration'])
|
|
|
+
|
|
|
+configuration = config_module.Configuration(lit_config, config)
|
|
|
configuration.configure()
|
|
|
config.test_format = configuration.get_test_format()
|