|
@@ -1,1113 +1,1113 @@
|
|
|
-#===----------------------------------------------------------------------===##
|
|
|
-#
|
|
|
-# The LLVM Compiler Infrastructure
|
|
|
-#
|
|
|
-# This file is dual licensed under the MIT and the University of Illinois Open
|
|
|
-# Source Licenses. See LICENSE.TXT for details.
|
|
|
-#
|
|
|
-#===----------------------------------------------------------------------===##
|
|
|
-
|
|
|
-import locale
|
|
|
-import os
|
|
|
-import platform
|
|
|
-import pkgutil
|
|
|
-import pipes
|
|
|
-import re
|
|
|
-import shlex
|
|
|
-import shutil
|
|
|
-import sys
|
|
|
-
|
|
|
-from libcxx.compiler import CXXCompiler
|
|
|
-from libcxx.test.target_info import make_target_info
|
|
|
-from libcxx.test.executor import *
|
|
|
-from libcxx.test.tracing import *
|
|
|
-import libcxx.util
|
|
|
-
|
|
|
-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.is_windows = platform.system() == 'Windows'
|
|
|
- self.cxx = None
|
|
|
- self.cxx_is_clang_cl = None
|
|
|
- self.cxx_stdlib_under_test = None
|
|
|
- self.project_obj_root = None
|
|
|
- self.libcxx_src_root = None
|
|
|
- self.libcxx_obj_root = None
|
|
|
- self.cxx_library_root = None
|
|
|
- self.cxx_runtime_root = None
|
|
|
- self.abi_library_root = None
|
|
|
- self.link_shared = self.get_lit_bool('enable_shared', default=True)
|
|
|
- self.debug_build = self.get_lit_bool('debug_build', default=False)
|
|
|
- self.exec_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, env_var=None):
|
|
|
- def check_value(value, var_name):
|
|
|
- if value is None:
|
|
|
- return default
|
|
|
- if isinstance(value, bool):
|
|
|
- return value
|
|
|
- if not isinstance(value, str):
|
|
|
- raise TypeError('expected bool or string')
|
|
|
- if value.lower() in ('1', 'true'):
|
|
|
- return True
|
|
|
- if value.lower() in ('', '0', 'false'):
|
|
|
- return False
|
|
|
- self.lit_config.fatal(
|
|
|
- "parameter '{}' should be true or false".format(var_name))
|
|
|
-
|
|
|
- conf_val = self.get_lit_conf(name)
|
|
|
- if env_var is not None and env_var in os.environ and \
|
|
|
- os.environ[env_var] is not None:
|
|
|
- val = os.environ[env_var]
|
|
|
- if conf_val is not None:
|
|
|
- self.lit_config.warning(
|
|
|
- 'Environment variable %s=%s is overriding explicit '
|
|
|
- '--param=%s=%s' % (env_var, val, name, conf_val))
|
|
|
- return check_value(val, env_var)
|
|
|
- return check_value(conf_val, name)
|
|
|
-
|
|
|
- def make_static_lib_name(self, name):
|
|
|
- """Return the full filename for the specified library name"""
|
|
|
- if self.is_windows:
|
|
|
- assert name == 'c++' # Only allow libc++ to use this function for now.
|
|
|
- return 'lib' + name + '.lib'
|
|
|
- else:
|
|
|
- return 'lib' + name + '.a'
|
|
|
-
|
|
|
- def configure(self):
|
|
|
- self.configure_executor()
|
|
|
- self.configure_use_system_cxx_lib()
|
|
|
- self.configure_target_info()
|
|
|
- self.configure_cxx()
|
|
|
- self.configure_triple()
|
|
|
- self.configure_deployment()
|
|
|
- self.configure_availability()
|
|
|
- self.configure_src_root()
|
|
|
- self.configure_obj_root()
|
|
|
- self.configure_cxx_stdlib_under_test()
|
|
|
- self.configure_cxx_library_root()
|
|
|
- self.configure_use_clang_verify()
|
|
|
- self.configure_use_thread_safety()
|
|
|
- self.configure_execute_external()
|
|
|
- self.configure_ccache()
|
|
|
- self.configure_compile_flags()
|
|
|
- self.configure_filesystem_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_modules()
|
|
|
- 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)
|
|
|
- if self.cxx.use_modules:
|
|
|
- self.lit_config.note('Using modules flags: %s' %
|
|
|
- self.cxx.modules_flags)
|
|
|
- self.lit_config.note('Using compile flags: %s'
|
|
|
- % self.cxx.compile_flags)
|
|
|
- if len(self.cxx.warning_flags):
|
|
|
- self.lit_config.note('Using warnings: %s' % self.cxx.warning_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.exec_env)
|
|
|
- sys.stderr.flush() # Force flushing to avoid broken output on Windows
|
|
|
-
|
|
|
- def get_test_format(self):
|
|
|
- from libcxx.test.format import LibcxxTestFormat
|
|
|
- return LibcxxTestFormat(
|
|
|
- self.cxx,
|
|
|
- self.use_clang_verify,
|
|
|
- self.execute_external,
|
|
|
- self.executor,
|
|
|
- exec_env=self.exec_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):
|
|
|
- self.target_info = make_target_info(self)
|
|
|
-
|
|
|
- def configure_cxx(self):
|
|
|
- # Gather various compiler parameters.
|
|
|
- cxx = self.get_lit_conf('cxx_under_test')
|
|
|
- self.cxx_is_clang_cl = cxx is not None and \
|
|
|
- os.path.basename(cxx) == 'clang-cl.exe'
|
|
|
- # If no specific cxx_under_test was given, attempt to infer it as
|
|
|
- # clang++.
|
|
|
- if cxx is None or self.cxx_is_clang_cl:
|
|
|
- search_paths = self.config.environment['PATH']
|
|
|
- if cxx is not None and os.path.isabs(cxx):
|
|
|
- search_paths = os.path.dirname(cxx)
|
|
|
- clangxx = libcxx.util.which('clang++', search_paths)
|
|
|
- if clangxx:
|
|
|
- cxx = clangxx
|
|
|
- self.lit_config.note(
|
|
|
- "inferred cxx_under_test as: %r" % cxx)
|
|
|
- elif self.cxx_is_clang_cl:
|
|
|
- self.lit_config.fatal('Failed to find clang++ substitution for'
|
|
|
- ' clang-cl')
|
|
|
- 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) if not self.cxx_is_clang_cl else \
|
|
|
- self._configure_clang_cl(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' % (cxx_type, maj_v))
|
|
|
- self.config.available_features.add('%s-%s.%s' % (
|
|
|
- cxx_type, maj_v, min_v))
|
|
|
- self.cxx.compile_env = dict(os.environ)
|
|
|
- # 'CCACHE_CPP2' prevents ccache from stripping comments while
|
|
|
- # preprocessing. This is required to prevent stripping of '-verify'
|
|
|
- # comments.
|
|
|
- self.cxx.compile_env['CCACHE_CPP2'] = '1'
|
|
|
-
|
|
|
- def _configure_clang_cl(self, clang_path):
|
|
|
- def _split_env_var(var):
|
|
|
- return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()]
|
|
|
-
|
|
|
- def _prefixed_env_list(var, prefix):
|
|
|
- from itertools import chain
|
|
|
- return list(chain.from_iterable((prefix, path) for path in _split_env_var(var)))
|
|
|
-
|
|
|
- assert self.cxx_is_clang_cl
|
|
|
- flags = []
|
|
|
- compile_flags = _prefixed_env_list('INCLUDE', '-isystem')
|
|
|
- link_flags = _prefixed_env_list('LIB', '-L')
|
|
|
- for path in _split_env_var('LIB'):
|
|
|
- self.add_path(self.exec_env, path)
|
|
|
- return CXXCompiler(clang_path, flags=flags,
|
|
|
- compile_flags=compile_flags,
|
|
|
- link_flags=link_flags)
|
|
|
-
|
|
|
-
|
|
|
- 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.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',
|
|
|
- self.libcxx_obj_root)
|
|
|
- self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root',
|
|
|
- self.cxx_library_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.
|
|
|
- # Default to testing against the locally built libc++ library.
|
|
|
- self.use_system_cxx_lib = self.get_lit_conf('use_system_cxx_lib')
|
|
|
- if self.use_system_cxx_lib == 'true':
|
|
|
- self.use_system_cxx_lib = True
|
|
|
- elif self.use_system_cxx_lib == 'false':
|
|
|
- self.use_system_cxx_lib = False
|
|
|
- elif self.use_system_cxx_lib:
|
|
|
- assert os.path.isdir(self.use_system_cxx_lib)
|
|
|
- self.lit_config.note(
|
|
|
- "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
|
|
|
-
|
|
|
- def configure_availability(self):
|
|
|
- # See http://llvm.org/docs/AvailabilityMarkup.html
|
|
|
- self.with_availability = self.get_lit_bool('with_availability', False)
|
|
|
- self.lit_config.note(
|
|
|
- "inferred with_availability as: %r" % self.with_availability)
|
|
|
-
|
|
|
- def configure_cxx_stdlib_under_test(self):
|
|
|
- self.cxx_stdlib_under_test = self.get_lit_conf(
|
|
|
- 'cxx_stdlib_under_test', 'libc++')
|
|
|
- if self.cxx_stdlib_under_test not in \
|
|
|
- ['libc++', 'libstdc++', 'msvc', 'cxx_default']:
|
|
|
- self.lit_config.fatal(
|
|
|
- 'unsupported value for "cxx_stdlib_under_test": %s'
|
|
|
- % self.cxx_stdlib_under_test)
|
|
|
- self.config.available_features.add(self.cxx_stdlib_under_test)
|
|
|
- if self.cxx_stdlib_under_test == 'libstdc++':
|
|
|
- self.config.available_features.add('libstdc++')
|
|
|
- # Manually enable the experimental and filesystem tests for libstdc++
|
|
|
- # if the options aren't present.
|
|
|
- # FIXME this is a hack.
|
|
|
- if self.get_lit_conf('enable_experimental') is None:
|
|
|
- self.config.enable_experimental = 'true'
|
|
|
- if self.get_lit_conf('enable_filesystem') is None:
|
|
|
- self.config.enable_filesystem = 'true'
|
|
|
-
|
|
|
- def configure_use_clang_verify(self):
|
|
|
- '''If set, run clang with -verify on failing tests.'''
|
|
|
- if self.with_availability:
|
|
|
- self.use_clang_verify = False
|
|
|
- return
|
|
|
- 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.isVerifySupported()
|
|
|
- self.lit_config.note(
|
|
|
- "inferred use_clang_verify as: %r" % self.use_clang_verify)
|
|
|
- if self.use_clang_verify:
|
|
|
- self.config.available_features.add('verify-support')
|
|
|
-
|
|
|
- def configure_use_thread_safety(self):
|
|
|
- '''If set, run clang with -verify on failing tests.'''
|
|
|
- has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
|
|
|
- if has_thread_safety:
|
|
|
- self.cxx.compile_flags += ['-Werror=thread-safety']
|
|
|
- self.config.available_features.add('thread-safety')
|
|
|
- self.lit_config.note("enabling thread-safety annotations")
|
|
|
-
|
|
|
- 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 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 = 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',
|
|
|
- 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 add_deployment_feature(self, feature):
|
|
|
- (arch, name, version) = self.config.deployment
|
|
|
- self.config.available_features.add('%s=%s-%s' % (feature, arch, name))
|
|
|
- self.config.available_features.add('%s=%s' % (feature, name))
|
|
|
- self.config.available_features.add('%s=%s%s' % (feature, name, version))
|
|
|
-
|
|
|
- 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())
|
|
|
- self.target_info.add_locale_features(self.config.available_features)
|
|
|
-
|
|
|
- target_platform = self.target_info.platform()
|
|
|
-
|
|
|
- # 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')
|
|
|
- self.config.available_features.add(
|
|
|
- 'with_system_cxx_lib=%s' % self.config.target_triple)
|
|
|
-
|
|
|
- # Add subcomponents individually.
|
|
|
- target_components = self.config.target_triple.split('-')
|
|
|
- for component in target_components:
|
|
|
- self.config.available_features.add(
|
|
|
- 'with_system_cxx_lib=%s' % component)
|
|
|
-
|
|
|
- # Add available features for more generic versions of the target
|
|
|
- # triple attached to with_system_cxx_lib.
|
|
|
- if self.use_deployment:
|
|
|
- self.add_deployment_feature('with_system_cxx_lib')
|
|
|
-
|
|
|
- # Configure the availability markup checks features.
|
|
|
- if self.with_availability:
|
|
|
- self.config.available_features.add('availability_markup')
|
|
|
- self.add_deployment_feature('availability_markup')
|
|
|
-
|
|
|
- if self.use_system_cxx_lib or self.with_availability:
|
|
|
- self.config.available_features.add('availability')
|
|
|
- self.add_deployment_feature('availability')
|
|
|
-
|
|
|
- if platform.system() == 'Darwin':
|
|
|
- self.config.available_features.add('apple-darwin')
|
|
|
-
|
|
|
- # Insert the platform name into the available features as a lower case.
|
|
|
- self.config.available_features.add(target_platform)
|
|
|
-
|
|
|
- # 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')
|
|
|
-
|
|
|
- if self.cxx.hasCompileFlag('-faligned-allocation'):
|
|
|
- self.config.available_features.add('-faligned-allocation')
|
|
|
- else:
|
|
|
- # FIXME remove this once more than just clang-4.0 support
|
|
|
- # C++17 aligned allocation.
|
|
|
- self.config.available_features.add('no-aligned-allocation')
|
|
|
-
|
|
|
- if self.get_lit_bool('has_libatomic', False):
|
|
|
- self.config.available_features.add('libatomic')
|
|
|
-
|
|
|
- macros = self.cxx.dumpMacros()
|
|
|
- if '__cpp_if_constexpr' not in macros:
|
|
|
- self.config.available_features.add('libcpp-no-if-constexpr')
|
|
|
-
|
|
|
- if '__cpp_structured_bindings' not in macros:
|
|
|
- self.config.available_features.add('libcpp-no-structured-bindings')
|
|
|
-
|
|
|
- if '__cpp_deduction_guides' not in macros:
|
|
|
- self.config.available_features.add('libcpp-no-deduction-guides')
|
|
|
-
|
|
|
- if self.is_windows:
|
|
|
- self.config.available_features.add('windows')
|
|
|
- if self.cxx_stdlib_under_test == 'libc++':
|
|
|
- # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
|
|
|
- # initial Windows failures until they can be properly diagnosed
|
|
|
- # and fixed. This allows easier detection of new test failures
|
|
|
- # and regressions. Note: New failures should not be suppressed
|
|
|
- # using this feature. (Also see llvm.org/PR32730)
|
|
|
- self.config.available_features.add('LIBCXX-WINDOWS-FIXME')
|
|
|
-
|
|
|
- # Attempt to detect the glibc version by querying for __GLIBC__
|
|
|
- # in 'features.h'.
|
|
|
- macros = self.cxx.dumpMacros(flags=['-include', 'features.h'])
|
|
|
- if macros is not None and '__GLIBC__' in macros:
|
|
|
- maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__'])
|
|
|
- self.config.available_features.add('glibc')
|
|
|
- self.config.available_features.add('glibc-%s' % maj_v)
|
|
|
- self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v))
|
|
|
-
|
|
|
- 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()
|
|
|
- # This include is always needed so add so add it regardless of
|
|
|
- # 'no_default_flags'.
|
|
|
- support_path = os.path.join(self.libcxx_src_root, 'test/support')
|
|
|
- self.cxx.compile_flags += ['-I' + support_path]
|
|
|
- # Configure extra flags
|
|
|
- compile_flags_str = self.get_lit_conf('compile_flags', '')
|
|
|
- self.cxx.compile_flags += shlex.split(compile_flags_str)
|
|
|
- # FIXME: Can we remove this?
|
|
|
- if self.is_windows:
|
|
|
- self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS']
|
|
|
-
|
|
|
- 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')
|
|
|
- if not std:
|
|
|
- # Choose the newest possible language dialect if none is given.
|
|
|
- possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03']
|
|
|
- if self.cxx.type == 'gcc':
|
|
|
- maj_v, _, _ = self.cxx.version
|
|
|
- maj_v = int(maj_v)
|
|
|
- if maj_v < 7:
|
|
|
- possible_stds.remove('c++1z')
|
|
|
- # FIXME: How many C++14 tests actually fail under GCC 5 and 6?
|
|
|
- # Should we XFAIL them individually instead?
|
|
|
- if maj_v <= 6:
|
|
|
- possible_stds.remove('c++14')
|
|
|
- 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.replace('gnu++', 'c++'))
|
|
|
- # Configure include paths
|
|
|
- self.configure_compile_flags_header_includes()
|
|
|
- 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_abi_version()
|
|
|
- enable_32bit = self.get_lit_bool('enable_32bit', False)
|
|
|
- if enable_32bit:
|
|
|
- self.cxx.flags += ['-m32']
|
|
|
- # 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]
|
|
|
- # NOTE: the _DEBUG definition must preceed the triple check because for
|
|
|
- # the Windows build of libc++, the forced inclusion of a header requires
|
|
|
- # that _DEBUG is defined. Incorrect ordering will result in -target
|
|
|
- # being elided.
|
|
|
- if self.is_windows and self.debug_build:
|
|
|
- self.cxx.compile_flags += ['-D_DEBUG']
|
|
|
- if self.use_target:
|
|
|
- if not self.cxx.addFlagIfSupported(
|
|
|
- ['-target', self.config.target_triple]):
|
|
|
- self.lit_config.warning('use_target is true but -target is '\
|
|
|
- 'not supported by the compiler')
|
|
|
- if self.use_deployment:
|
|
|
- arch, name, version = self.config.deployment
|
|
|
- self.cxx.flags += ['-arch', arch]
|
|
|
- self.cxx.flags += ['-m' + name + '-version-min=' + version]
|
|
|
-
|
|
|
- # Disable availability unless explicitely requested
|
|
|
- if not self.with_availability:
|
|
|
- self.cxx.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY']
|
|
|
-
|
|
|
- def configure_compile_flags_header_includes(self):
|
|
|
- support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
|
|
|
- self.configure_config_site_header()
|
|
|
- if self.cxx_stdlib_under_test != 'libstdc++' and \
|
|
|
- not self.is_windows:
|
|
|
- self.cxx.compile_flags += [
|
|
|
- '-include', os.path.join(support_path, 'nasty_macros.hpp')]
|
|
|
- if self.cxx_stdlib_under_test == 'msvc':
|
|
|
- self.cxx.compile_flags += [
|
|
|
- '-include', os.path.join(support_path,
|
|
|
- 'msvc_stdlib_force_include.hpp')]
|
|
|
- pass
|
|
|
- if self.is_windows and self.debug_build and \
|
|
|
- self.cxx_stdlib_under_test != 'msvc':
|
|
|
- self.cxx.compile_flags += [
|
|
|
- '-include', os.path.join(support_path,
|
|
|
- 'set_windows_crt_report_mode.h')
|
|
|
- ]
|
|
|
- cxx_headers = self.get_lit_conf('cxx_headers')
|
|
|
- if cxx_headers == '' or (cxx_headers is None
|
|
|
- and self.cxx_stdlib_under_test != 'libc++'):
|
|
|
- self.lit_config.note('using the system cxx headers')
|
|
|
- return
|
|
|
- self.cxx.compile_flags += ['-nostdinc++']
|
|
|
- if cxx_headers is None:
|
|
|
- cxx_headers = os.path.join(self.libcxx_src_root, 'include')
|
|
|
- if not os.path.isdir(cxx_headers):
|
|
|
- self.lit_config.fatal("cxx_headers='%s' is not a directory."
|
|
|
- % cxx_headers)
|
|
|
- self.cxx.compile_flags += ['-I' + cxx_headers]
|
|
|
- if self.libcxx_obj_root is not None:
|
|
|
- cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include',
|
|
|
- 'c++build')
|
|
|
- if os.path.isdir(cxxabi_headers):
|
|
|
- self.cxx.compile_flags += ['-I' + cxxabi_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_DISABLE_VISIBILITY_ANNOTATIONS':
|
|
|
- continue
|
|
|
- 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:
|
|
|
- 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_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_filesystem_compile_flags(self):
|
|
|
- enable_fs = self.get_lit_bool('enable_filesystem', default=False)
|
|
|
- if not enable_fs:
|
|
|
- return
|
|
|
- enable_experimental = self.get_lit_bool('enable_experimental', default=False)
|
|
|
- if not enable_experimental:
|
|
|
- self.lit_config.fatal(
|
|
|
- 'filesystem is enabled but libc++experimental.a is not.')
|
|
|
- self.config.available_features.add('c++filesystem')
|
|
|
- static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
|
|
|
- 'experimental', 'filesystem', 'Inputs', 'static_test_env')
|
|
|
- static_env = os.path.realpath(static_env)
|
|
|
- assert os.path.isdir(static_env)
|
|
|
- self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env]
|
|
|
-
|
|
|
- dynamic_env = os.path.join(self.config.test_exec_root,
|
|
|
- 'filesystem', 'Output', 'dynamic_env')
|
|
|
- dynamic_env = os.path.realpath(dynamic_env)
|
|
|
- if not os.path.isdir(dynamic_env):
|
|
|
- os.makedirs(dynamic_env)
|
|
|
- self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env]
|
|
|
- self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
|
|
|
-
|
|
|
- dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
|
|
|
- 'filesystem_dynamic_test_helper.py')
|
|
|
- assert os.path.isfile(dynamic_helper)
|
|
|
-
|
|
|
- self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"'
|
|
|
- % (sys.executable, dynamic_helper)]
|
|
|
-
|
|
|
-
|
|
|
- def configure_link_flags(self):
|
|
|
- no_default_flags = self.get_lit_bool('no_default_flags', False)
|
|
|
- if not no_default_flags:
|
|
|
- # Configure library path
|
|
|
- self.configure_link_flags_cxx_library_path()
|
|
|
- self.configure_link_flags_abi_library_path()
|
|
|
-
|
|
|
- # Configure libraries
|
|
|
- if self.cxx_stdlib_under_test == 'libc++':
|
|
|
- self.cxx.link_flags += ['-nodefaultlibs']
|
|
|
- # FIXME: Handle MSVCRT as part of the ABI library handling.
|
|
|
- if self.is_windows:
|
|
|
- self.cxx.link_flags += ['-nostdlib']
|
|
|
- self.configure_link_flags_cxx_library()
|
|
|
- self.configure_link_flags_abi_library()
|
|
|
- self.configure_extra_library_flags()
|
|
|
- elif self.cxx_stdlib_under_test == 'libstdc++':
|
|
|
- enable_fs = self.get_lit_bool('enable_filesystem',
|
|
|
- default=False)
|
|
|
- if enable_fs:
|
|
|
- self.config.available_features.add('c++experimental')
|
|
|
- self.cxx.link_flags += ['-lstdc++fs']
|
|
|
- self.cxx.link_flags += ['-lm', '-pthread']
|
|
|
- elif self.cxx_stdlib_under_test == 'msvc':
|
|
|
- # FIXME: Correctly setup debug/release flags here.
|
|
|
- pass
|
|
|
- elif self.cxx_stdlib_under_test == 'cxx_default':
|
|
|
- self.cxx.link_flags += ['-pthread']
|
|
|
- else:
|
|
|
- self.lit_config.fatal(
|
|
|
- 'unsupported value for "use_stdlib_type": %s'
|
|
|
- % use_stdlib_type)
|
|
|
-
|
|
|
- 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):
|
|
|
- if not self.use_system_cxx_lib:
|
|
|
- if self.cxx_library_root:
|
|
|
- self.cxx.link_flags += ['-L' + self.cxx_library_root]
|
|
|
- if self.is_windows and self.link_shared:
|
|
|
- self.add_path(self.cxx.compile_env, self.cxx_library_root)
|
|
|
- if self.cxx_runtime_root:
|
|
|
- if not self.is_windows:
|
|
|
- self.cxx.link_flags += ['-Wl,-rpath,' +
|
|
|
- self.cxx_runtime_root]
|
|
|
- elif self.is_windows and self.link_shared:
|
|
|
- self.add_path(self.exec_env, self.cxx_runtime_root)
|
|
|
- elif os.path.isdir(str(self.use_system_cxx_lib)):
|
|
|
- self.cxx.link_flags += ['-L' + self.use_system_cxx_lib]
|
|
|
- if not self.is_windows:
|
|
|
- self.cxx.link_flags += ['-Wl,-rpath,' +
|
|
|
- self.use_system_cxx_lib]
|
|
|
- if self.is_windows and self.link_shared:
|
|
|
- self.add_path(self.cxx.compile_env, self.use_system_cxx_lib)
|
|
|
-
|
|
|
- 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]
|
|
|
- if not self.is_windows:
|
|
|
- self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root]
|
|
|
- else:
|
|
|
- self.add_path(self.exec_env, self.abi_library_root)
|
|
|
-
|
|
|
- def configure_link_flags_cxx_library(self):
|
|
|
- libcxx_experimental = self.get_lit_bool('enable_experimental', default=False)
|
|
|
- if libcxx_experimental:
|
|
|
- self.config.available_features.add('c++experimental')
|
|
|
- self.cxx.link_flags += ['-lc++experimental']
|
|
|
- if self.link_shared:
|
|
|
- self.cxx.link_flags += ['-lc++']
|
|
|
- else:
|
|
|
- cxx_library_root = self.get_lit_conf('cxx_library_root')
|
|
|
- if cxx_library_root:
|
|
|
- libname = self.make_static_lib_name('c++')
|
|
|
- abs_path = os.path.join(cxx_library_root, libname)
|
|
|
- assert os.path.exists(abs_path) and \
|
|
|
- "static libc++ library does not exist"
|
|
|
- self.cxx.link_flags += [abs_path]
|
|
|
- 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':
|
|
|
- if self.target_info.allow_cxxabi_link():
|
|
|
- libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True)
|
|
|
- if libcxxabi_shared:
|
|
|
- self.cxx.link_flags += ['-lc++abi']
|
|
|
- else:
|
|
|
- cxxabi_library_root = self.get_lit_conf('abi_library_path')
|
|
|
- if cxxabi_library_root:
|
|
|
- libname = self.make_static_lib_name('c++abi')
|
|
|
- abs_path = os.path.join(cxxabi_library_root, libname)
|
|
|
- self.cxx.link_flags += [abs_path]
|
|
|
- else:
|
|
|
- self.cxx.link_flags += ['-lc++abi']
|
|
|
- elif cxx_abi == 'libcxxrt':
|
|
|
- self.cxx.link_flags += ['-lcxxrt']
|
|
|
- elif cxx_abi == 'vcruntime':
|
|
|
- debug_suffix = 'd' if self.debug_build else ''
|
|
|
- self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in
|
|
|
- ['vcruntime', 'ucrt', 'msvcrt']]
|
|
|
- elif cxx_abi == 'none' or cxx_abi == 'default':
|
|
|
- if self.is_windows:
|
|
|
- debug_suffix = 'd' if self.debug_build else ''
|
|
|
- self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
|
|
|
- else:
|
|
|
- self.lit_config.fatal(
|
|
|
- 'C++ ABI setting %s unsupported for tests' % cxx_abi)
|
|
|
-
|
|
|
- def configure_extra_library_flags(self):
|
|
|
- if self.get_lit_bool('cxx_ext_threads', default=False):
|
|
|
- self.cxx.link_flags += ['-lc++external_threads']
|
|
|
- self.target_info.add_cxx_link_flags(self.cxx.link_flags)
|
|
|
-
|
|
|
- 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):
|
|
|
- # Turn on warnings by default for Clang based compilers when C++ >= 11
|
|
|
- default_enable_warnings = self.cxx.type in ['clang', 'apple-clang'] \
|
|
|
- and len(self.config.available_features.intersection(
|
|
|
- ['c++11', 'c++14', 'c++1z'])) != 0
|
|
|
- enable_warnings = self.get_lit_bool('enable_warnings',
|
|
|
- default_enable_warnings)
|
|
|
- self.cxx.useWarnings(enable_warnings)
|
|
|
- self.cxx.warning_flags += [
|
|
|
- '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER',
|
|
|
- '-Wall', '-Wextra', '-Werror'
|
|
|
- ]
|
|
|
- if self.cxx.hasWarningFlag('-Wuser-defined-warnings'):
|
|
|
- self.cxx.warning_flags += ['-Wuser-defined-warnings']
|
|
|
- self.config.available_features.add('diagnose-if-support')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wshadow')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wno-unused-command-line-argument')
|
|
|
- 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')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type')
|
|
|
- # These warnings should be enabled in order to support the MSVC
|
|
|
- # team using the test suite; They enable the warnings below and
|
|
|
- # expect the test suite to be clean.
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wsign-compare')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wunused-variable')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wunused-parameter')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wunreachable-code')
|
|
|
- # FIXME: Enable the two warnings below.
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wno-conversion')
|
|
|
- self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
|
|
|
- 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', '')
|
|
|
- cxx_path = libcxx.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 = libcxx.util.which('llvm-symbolizer',
|
|
|
- symbolizer_search_paths)
|
|
|
-
|
|
|
- def add_ubsan():
|
|
|
- self.cxx.flags += ['-fsanitize=undefined',
|
|
|
- '-fno-sanitize=vptr,function,float-divide-by-zero',
|
|
|
- '-fno-sanitize-recover=all']
|
|
|
- self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
|
|
|
- self.config.available_features.add('ubsan')
|
|
|
-
|
|
|
- # Setup the sanitizer compile flags
|
|
|
- self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
|
|
|
- if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address':
|
|
|
- self.cxx.flags += ['-fsanitize=address']
|
|
|
- if llvm_symbolizer is not None:
|
|
|
- self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
|
|
- # FIXME: Turn ODR violation back on after PR28391 is resolved
|
|
|
- # https://bugs.llvm.org/show_bug.cgi?id=28391
|
|
|
- self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
|
|
|
- self.config.available_features.add('asan')
|
|
|
- self.config.available_features.add('sanitizer-new-delete')
|
|
|
- self.cxx.compile_flags += ['-O1']
|
|
|
- if san == 'Address;Undefined' or san == 'Undefined;Address':
|
|
|
- add_ubsan()
|
|
|
- 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.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
|
|
- self.config.available_features.add('msan')
|
|
|
- self.config.available_features.add('sanitizer-new-delete')
|
|
|
- self.cxx.compile_flags += ['-O1']
|
|
|
- elif san == 'Undefined':
|
|
|
- add_ubsan()
|
|
|
- self.cxx.compile_flags += ['-O2']
|
|
|
- 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))
|
|
|
- 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)
|
|
|
- if self.generate_coverage:
|
|
|
- self.cxx.flags += ['-g', '--coverage']
|
|
|
- self.cxx.compile_flags += ['-O0']
|
|
|
-
|
|
|
- def configure_modules(self):
|
|
|
- modules_flags = ['-fmodules']
|
|
|
- if platform.system() != 'Darwin':
|
|
|
- modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility']
|
|
|
- supports_modules = self.cxx.hasCompileFlag(modules_flags)
|
|
|
- enable_modules = self.get_lit_bool('enable_modules',
|
|
|
- default=False,
|
|
|
- env_var='LIBCXX_ENABLE_MODULES')
|
|
|
- if enable_modules and not supports_modules:
|
|
|
- self.lit_config.fatal(
|
|
|
- '-fmodules is enabled but not supported by the compiler')
|
|
|
- if not supports_modules:
|
|
|
- return
|
|
|
- self.config.available_features.add('modules-support')
|
|
|
- module_cache = os.path.join(self.config.test_exec_root,
|
|
|
- 'modules.cache')
|
|
|
- module_cache = os.path.realpath(module_cache)
|
|
|
- if os.path.isdir(module_cache):
|
|
|
- shutil.rmtree(module_cache)
|
|
|
- os.makedirs(module_cache)
|
|
|
- self.cxx.modules_flags = modules_flags + \
|
|
|
- ['-fmodules-cache-path=' + module_cache]
|
|
|
- if enable_modules:
|
|
|
- self.config.available_features.add('-fmodules')
|
|
|
- self.cxx.useModules()
|
|
|
-
|
|
|
- def configure_substitutions(self):
|
|
|
- sub = self.config.substitutions
|
|
|
- cxx_path = pipes.quote(self.cxx.path)
|
|
|
- # Configure compiler substitutions
|
|
|
- sub.append(('%cxx', cxx_path))
|
|
|
- # Configure flags substitutions
|
|
|
- flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags])
|
|
|
- compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags])
|
|
|
- link_flags_str = ' '.join([pipes.quote(f) for f in 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))
|
|
|
- if self.cxx.isVerifySupported():
|
|
|
- verify_str = ' ' + ' '.join(self.cxx.verify_flags) + ' '
|
|
|
- sub.append(('%verify', verify_str))
|
|
|
- # Add compile and link shortcuts
|
|
|
- compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str
|
|
|
- + ' ' + compile_flags_str)
|
|
|
- link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' '
|
|
|
- + link_flags_str)
|
|
|
- assert type(link_str) is str
|
|
|
- build_str = cxx_path + ' -o %t.exe %s ' + all_flags
|
|
|
- if self.cxx.use_modules:
|
|
|
- sub.append(('%compile_module', compile_str))
|
|
|
- sub.append(('%build_module', build_str))
|
|
|
- elif self.cxx.modules_flags is not None:
|
|
|
- modules_str = ' '.join(self.cxx.modules_flags) + ' '
|
|
|
- sub.append(('%compile_module', compile_str + ' ' + modules_str))
|
|
|
- sub.append(('%build_module', build_str + ' ' + modules_str))
|
|
|
- sub.append(('%compile', compile_str))
|
|
|
- sub.append(('%link', link_str))
|
|
|
- sub.append(('%build', build_str))
|
|
|
- # Configure exec prefix substitutions.
|
|
|
- exec_env_str = ''
|
|
|
- if not self.is_windows and len(self.exec_env) != 0:
|
|
|
- exec_env_str = 'env '
|
|
|
- for k, v in self.exec_env.items():
|
|
|
- exec_env_str += ' %s=%s' % (k, v)
|
|
|
- # Configure run env substitution.
|
|
|
- exec_str = exec_env_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 substitutions
|
|
|
- not_py = os.path.join(self.libcxx_src_root, 'utils', 'not.py')
|
|
|
- not_str = '%s %s ' % (pipes.quote(sys.executable), pipes.quote(not_py))
|
|
|
- sub.append(('not ', not_str))
|
|
|
-
|
|
|
- def can_use_deployment(self):
|
|
|
- # Check if the host is on an Apple platform using clang.
|
|
|
- if not self.target_info.platform() == "darwin":
|
|
|
- return False
|
|
|
- if not self.target_info.is_host_macosx():
|
|
|
- return False
|
|
|
- if not self.cxx.type.endswith('clang'):
|
|
|
- return False
|
|
|
- return True
|
|
|
-
|
|
|
- def configure_triple(self):
|
|
|
- # Get or infer the target triple.
|
|
|
- target_triple = self.get_lit_conf('target_triple')
|
|
|
- self.use_target = self.get_lit_bool('use_target', False)
|
|
|
- if self.use_target and target_triple:
|
|
|
- self.lit_config.warning('use_target is true but no triple is specified')
|
|
|
-
|
|
|
- # Use deployment if possible.
|
|
|
- self.use_deployment = not self.use_target and self.can_use_deployment()
|
|
|
- if self.use_deployment:
|
|
|
- return
|
|
|
-
|
|
|
- # Save the triple (and warn on Apple platforms).
|
|
|
- self.config.target_triple = target_triple
|
|
|
- if self.use_target and 'apple' in target_triple:
|
|
|
- self.lit_config.warning('consider using arch and platform instead'
|
|
|
- ' of target_triple on Apple platforms')
|
|
|
-
|
|
|
- # If no target triple was given, try to infer it from the compiler
|
|
|
- # under test.
|
|
|
- if not self.config.target_triple:
|
|
|
- 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_deployment(self):
|
|
|
- assert not self.use_deployment is None
|
|
|
- assert not self.use_target is None
|
|
|
- if not self.use_deployment:
|
|
|
- # Warn about ignored parameters.
|
|
|
- if self.get_lit_conf('arch'):
|
|
|
- self.lit_config.warning('ignoring arch, using target_triple')
|
|
|
- if self.get_lit_conf('platform'):
|
|
|
- self.lit_config.warning('ignoring platform, using target_triple')
|
|
|
- return
|
|
|
-
|
|
|
- assert not self.use_target
|
|
|
- assert self.target_info.is_host_macosx()
|
|
|
-
|
|
|
- # Always specify deployment explicitly on Apple platforms, since
|
|
|
- # otherwise a platform is picked up from the SDK. If the SDK version
|
|
|
- # doesn't match the system version, tests that use the system library
|
|
|
- # may fail spuriously.
|
|
|
- arch = self.get_lit_conf('arch')
|
|
|
- if not arch:
|
|
|
- arch = self.cxx.getTriple().split('-', 1)[0]
|
|
|
- self.lit_config.note("inferred arch as: %r" % arch)
|
|
|
-
|
|
|
- inferred_platform, name, version = self.target_info.get_platform()
|
|
|
- if inferred_platform:
|
|
|
- self.lit_config.note("inferred platform as: %r" % (name + version))
|
|
|
- self.config.deployment = (arch, name, version)
|
|
|
-
|
|
|
- # Set the target triple for use by lit.
|
|
|
- self.config.target_triple = arch + '-apple-' + name + version
|
|
|
- self.lit_config.note(
|
|
|
- "computed target_triple as: %r" % self.config.target_triple)
|
|
|
-
|
|
|
- def configure_env(self):
|
|
|
- self.target_info.configure_env(self.exec_env)
|
|
|
-
|
|
|
- def add_path(self, dest_env, new_path):
|
|
|
- if 'PATH' not in dest_env:
|
|
|
- dest_env['PATH'] = new_path
|
|
|
- else:
|
|
|
- split_char = ';' if self.is_windows else ':'
|
|
|
- dest_env['PATH'] = '%s%s%s' % (new_path, split_char,
|
|
|
- dest_env['PATH'])
|
|
|
+#===----------------------------------------------------------------------===##
|
|
|
+#
|
|
|
+# The LLVM Compiler Infrastructure
|
|
|
+#
|
|
|
+# This file is dual licensed under the MIT and the University of Illinois Open
|
|
|
+# Source Licenses. See LICENSE.TXT for details.
|
|
|
+#
|
|
|
+#===----------------------------------------------------------------------===##
|
|
|
+
|
|
|
+import locale
|
|
|
+import os
|
|
|
+import platform
|
|
|
+import pkgutil
|
|
|
+import pipes
|
|
|
+import re
|
|
|
+import shlex
|
|
|
+import shutil
|
|
|
+import sys
|
|
|
+
|
|
|
+from libcxx.compiler import CXXCompiler
|
|
|
+from libcxx.test.target_info import make_target_info
|
|
|
+from libcxx.test.executor import *
|
|
|
+from libcxx.test.tracing import *
|
|
|
+import libcxx.util
|
|
|
+
|
|
|
+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.is_windows = platform.system() == 'Windows'
|
|
|
+ self.cxx = None
|
|
|
+ self.cxx_is_clang_cl = None
|
|
|
+ self.cxx_stdlib_under_test = None
|
|
|
+ self.project_obj_root = None
|
|
|
+ self.libcxx_src_root = None
|
|
|
+ self.libcxx_obj_root = None
|
|
|
+ self.cxx_library_root = None
|
|
|
+ self.cxx_runtime_root = None
|
|
|
+ self.abi_library_root = None
|
|
|
+ self.link_shared = self.get_lit_bool('enable_shared', default=True)
|
|
|
+ self.debug_build = self.get_lit_bool('debug_build', default=False)
|
|
|
+ self.exec_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, env_var=None):
|
|
|
+ def check_value(value, var_name):
|
|
|
+ if value is None:
|
|
|
+ return default
|
|
|
+ if isinstance(value, bool):
|
|
|
+ return value
|
|
|
+ if not isinstance(value, str):
|
|
|
+ raise TypeError('expected bool or string')
|
|
|
+ if value.lower() in ('1', 'true'):
|
|
|
+ return True
|
|
|
+ if value.lower() in ('', '0', 'false'):
|
|
|
+ return False
|
|
|
+ self.lit_config.fatal(
|
|
|
+ "parameter '{}' should be true or false".format(var_name))
|
|
|
+
|
|
|
+ conf_val = self.get_lit_conf(name)
|
|
|
+ if env_var is not None and env_var in os.environ and \
|
|
|
+ os.environ[env_var] is not None:
|
|
|
+ val = os.environ[env_var]
|
|
|
+ if conf_val is not None:
|
|
|
+ self.lit_config.warning(
|
|
|
+ 'Environment variable %s=%s is overriding explicit '
|
|
|
+ '--param=%s=%s' % (env_var, val, name, conf_val))
|
|
|
+ return check_value(val, env_var)
|
|
|
+ return check_value(conf_val, name)
|
|
|
+
|
|
|
+ def make_static_lib_name(self, name):
|
|
|
+ """Return the full filename for the specified library name"""
|
|
|
+ if self.is_windows:
|
|
|
+ assert name == 'c++' # Only allow libc++ to use this function for now.
|
|
|
+ return 'lib' + name + '.lib'
|
|
|
+ else:
|
|
|
+ return 'lib' + name + '.a'
|
|
|
+
|
|
|
+ def configure(self):
|
|
|
+ self.configure_executor()
|
|
|
+ self.configure_use_system_cxx_lib()
|
|
|
+ self.configure_target_info()
|
|
|
+ self.configure_cxx()
|
|
|
+ self.configure_triple()
|
|
|
+ self.configure_deployment()
|
|
|
+ self.configure_availability()
|
|
|
+ self.configure_src_root()
|
|
|
+ self.configure_obj_root()
|
|
|
+ self.configure_cxx_stdlib_under_test()
|
|
|
+ self.configure_cxx_library_root()
|
|
|
+ self.configure_use_clang_verify()
|
|
|
+ self.configure_use_thread_safety()
|
|
|
+ self.configure_execute_external()
|
|
|
+ self.configure_ccache()
|
|
|
+ self.configure_compile_flags()
|
|
|
+ self.configure_filesystem_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_modules()
|
|
|
+ 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)
|
|
|
+ if self.cxx.use_modules:
|
|
|
+ self.lit_config.note('Using modules flags: %s' %
|
|
|
+ self.cxx.modules_flags)
|
|
|
+ self.lit_config.note('Using compile flags: %s'
|
|
|
+ % self.cxx.compile_flags)
|
|
|
+ if len(self.cxx.warning_flags):
|
|
|
+ self.lit_config.note('Using warnings: %s' % self.cxx.warning_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.exec_env)
|
|
|
+ sys.stderr.flush() # Force flushing to avoid broken output on Windows
|
|
|
+
|
|
|
+ def get_test_format(self):
|
|
|
+ from libcxx.test.format import LibcxxTestFormat
|
|
|
+ return LibcxxTestFormat(
|
|
|
+ self.cxx,
|
|
|
+ self.use_clang_verify,
|
|
|
+ self.execute_external,
|
|
|
+ self.executor,
|
|
|
+ exec_env=self.exec_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):
|
|
|
+ self.target_info = make_target_info(self)
|
|
|
+
|
|
|
+ def configure_cxx(self):
|
|
|
+ # Gather various compiler parameters.
|
|
|
+ cxx = self.get_lit_conf('cxx_under_test')
|
|
|
+ self.cxx_is_clang_cl = cxx is not None and \
|
|
|
+ os.path.basename(cxx) == 'clang-cl.exe'
|
|
|
+ # If no specific cxx_under_test was given, attempt to infer it as
|
|
|
+ # clang++.
|
|
|
+ if cxx is None or self.cxx_is_clang_cl:
|
|
|
+ search_paths = self.config.environment['PATH']
|
|
|
+ if cxx is not None and os.path.isabs(cxx):
|
|
|
+ search_paths = os.path.dirname(cxx)
|
|
|
+ clangxx = libcxx.util.which('clang++', search_paths)
|
|
|
+ if clangxx:
|
|
|
+ cxx = clangxx
|
|
|
+ self.lit_config.note(
|
|
|
+ "inferred cxx_under_test as: %r" % cxx)
|
|
|
+ elif self.cxx_is_clang_cl:
|
|
|
+ self.lit_config.fatal('Failed to find clang++ substitution for'
|
|
|
+ ' clang-cl')
|
|
|
+ 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) if not self.cxx_is_clang_cl else \
|
|
|
+ self._configure_clang_cl(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' % (cxx_type, maj_v))
|
|
|
+ self.config.available_features.add('%s-%s.%s' % (
|
|
|
+ cxx_type, maj_v, min_v))
|
|
|
+ self.cxx.compile_env = dict(os.environ)
|
|
|
+ # 'CCACHE_CPP2' prevents ccache from stripping comments while
|
|
|
+ # preprocessing. This is required to prevent stripping of '-verify'
|
|
|
+ # comments.
|
|
|
+ self.cxx.compile_env['CCACHE_CPP2'] = '1'
|
|
|
+
|
|
|
+ def _configure_clang_cl(self, clang_path):
|
|
|
+ def _split_env_var(var):
|
|
|
+ return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()]
|
|
|
+
|
|
|
+ def _prefixed_env_list(var, prefix):
|
|
|
+ from itertools import chain
|
|
|
+ return list(chain.from_iterable((prefix, path) for path in _split_env_var(var)))
|
|
|
+
|
|
|
+ assert self.cxx_is_clang_cl
|
|
|
+ flags = []
|
|
|
+ compile_flags = _prefixed_env_list('INCLUDE', '-isystem')
|
|
|
+ link_flags = _prefixed_env_list('LIB', '-L')
|
|
|
+ for path in _split_env_var('LIB'):
|
|
|
+ self.add_path(self.exec_env, path)
|
|
|
+ return CXXCompiler(clang_path, flags=flags,
|
|
|
+ compile_flags=compile_flags,
|
|
|
+ link_flags=link_flags)
|
|
|
+
|
|
|
+
|
|
|
+ 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.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',
|
|
|
+ self.libcxx_obj_root)
|
|
|
+ self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root',
|
|
|
+ self.cxx_library_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.
|
|
|
+ # Default to testing against the locally built libc++ library.
|
|
|
+ self.use_system_cxx_lib = self.get_lit_conf('use_system_cxx_lib')
|
|
|
+ if self.use_system_cxx_lib == 'true':
|
|
|
+ self.use_system_cxx_lib = True
|
|
|
+ elif self.use_system_cxx_lib == 'false':
|
|
|
+ self.use_system_cxx_lib = False
|
|
|
+ elif self.use_system_cxx_lib:
|
|
|
+ assert os.path.isdir(self.use_system_cxx_lib)
|
|
|
+ self.lit_config.note(
|
|
|
+ "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
|
|
|
+
|
|
|
+ def configure_availability(self):
|
|
|
+ # See http://llvm.org/docs/AvailabilityMarkup.html
|
|
|
+ self.with_availability = self.get_lit_bool('with_availability', False)
|
|
|
+ self.lit_config.note(
|
|
|
+ "inferred with_availability as: %r" % self.with_availability)
|
|
|
+
|
|
|
+ def configure_cxx_stdlib_under_test(self):
|
|
|
+ self.cxx_stdlib_under_test = self.get_lit_conf(
|
|
|
+ 'cxx_stdlib_under_test', 'libc++')
|
|
|
+ if self.cxx_stdlib_under_test not in \
|
|
|
+ ['libc++', 'libstdc++', 'msvc', 'cxx_default']:
|
|
|
+ self.lit_config.fatal(
|
|
|
+ 'unsupported value for "cxx_stdlib_under_test": %s'
|
|
|
+ % self.cxx_stdlib_under_test)
|
|
|
+ self.config.available_features.add(self.cxx_stdlib_under_test)
|
|
|
+ if self.cxx_stdlib_under_test == 'libstdc++':
|
|
|
+ self.config.available_features.add('libstdc++')
|
|
|
+ # Manually enable the experimental and filesystem tests for libstdc++
|
|
|
+ # if the options aren't present.
|
|
|
+ # FIXME this is a hack.
|
|
|
+ if self.get_lit_conf('enable_experimental') is None:
|
|
|
+ self.config.enable_experimental = 'true'
|
|
|
+ if self.get_lit_conf('enable_filesystem') is None:
|
|
|
+ self.config.enable_filesystem = 'true'
|
|
|
+
|
|
|
+ def configure_use_clang_verify(self):
|
|
|
+ '''If set, run clang with -verify on failing tests.'''
|
|
|
+ if self.with_availability:
|
|
|
+ self.use_clang_verify = False
|
|
|
+ return
|
|
|
+ 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.isVerifySupported()
|
|
|
+ self.lit_config.note(
|
|
|
+ "inferred use_clang_verify as: %r" % self.use_clang_verify)
|
|
|
+ if self.use_clang_verify:
|
|
|
+ self.config.available_features.add('verify-support')
|
|
|
+
|
|
|
+ def configure_use_thread_safety(self):
|
|
|
+ '''If set, run clang with -verify on failing tests.'''
|
|
|
+ has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
|
|
|
+ if has_thread_safety:
|
|
|
+ self.cxx.compile_flags += ['-Werror=thread-safety']
|
|
|
+ self.config.available_features.add('thread-safety')
|
|
|
+ self.lit_config.note("enabling thread-safety annotations")
|
|
|
+
|
|
|
+ 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 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 = 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',
|
|
|
+ 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 add_deployment_feature(self, feature):
|
|
|
+ (arch, name, version) = self.config.deployment
|
|
|
+ self.config.available_features.add('%s=%s-%s' % (feature, arch, name))
|
|
|
+ self.config.available_features.add('%s=%s' % (feature, name))
|
|
|
+ self.config.available_features.add('%s=%s%s' % (feature, name, version))
|
|
|
+
|
|
|
+ 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())
|
|
|
+ self.target_info.add_locale_features(self.config.available_features)
|
|
|
+
|
|
|
+ target_platform = self.target_info.platform()
|
|
|
+
|
|
|
+ # 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')
|
|
|
+ self.config.available_features.add(
|
|
|
+ 'with_system_cxx_lib=%s' % self.config.target_triple)
|
|
|
+
|
|
|
+ # Add subcomponents individually.
|
|
|
+ target_components = self.config.target_triple.split('-')
|
|
|
+ for component in target_components:
|
|
|
+ self.config.available_features.add(
|
|
|
+ 'with_system_cxx_lib=%s' % component)
|
|
|
+
|
|
|
+ # Add available features for more generic versions of the target
|
|
|
+ # triple attached to with_system_cxx_lib.
|
|
|
+ if self.use_deployment:
|
|
|
+ self.add_deployment_feature('with_system_cxx_lib')
|
|
|
+
|
|
|
+ # Configure the availability markup checks features.
|
|
|
+ if self.with_availability:
|
|
|
+ self.config.available_features.add('availability_markup')
|
|
|
+ self.add_deployment_feature('availability_markup')
|
|
|
+
|
|
|
+ if self.use_system_cxx_lib or self.with_availability:
|
|
|
+ self.config.available_features.add('availability')
|
|
|
+ self.add_deployment_feature('availability')
|
|
|
+
|
|
|
+ if platform.system() == 'Darwin':
|
|
|
+ self.config.available_features.add('apple-darwin')
|
|
|
+
|
|
|
+ # Insert the platform name into the available features as a lower case.
|
|
|
+ self.config.available_features.add(target_platform)
|
|
|
+
|
|
|
+ # 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')
|
|
|
+
|
|
|
+ if self.cxx.hasCompileFlag('-faligned-allocation'):
|
|
|
+ self.config.available_features.add('-faligned-allocation')
|
|
|
+ else:
|
|
|
+ # FIXME remove this once more than just clang-4.0 support
|
|
|
+ # C++17 aligned allocation.
|
|
|
+ self.config.available_features.add('no-aligned-allocation')
|
|
|
+
|
|
|
+ if self.get_lit_bool('has_libatomic', False):
|
|
|
+ self.config.available_features.add('libatomic')
|
|
|
+
|
|
|
+ macros = self.cxx.dumpMacros()
|
|
|
+ if '__cpp_if_constexpr' not in macros:
|
|
|
+ self.config.available_features.add('libcpp-no-if-constexpr')
|
|
|
+
|
|
|
+ if '__cpp_structured_bindings' not in macros:
|
|
|
+ self.config.available_features.add('libcpp-no-structured-bindings')
|
|
|
+
|
|
|
+ if '__cpp_deduction_guides' not in macros:
|
|
|
+ self.config.available_features.add('libcpp-no-deduction-guides')
|
|
|
+
|
|
|
+ if self.is_windows:
|
|
|
+ self.config.available_features.add('windows')
|
|
|
+ if self.cxx_stdlib_under_test == 'libc++':
|
|
|
+ # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
|
|
|
+ # initial Windows failures until they can be properly diagnosed
|
|
|
+ # and fixed. This allows easier detection of new test failures
|
|
|
+ # and regressions. Note: New failures should not be suppressed
|
|
|
+ # using this feature. (Also see llvm.org/PR32730)
|
|
|
+ self.config.available_features.add('LIBCXX-WINDOWS-FIXME')
|
|
|
+
|
|
|
+ # Attempt to detect the glibc version by querying for __GLIBC__
|
|
|
+ # in 'features.h'.
|
|
|
+ macros = self.cxx.dumpMacros(flags=['-include', 'features.h'])
|
|
|
+ if macros is not None and '__GLIBC__' in macros:
|
|
|
+ maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__'])
|
|
|
+ self.config.available_features.add('glibc')
|
|
|
+ self.config.available_features.add('glibc-%s' % maj_v)
|
|
|
+ self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v))
|
|
|
+
|
|
|
+ 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()
|
|
|
+ # This include is always needed so add so add it regardless of
|
|
|
+ # 'no_default_flags'.
|
|
|
+ support_path = os.path.join(self.libcxx_src_root, 'test/support')
|
|
|
+ self.cxx.compile_flags += ['-I' + support_path]
|
|
|
+ # Configure extra flags
|
|
|
+ compile_flags_str = self.get_lit_conf('compile_flags', '')
|
|
|
+ self.cxx.compile_flags += shlex.split(compile_flags_str)
|
|
|
+ # FIXME: Can we remove this?
|
|
|
+ if self.is_windows:
|
|
|
+ self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS']
|
|
|
+
|
|
|
+ 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')
|
|
|
+ if not std:
|
|
|
+ # Choose the newest possible language dialect if none is given.
|
|
|
+ possible_stds = ['c++1z', 'c++14', 'c++11', 'c++03']
|
|
|
+ if self.cxx.type == 'gcc':
|
|
|
+ maj_v, _, _ = self.cxx.version
|
|
|
+ maj_v = int(maj_v)
|
|
|
+ if maj_v < 7:
|
|
|
+ possible_stds.remove('c++1z')
|
|
|
+ # FIXME: How many C++14 tests actually fail under GCC 5 and 6?
|
|
|
+ # Should we XFAIL them individually instead?
|
|
|
+ if maj_v <= 6:
|
|
|
+ possible_stds.remove('c++14')
|
|
|
+ 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.replace('gnu++', 'c++'))
|
|
|
+ # Configure include paths
|
|
|
+ self.configure_compile_flags_header_includes()
|
|
|
+ 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_abi_version()
|
|
|
+ enable_32bit = self.get_lit_bool('enable_32bit', False)
|
|
|
+ if enable_32bit:
|
|
|
+ self.cxx.flags += ['-m32']
|
|
|
+ # 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]
|
|
|
+ # NOTE: the _DEBUG definition must preceed the triple check because for
|
|
|
+ # the Windows build of libc++, the forced inclusion of a header requires
|
|
|
+ # that _DEBUG is defined. Incorrect ordering will result in -target
|
|
|
+ # being elided.
|
|
|
+ if self.is_windows and self.debug_build:
|
|
|
+ self.cxx.compile_flags += ['-D_DEBUG']
|
|
|
+ if self.use_target:
|
|
|
+ if not self.cxx.addFlagIfSupported(
|
|
|
+ ['-target', self.config.target_triple]):
|
|
|
+ self.lit_config.warning('use_target is true but -target is '\
|
|
|
+ 'not supported by the compiler')
|
|
|
+ if self.use_deployment:
|
|
|
+ arch, name, version = self.config.deployment
|
|
|
+ self.cxx.flags += ['-arch', arch]
|
|
|
+ self.cxx.flags += ['-m' + name + '-version-min=' + version]
|
|
|
+
|
|
|
+ # Disable availability unless explicitely requested
|
|
|
+ if not self.with_availability:
|
|
|
+ self.cxx.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY']
|
|
|
+
|
|
|
+ def configure_compile_flags_header_includes(self):
|
|
|
+ support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
|
|
|
+ if self.cxx_stdlib_under_test != 'libstdc++' and \
|
|
|
+ not self.is_windows:
|
|
|
+ self.cxx.compile_flags += [
|
|
|
+ '-include', os.path.join(support_path, 'nasty_macros.hpp')]
|
|
|
+ if self.cxx_stdlib_under_test == 'msvc':
|
|
|
+ self.cxx.compile_flags += [
|
|
|
+ '-include', os.path.join(support_path,
|
|
|
+ 'msvc_stdlib_force_include.hpp')]
|
|
|
+ pass
|
|
|
+ if self.is_windows and self.debug_build and \
|
|
|
+ self.cxx_stdlib_under_test != 'msvc':
|
|
|
+ self.cxx.compile_flags += [
|
|
|
+ '-include', os.path.join(support_path,
|
|
|
+ 'set_windows_crt_report_mode.h')
|
|
|
+ ]
|
|
|
+ self.configure_config_site_header()
|
|
|
+ cxx_headers = self.get_lit_conf('cxx_headers')
|
|
|
+ if cxx_headers == '' or (cxx_headers is None
|
|
|
+ and self.cxx_stdlib_under_test != 'libc++'):
|
|
|
+ self.lit_config.note('using the system cxx headers')
|
|
|
+ return
|
|
|
+ self.cxx.compile_flags += ['-nostdinc++']
|
|
|
+ if cxx_headers is None:
|
|
|
+ cxx_headers = os.path.join(self.libcxx_src_root, 'include')
|
|
|
+ if not os.path.isdir(cxx_headers):
|
|
|
+ self.lit_config.fatal("cxx_headers='%s' is not a directory."
|
|
|
+ % cxx_headers)
|
|
|
+ self.cxx.compile_flags += ['-I' + cxx_headers]
|
|
|
+ if self.libcxx_obj_root is not None:
|
|
|
+ cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include',
|
|
|
+ 'c++build')
|
|
|
+ if os.path.isdir(cxxabi_headers):
|
|
|
+ self.cxx.compile_flags += ['-I' + cxxabi_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_DISABLE_VISIBILITY_ANNOTATIONS':
|
|
|
+ continue
|
|
|
+ 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:
|
|
|
+ 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_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_filesystem_compile_flags(self):
|
|
|
+ enable_fs = self.get_lit_bool('enable_filesystem', default=False)
|
|
|
+ if not enable_fs:
|
|
|
+ return
|
|
|
+ enable_experimental = self.get_lit_bool('enable_experimental', default=False)
|
|
|
+ if not enable_experimental:
|
|
|
+ self.lit_config.fatal(
|
|
|
+ 'filesystem is enabled but libc++experimental.a is not.')
|
|
|
+ self.config.available_features.add('c++filesystem')
|
|
|
+ static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
|
|
|
+ 'experimental', 'filesystem', 'Inputs', 'static_test_env')
|
|
|
+ static_env = os.path.realpath(static_env)
|
|
|
+ assert os.path.isdir(static_env)
|
|
|
+ self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env]
|
|
|
+
|
|
|
+ dynamic_env = os.path.join(self.config.test_exec_root,
|
|
|
+ 'filesystem', 'Output', 'dynamic_env')
|
|
|
+ dynamic_env = os.path.realpath(dynamic_env)
|
|
|
+ if not os.path.isdir(dynamic_env):
|
|
|
+ os.makedirs(dynamic_env)
|
|
|
+ self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env]
|
|
|
+ self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
|
|
|
+
|
|
|
+ dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
|
|
|
+ 'filesystem_dynamic_test_helper.py')
|
|
|
+ assert os.path.isfile(dynamic_helper)
|
|
|
+
|
|
|
+ self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"'
|
|
|
+ % (sys.executable, dynamic_helper)]
|
|
|
+
|
|
|
+
|
|
|
+ def configure_link_flags(self):
|
|
|
+ no_default_flags = self.get_lit_bool('no_default_flags', False)
|
|
|
+ if not no_default_flags:
|
|
|
+ # Configure library path
|
|
|
+ self.configure_link_flags_cxx_library_path()
|
|
|
+ self.configure_link_flags_abi_library_path()
|
|
|
+
|
|
|
+ # Configure libraries
|
|
|
+ if self.cxx_stdlib_under_test == 'libc++':
|
|
|
+ self.cxx.link_flags += ['-nodefaultlibs']
|
|
|
+ # FIXME: Handle MSVCRT as part of the ABI library handling.
|
|
|
+ if self.is_windows:
|
|
|
+ self.cxx.link_flags += ['-nostdlib']
|
|
|
+ self.configure_link_flags_cxx_library()
|
|
|
+ self.configure_link_flags_abi_library()
|
|
|
+ self.configure_extra_library_flags()
|
|
|
+ elif self.cxx_stdlib_under_test == 'libstdc++':
|
|
|
+ enable_fs = self.get_lit_bool('enable_filesystem',
|
|
|
+ default=False)
|
|
|
+ if enable_fs:
|
|
|
+ self.config.available_features.add('c++experimental')
|
|
|
+ self.cxx.link_flags += ['-lstdc++fs']
|
|
|
+ self.cxx.link_flags += ['-lm', '-pthread']
|
|
|
+ elif self.cxx_stdlib_under_test == 'msvc':
|
|
|
+ # FIXME: Correctly setup debug/release flags here.
|
|
|
+ pass
|
|
|
+ elif self.cxx_stdlib_under_test == 'cxx_default':
|
|
|
+ self.cxx.link_flags += ['-pthread']
|
|
|
+ else:
|
|
|
+ self.lit_config.fatal(
|
|
|
+ 'unsupported value for "use_stdlib_type": %s'
|
|
|
+ % use_stdlib_type)
|
|
|
+
|
|
|
+ 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):
|
|
|
+ if not self.use_system_cxx_lib:
|
|
|
+ if self.cxx_library_root:
|
|
|
+ self.cxx.link_flags += ['-L' + self.cxx_library_root]
|
|
|
+ if self.is_windows and self.link_shared:
|
|
|
+ self.add_path(self.cxx.compile_env, self.cxx_library_root)
|
|
|
+ if self.cxx_runtime_root:
|
|
|
+ if not self.is_windows:
|
|
|
+ self.cxx.link_flags += ['-Wl,-rpath,' +
|
|
|
+ self.cxx_runtime_root]
|
|
|
+ elif self.is_windows and self.link_shared:
|
|
|
+ self.add_path(self.exec_env, self.cxx_runtime_root)
|
|
|
+ elif os.path.isdir(str(self.use_system_cxx_lib)):
|
|
|
+ self.cxx.link_flags += ['-L' + self.use_system_cxx_lib]
|
|
|
+ if not self.is_windows:
|
|
|
+ self.cxx.link_flags += ['-Wl,-rpath,' +
|
|
|
+ self.use_system_cxx_lib]
|
|
|
+ if self.is_windows and self.link_shared:
|
|
|
+ self.add_path(self.cxx.compile_env, self.use_system_cxx_lib)
|
|
|
+
|
|
|
+ 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]
|
|
|
+ if not self.is_windows:
|
|
|
+ self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root]
|
|
|
+ else:
|
|
|
+ self.add_path(self.exec_env, self.abi_library_root)
|
|
|
+
|
|
|
+ def configure_link_flags_cxx_library(self):
|
|
|
+ libcxx_experimental = self.get_lit_bool('enable_experimental', default=False)
|
|
|
+ if libcxx_experimental:
|
|
|
+ self.config.available_features.add('c++experimental')
|
|
|
+ self.cxx.link_flags += ['-lc++experimental']
|
|
|
+ if self.link_shared:
|
|
|
+ self.cxx.link_flags += ['-lc++']
|
|
|
+ else:
|
|
|
+ cxx_library_root = self.get_lit_conf('cxx_library_root')
|
|
|
+ if cxx_library_root:
|
|
|
+ libname = self.make_static_lib_name('c++')
|
|
|
+ abs_path = os.path.join(cxx_library_root, libname)
|
|
|
+ assert os.path.exists(abs_path) and \
|
|
|
+ "static libc++ library does not exist"
|
|
|
+ self.cxx.link_flags += [abs_path]
|
|
|
+ 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':
|
|
|
+ if self.target_info.allow_cxxabi_link():
|
|
|
+ libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True)
|
|
|
+ if libcxxabi_shared:
|
|
|
+ self.cxx.link_flags += ['-lc++abi']
|
|
|
+ else:
|
|
|
+ cxxabi_library_root = self.get_lit_conf('abi_library_path')
|
|
|
+ if cxxabi_library_root:
|
|
|
+ libname = self.make_static_lib_name('c++abi')
|
|
|
+ abs_path = os.path.join(cxxabi_library_root, libname)
|
|
|
+ self.cxx.link_flags += [abs_path]
|
|
|
+ else:
|
|
|
+ self.cxx.link_flags += ['-lc++abi']
|
|
|
+ elif cxx_abi == 'libcxxrt':
|
|
|
+ self.cxx.link_flags += ['-lcxxrt']
|
|
|
+ elif cxx_abi == 'vcruntime':
|
|
|
+ debug_suffix = 'd' if self.debug_build else ''
|
|
|
+ self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in
|
|
|
+ ['vcruntime', 'ucrt', 'msvcrt']]
|
|
|
+ elif cxx_abi == 'none' or cxx_abi == 'default':
|
|
|
+ if self.is_windows:
|
|
|
+ debug_suffix = 'd' if self.debug_build else ''
|
|
|
+ self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
|
|
|
+ else:
|
|
|
+ self.lit_config.fatal(
|
|
|
+ 'C++ ABI setting %s unsupported for tests' % cxx_abi)
|
|
|
+
|
|
|
+ def configure_extra_library_flags(self):
|
|
|
+ if self.get_lit_bool('cxx_ext_threads', default=False):
|
|
|
+ self.cxx.link_flags += ['-lc++external_threads']
|
|
|
+ self.target_info.add_cxx_link_flags(self.cxx.link_flags)
|
|
|
+
|
|
|
+ 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):
|
|
|
+ # Turn on warnings by default for Clang based compilers when C++ >= 11
|
|
|
+ default_enable_warnings = self.cxx.type in ['clang', 'apple-clang'] \
|
|
|
+ and len(self.config.available_features.intersection(
|
|
|
+ ['c++11', 'c++14', 'c++1z'])) != 0
|
|
|
+ enable_warnings = self.get_lit_bool('enable_warnings',
|
|
|
+ default_enable_warnings)
|
|
|
+ self.cxx.useWarnings(enable_warnings)
|
|
|
+ self.cxx.warning_flags += [
|
|
|
+ '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER',
|
|
|
+ '-Wall', '-Wextra', '-Werror'
|
|
|
+ ]
|
|
|
+ if self.cxx.hasWarningFlag('-Wuser-defined-warnings'):
|
|
|
+ self.cxx.warning_flags += ['-Wuser-defined-warnings']
|
|
|
+ self.config.available_features.add('diagnose-if-support')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wshadow')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wno-unused-command-line-argument')
|
|
|
+ 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')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type')
|
|
|
+ # These warnings should be enabled in order to support the MSVC
|
|
|
+ # team using the test suite; They enable the warnings below and
|
|
|
+ # expect the test suite to be clean.
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wsign-compare')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wunused-variable')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wunused-parameter')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wunreachable-code')
|
|
|
+ # FIXME: Enable the two warnings below.
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wno-conversion')
|
|
|
+ self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
|
|
|
+ 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', '')
|
|
|
+ cxx_path = libcxx.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 = libcxx.util.which('llvm-symbolizer',
|
|
|
+ symbolizer_search_paths)
|
|
|
+
|
|
|
+ def add_ubsan():
|
|
|
+ self.cxx.flags += ['-fsanitize=undefined',
|
|
|
+ '-fno-sanitize=vptr,function,float-divide-by-zero',
|
|
|
+ '-fno-sanitize-recover=all']
|
|
|
+ self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
|
|
|
+ self.config.available_features.add('ubsan')
|
|
|
+
|
|
|
+ # Setup the sanitizer compile flags
|
|
|
+ self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
|
|
|
+ if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address':
|
|
|
+ self.cxx.flags += ['-fsanitize=address']
|
|
|
+ if llvm_symbolizer is not None:
|
|
|
+ self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
|
|
+ # FIXME: Turn ODR violation back on after PR28391 is resolved
|
|
|
+ # https://bugs.llvm.org/show_bug.cgi?id=28391
|
|
|
+ self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
|
|
|
+ self.config.available_features.add('asan')
|
|
|
+ self.config.available_features.add('sanitizer-new-delete')
|
|
|
+ self.cxx.compile_flags += ['-O1']
|
|
|
+ if san == 'Address;Undefined' or san == 'Undefined;Address':
|
|
|
+ add_ubsan()
|
|
|
+ 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.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
|
|
+ self.config.available_features.add('msan')
|
|
|
+ self.config.available_features.add('sanitizer-new-delete')
|
|
|
+ self.cxx.compile_flags += ['-O1']
|
|
|
+ elif san == 'Undefined':
|
|
|
+ add_ubsan()
|
|
|
+ self.cxx.compile_flags += ['-O2']
|
|
|
+ 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))
|
|
|
+ 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)
|
|
|
+ if self.generate_coverage:
|
|
|
+ self.cxx.flags += ['-g', '--coverage']
|
|
|
+ self.cxx.compile_flags += ['-O0']
|
|
|
+
|
|
|
+ def configure_modules(self):
|
|
|
+ modules_flags = ['-fmodules']
|
|
|
+ if platform.system() != 'Darwin':
|
|
|
+ modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility']
|
|
|
+ supports_modules = self.cxx.hasCompileFlag(modules_flags)
|
|
|
+ enable_modules = self.get_lit_bool('enable_modules',
|
|
|
+ default=False,
|
|
|
+ env_var='LIBCXX_ENABLE_MODULES')
|
|
|
+ if enable_modules and not supports_modules:
|
|
|
+ self.lit_config.fatal(
|
|
|
+ '-fmodules is enabled but not supported by the compiler')
|
|
|
+ if not supports_modules:
|
|
|
+ return
|
|
|
+ self.config.available_features.add('modules-support')
|
|
|
+ module_cache = os.path.join(self.config.test_exec_root,
|
|
|
+ 'modules.cache')
|
|
|
+ module_cache = os.path.realpath(module_cache)
|
|
|
+ if os.path.isdir(module_cache):
|
|
|
+ shutil.rmtree(module_cache)
|
|
|
+ os.makedirs(module_cache)
|
|
|
+ self.cxx.modules_flags = modules_flags + \
|
|
|
+ ['-fmodules-cache-path=' + module_cache]
|
|
|
+ if enable_modules:
|
|
|
+ self.config.available_features.add('-fmodules')
|
|
|
+ self.cxx.useModules()
|
|
|
+
|
|
|
+ def configure_substitutions(self):
|
|
|
+ sub = self.config.substitutions
|
|
|
+ cxx_path = pipes.quote(self.cxx.path)
|
|
|
+ # Configure compiler substitutions
|
|
|
+ sub.append(('%cxx', cxx_path))
|
|
|
+ # Configure flags substitutions
|
|
|
+ flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags])
|
|
|
+ compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags])
|
|
|
+ link_flags_str = ' '.join([pipes.quote(f) for f in 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))
|
|
|
+ if self.cxx.isVerifySupported():
|
|
|
+ verify_str = ' ' + ' '.join(self.cxx.verify_flags) + ' '
|
|
|
+ sub.append(('%verify', verify_str))
|
|
|
+ # Add compile and link shortcuts
|
|
|
+ compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str
|
|
|
+ + ' ' + compile_flags_str)
|
|
|
+ link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' '
|
|
|
+ + link_flags_str)
|
|
|
+ assert type(link_str) is str
|
|
|
+ build_str = cxx_path + ' -o %t.exe %s ' + all_flags
|
|
|
+ if self.cxx.use_modules:
|
|
|
+ sub.append(('%compile_module', compile_str))
|
|
|
+ sub.append(('%build_module', build_str))
|
|
|
+ elif self.cxx.modules_flags is not None:
|
|
|
+ modules_str = ' '.join(self.cxx.modules_flags) + ' '
|
|
|
+ sub.append(('%compile_module', compile_str + ' ' + modules_str))
|
|
|
+ sub.append(('%build_module', build_str + ' ' + modules_str))
|
|
|
+ sub.append(('%compile', compile_str))
|
|
|
+ sub.append(('%link', link_str))
|
|
|
+ sub.append(('%build', build_str))
|
|
|
+ # Configure exec prefix substitutions.
|
|
|
+ exec_env_str = ''
|
|
|
+ if not self.is_windows and len(self.exec_env) != 0:
|
|
|
+ exec_env_str = 'env '
|
|
|
+ for k, v in self.exec_env.items():
|
|
|
+ exec_env_str += ' %s=%s' % (k, v)
|
|
|
+ # Configure run env substitution.
|
|
|
+ exec_str = exec_env_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 substitutions
|
|
|
+ not_py = os.path.join(self.libcxx_src_root, 'utils', 'not.py')
|
|
|
+ not_str = '%s %s ' % (pipes.quote(sys.executable), pipes.quote(not_py))
|
|
|
+ sub.append(('not ', not_str))
|
|
|
+
|
|
|
+ def can_use_deployment(self):
|
|
|
+ # Check if the host is on an Apple platform using clang.
|
|
|
+ if not self.target_info.platform() == "darwin":
|
|
|
+ return False
|
|
|
+ if not self.target_info.is_host_macosx():
|
|
|
+ return False
|
|
|
+ if not self.cxx.type.endswith('clang'):
|
|
|
+ return False
|
|
|
+ return True
|
|
|
+
|
|
|
+ def configure_triple(self):
|
|
|
+ # Get or infer the target triple.
|
|
|
+ target_triple = self.get_lit_conf('target_triple')
|
|
|
+ self.use_target = self.get_lit_bool('use_target', False)
|
|
|
+ if self.use_target and target_triple:
|
|
|
+ self.lit_config.warning('use_target is true but no triple is specified')
|
|
|
+
|
|
|
+ # Use deployment if possible.
|
|
|
+ self.use_deployment = not self.use_target and self.can_use_deployment()
|
|
|
+ if self.use_deployment:
|
|
|
+ return
|
|
|
+
|
|
|
+ # Save the triple (and warn on Apple platforms).
|
|
|
+ self.config.target_triple = target_triple
|
|
|
+ if self.use_target and 'apple' in target_triple:
|
|
|
+ self.lit_config.warning('consider using arch and platform instead'
|
|
|
+ ' of target_triple on Apple platforms')
|
|
|
+
|
|
|
+ # If no target triple was given, try to infer it from the compiler
|
|
|
+ # under test.
|
|
|
+ if not self.config.target_triple:
|
|
|
+ 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_deployment(self):
|
|
|
+ assert not self.use_deployment is None
|
|
|
+ assert not self.use_target is None
|
|
|
+ if not self.use_deployment:
|
|
|
+ # Warn about ignored parameters.
|
|
|
+ if self.get_lit_conf('arch'):
|
|
|
+ self.lit_config.warning('ignoring arch, using target_triple')
|
|
|
+ if self.get_lit_conf('platform'):
|
|
|
+ self.lit_config.warning('ignoring platform, using target_triple')
|
|
|
+ return
|
|
|
+
|
|
|
+ assert not self.use_target
|
|
|
+ assert self.target_info.is_host_macosx()
|
|
|
+
|
|
|
+ # Always specify deployment explicitly on Apple platforms, since
|
|
|
+ # otherwise a platform is picked up from the SDK. If the SDK version
|
|
|
+ # doesn't match the system version, tests that use the system library
|
|
|
+ # may fail spuriously.
|
|
|
+ arch = self.get_lit_conf('arch')
|
|
|
+ if not arch:
|
|
|
+ arch = self.cxx.getTriple().split('-', 1)[0]
|
|
|
+ self.lit_config.note("inferred arch as: %r" % arch)
|
|
|
+
|
|
|
+ inferred_platform, name, version = self.target_info.get_platform()
|
|
|
+ if inferred_platform:
|
|
|
+ self.lit_config.note("inferred platform as: %r" % (name + version))
|
|
|
+ self.config.deployment = (arch, name, version)
|
|
|
+
|
|
|
+ # Set the target triple for use by lit.
|
|
|
+ self.config.target_triple = arch + '-apple-' + name + version
|
|
|
+ self.lit_config.note(
|
|
|
+ "computed target_triple as: %r" % self.config.target_triple)
|
|
|
+
|
|
|
+ def configure_env(self):
|
|
|
+ self.target_info.configure_env(self.exec_env)
|
|
|
+
|
|
|
+ def add_path(self, dest_env, new_path):
|
|
|
+ if 'PATH' not in dest_env:
|
|
|
+ dest_env['PATH'] = new_path
|
|
|
+ else:
|
|
|
+ split_char = ';' if self.is_windows else ':'
|
|
|
+ dest_env['PATH'] = '%s%s%s' % (new_path, split_char,
|
|
|
+ dest_env['PATH'])
|