You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
10 KiB
Python
286 lines
10 KiB
Python
#===----------------------------------------------------------------------===//
|
|
#
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
#
|
|
#===----------------------------------------------------------------------===//
|
|
|
|
import importlib
|
|
import locale
|
|
import os
|
|
import platform
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
from libcxx.util import executeCommand
|
|
|
|
class DefaultTargetInfo(object):
|
|
def __init__(self, full_config):
|
|
self.full_config = full_config
|
|
|
|
def platform(self):
|
|
return sys.platform.lower().strip()
|
|
|
|
def add_locale_features(self, features):
|
|
self.full_config.lit_config.warning(
|
|
"No locales entry for target_system: %s" % self.platform())
|
|
|
|
def add_cxx_compile_flags(self, flags): pass
|
|
def add_cxx_link_flags(self, flags): pass
|
|
def configure_env(self, env): pass
|
|
def allow_cxxabi_link(self): return True
|
|
def add_sanitizer_features(self, sanitizer_type, features): pass
|
|
def use_lit_shell_default(self): return False
|
|
|
|
|
|
def test_locale(loc):
|
|
assert loc is not None
|
|
default_locale = locale.setlocale(locale.LC_ALL)
|
|
try:
|
|
locale.setlocale(locale.LC_ALL, loc)
|
|
return True
|
|
except locale.Error:
|
|
return False
|
|
finally:
|
|
locale.setlocale(locale.LC_ALL, default_locale)
|
|
|
|
|
|
def add_common_locales(features, lit_config, is_windows=False):
|
|
# A list of locales needed by the test-suite.
|
|
# The list uses the canonical name for the locale used in the test-suite
|
|
# TODO: On Linux ISO8859 *may* needs to hyphenated.
|
|
locales = [
|
|
('en_US.UTF-8', 'English_United States.1252'),
|
|
('fr_FR.UTF-8', 'French_France.1252'),
|
|
('ru_RU.UTF-8', 'Russian_Russia.1251'),
|
|
('zh_CN.UTF-8', 'Chinese_China.936'),
|
|
('fr_CA.ISO8859-1', 'French_Canada.1252'),
|
|
('cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250')
|
|
]
|
|
for loc_id, windows_loc_name in locales:
|
|
loc_name = windows_loc_name if is_windows else loc_id
|
|
if test_locale(loc_name):
|
|
features.add('locale.{0}'.format(loc_id))
|
|
else:
|
|
lit_config.warning('The locale {0} is not supported by '
|
|
'your platform. Some tests will be '
|
|
'unsupported.'.format(loc_name))
|
|
|
|
|
|
class DarwinLocalTI(DefaultTargetInfo):
|
|
def __init__(self, full_config):
|
|
super(DarwinLocalTI, self).__init__(full_config)
|
|
|
|
def is_host_macosx(self):
|
|
name = subprocess.check_output(['sw_vers', '-productName']).strip()
|
|
return name == "Mac OS X"
|
|
|
|
def get_macosx_version(self):
|
|
assert self.is_host_macosx()
|
|
version = subprocess.check_output(
|
|
['sw_vers', '-productVersion']).strip()
|
|
version = re.sub(r'([0-9]+\.[0-9]+)(\..*)?', r'\1', version)
|
|
return version
|
|
|
|
def get_sdk_version(self, name):
|
|
assert self.is_host_macosx()
|
|
cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
|
|
try:
|
|
out = subprocess.check_output(cmd).strip()
|
|
except OSError:
|
|
pass
|
|
|
|
if not out:
|
|
self.full_config.lit_config.fatal(
|
|
"cannot infer sdk version with: %r" % cmd)
|
|
|
|
return re.sub(r'.*/[^0-9]+([0-9.]+)\.sdk', r'\1', out)
|
|
|
|
def get_platform(self):
|
|
platform = self.full_config.get_lit_conf('platform')
|
|
if platform:
|
|
platform = re.sub(r'([^0-9]+)([0-9\.]*)', r'\1-\2', platform)
|
|
name, version = tuple(platform.split('-', 1))
|
|
else:
|
|
name = 'macosx'
|
|
version = None
|
|
|
|
if version:
|
|
return (False, name, version)
|
|
|
|
# Infer the version, either from the SDK or the system itself. For
|
|
# macosx, ignore the SDK version; what matters is what's at
|
|
# /usr/lib/libc++.dylib.
|
|
if name == 'macosx':
|
|
version = self.get_macosx_version()
|
|
else:
|
|
version = self.get_sdk_version(name)
|
|
return (True, name, version)
|
|
|
|
def add_locale_features(self, features):
|
|
add_common_locales(features, self.full_config.lit_config)
|
|
|
|
def add_cxx_compile_flags(self, flags):
|
|
if self.full_config.use_deployment:
|
|
_, name, _ = self.full_config.config.deployment
|
|
cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
|
|
else:
|
|
cmd = ['xcrun', '--show-sdk-path']
|
|
out, err, exit_code = executeCommand(cmd)
|
|
if exit_code != 0:
|
|
self.full_config.lit_config.warning("Could not determine macOS SDK path! stderr was " + err)
|
|
if exit_code == 0 and out:
|
|
sdk_path = out.strip()
|
|
self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path)
|
|
assert isinstance(sdk_path, str)
|
|
flags += ["-isysroot", sdk_path]
|
|
|
|
def add_cxx_link_flags(self, flags):
|
|
flags += ['-lSystem']
|
|
|
|
def configure_env(self, env):
|
|
library_paths = []
|
|
# Configure the library path for libc++
|
|
if self.full_config.cxx_runtime_root:
|
|
library_paths += [self.full_config.cxx_runtime_root]
|
|
elif self.full_config.use_system_cxx_lib:
|
|
if (os.path.isdir(str(self.full_config.use_system_cxx_lib))):
|
|
library_paths += [self.full_config.use_system_cxx_lib]
|
|
|
|
# Configure the abi library path
|
|
if self.full_config.abi_library_root:
|
|
library_paths += [self.full_config.abi_library_root]
|
|
if library_paths:
|
|
env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths)
|
|
|
|
def allow_cxxabi_link(self):
|
|
# Don't link libc++abi explicitly on OS X because the symbols
|
|
# should be available in libc++ directly.
|
|
return False
|
|
|
|
|
|
class FreeBSDLocalTI(DefaultTargetInfo):
|
|
def __init__(self, full_config):
|
|
super(FreeBSDLocalTI, self).__init__(full_config)
|
|
|
|
def add_locale_features(self, features):
|
|
add_common_locales(features, self.full_config.lit_config)
|
|
|
|
def add_cxx_link_flags(self, flags):
|
|
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
|
|
|
|
|
|
class NetBSDLocalTI(DefaultTargetInfo):
|
|
def __init__(self, full_config):
|
|
super(NetBSDLocalTI, self).__init__(full_config)
|
|
|
|
def add_locale_features(self, features):
|
|
add_common_locales(features, self.full_config.lit_config)
|
|
|
|
def add_cxx_link_flags(self, flags):
|
|
flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi',
|
|
'-lunwind']
|
|
|
|
|
|
class LinuxLocalTI(DefaultTargetInfo):
|
|
def __init__(self, full_config):
|
|
super(LinuxLocalTI, self).__init__(full_config)
|
|
|
|
def platform(self):
|
|
return 'linux'
|
|
|
|
def platform_name(self):
|
|
name, _, _ = platform.linux_distribution()
|
|
# Some distros have spaces, e.g. 'SUSE Linux Enterprise Server'
|
|
# lit features can't have spaces
|
|
name = name.lower().strip().replace(' ', '-')
|
|
return name # Permitted to be None
|
|
|
|
def platform_ver(self):
|
|
_, ver, _ = platform.linux_distribution()
|
|
ver = ver.lower().strip().replace(' ', '-')
|
|
return ver # Permitted to be None.
|
|
|
|
def add_locale_features(self, features):
|
|
add_common_locales(features, self.full_config.lit_config)
|
|
# Some linux distributions have different locale data than others.
|
|
# Insert the distributions name and name-version into the available
|
|
# features to allow tests to XFAIL on them.
|
|
name = self.platform_name()
|
|
ver = self.platform_ver()
|
|
if name:
|
|
features.add(name)
|
|
if name and ver:
|
|
features.add('%s-%s' % (name, ver))
|
|
|
|
def add_cxx_compile_flags(self, flags):
|
|
flags += ['-D__STDC_FORMAT_MACROS',
|
|
'-D__STDC_LIMIT_MACROS',
|
|
'-D__STDC_CONSTANT_MACROS']
|
|
|
|
def add_cxx_link_flags(self, flags):
|
|
enable_threads = ('libcpp-has-no-threads' not in
|
|
self.full_config.config.available_features)
|
|
llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False)
|
|
shared_libcxx = self.full_config.get_lit_bool('enable_shared', True)
|
|
flags += ['-lm']
|
|
if not llvm_unwinder:
|
|
flags += ['-lgcc_s', '-lgcc']
|
|
if enable_threads:
|
|
flags += ['-lpthread']
|
|
if not shared_libcxx:
|
|
flags += ['-lrt']
|
|
flags += ['-lc']
|
|
if llvm_unwinder:
|
|
flags += ['-lunwind', '-ldl']
|
|
else:
|
|
flags += ['-lgcc_s']
|
|
builtins_lib = self.full_config.get_lit_conf('builtins_library')
|
|
if builtins_lib:
|
|
flags += [builtins_lib]
|
|
else:
|
|
flags += ['-lgcc']
|
|
use_libatomic = self.full_config.get_lit_bool('use_libatomic', False)
|
|
if use_libatomic:
|
|
flags += ['-latomic']
|
|
san = self.full_config.get_lit_conf('use_sanitizer', '').strip()
|
|
if san:
|
|
# The libraries and their order are taken from the
|
|
# linkSanitizerRuntimeDeps function in
|
|
# clang/lib/Driver/Tools.cpp
|
|
flags += ['-lpthread', '-lrt', '-lm', '-ldl']
|
|
|
|
|
|
class WindowsLocalTI(DefaultTargetInfo):
|
|
def __init__(self, full_config):
|
|
super(WindowsLocalTI, self).__init__(full_config)
|
|
|
|
def add_locale_features(self, features):
|
|
add_common_locales(features, self.full_config.lit_config,
|
|
is_windows=True)
|
|
|
|
def use_lit_shell_default(self):
|
|
# Default to the internal shell on Windows, as bash on Windows is
|
|
# usually very slow.
|
|
return True
|
|
|
|
|
|
def make_target_info(full_config):
|
|
default = "libcxx.test.target_info.LocalTI"
|
|
info_str = full_config.get_lit_conf('target_info', default)
|
|
if info_str != default:
|
|
mod_path, _, info = info_str.rpartition('.')
|
|
mod = importlib.import_module(mod_path)
|
|
target_info = getattr(mod, info)(full_config)
|
|
full_config.lit_config.note("inferred target_info as: %r" % info_str)
|
|
return target_info
|
|
target_system = platform.system()
|
|
if target_system == 'Darwin': return DarwinLocalTI(full_config)
|
|
if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config)
|
|
if target_system == 'NetBSD': return NetBSDLocalTI(full_config)
|
|
if target_system == 'Linux': return LinuxLocalTI(full_config)
|
|
if target_system == 'Windows': return WindowsLocalTI(full_config)
|
|
return DefaultTargetInfo(full_config)
|