]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - utils/libcxx/test/target_info.py
Vendor import of libc++ trunk r351319 (just before the release_80
[FreeBSD/FreeBSD.git] / utils / libcxx / test / target_info.py
1 #===----------------------------------------------------------------------===//
2 #
3 #                     The LLVM Compiler Infrastructure
4 #
5 # This file is dual licensed under the MIT and the University of Illinois Open
6 # Source Licenses. See LICENSE.TXT for details.
7 #
8 #===----------------------------------------------------------------------===//
9
10 import importlib
11 import locale
12 import os
13 import platform
14 import re
15 import subprocess
16 import sys
17
18 from libcxx.util import executeCommand
19
20 class DefaultTargetInfo(object):
21     def __init__(self, full_config):
22         self.full_config = full_config
23
24     def platform(self):
25         return sys.platform.lower().strip()
26
27     def add_locale_features(self, features):
28         self.full_config.lit_config.warning(
29             "No locales entry for target_system: %s" % self.platform())
30
31     def add_cxx_compile_flags(self, flags): pass
32     def add_cxx_link_flags(self, flags): pass
33     def configure_env(self, env): pass
34     def allow_cxxabi_link(self): return True
35     def add_sanitizer_features(self, sanitizer_type, features): pass
36     def use_lit_shell_default(self): return False
37
38
39 def test_locale(loc):
40     assert loc is not None
41     default_locale = locale.setlocale(locale.LC_ALL)
42     try:
43         locale.setlocale(locale.LC_ALL, loc)
44         return True
45     except locale.Error:
46         return False
47     finally:
48         locale.setlocale(locale.LC_ALL, default_locale)
49
50
51 def add_common_locales(features, lit_config, is_windows=False):
52     # A list of locales needed by the test-suite.
53     # The list uses the canonical name for the locale used in the test-suite
54     # TODO: On Linux ISO8859 *may* needs to hyphenated.
55     locales = [
56         ('en_US.UTF-8', 'English_United States.1252'),
57         ('fr_FR.UTF-8', 'French_France.1252'),
58         ('ru_RU.UTF-8', 'Russian_Russia.1251'),
59         ('zh_CN.UTF-8', 'Chinese_China.936'),
60         ('fr_CA.ISO8859-1', 'French_Canada.1252'),
61         ('cs_CZ.ISO8859-2', 'Czech_Czech Republic.1250')
62     ]
63     for loc_id, windows_loc_name in locales:
64         loc_name = windows_loc_name if is_windows else loc_id
65         if test_locale(loc_name):
66             features.add('locale.{0}'.format(loc_id))
67         else:
68             lit_config.warning('The locale {0} is not supported by '
69                                'your platform. Some tests will be '
70                                'unsupported.'.format(loc_name))
71
72
73 class DarwinLocalTI(DefaultTargetInfo):
74     def __init__(self, full_config):
75         super(DarwinLocalTI, self).__init__(full_config)
76
77     def is_host_macosx(self):
78         name = subprocess.check_output(['sw_vers', '-productName']).strip()
79         return name == "Mac OS X"
80
81     def get_macosx_version(self):
82         assert self.is_host_macosx()
83         version = subprocess.check_output(
84             ['sw_vers', '-productVersion']).strip()
85         version = re.sub(r'([0-9]+\.[0-9]+)(\..*)?', r'\1', version)
86         return version
87
88     def get_sdk_version(self, name):
89         assert self.is_host_macosx()
90         cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
91         try:
92             out = subprocess.check_output(cmd).strip()
93         except OSError:
94             pass
95
96         if not out:
97             self.full_config.lit_config.fatal(
98                     "cannot infer sdk version with: %r" % cmd)
99
100         return re.sub(r'.*/[^0-9]+([0-9.]+)\.sdk', r'\1', out)
101
102     def get_platform(self):
103         platform = self.full_config.get_lit_conf('platform')
104         if platform:
105             platform = re.sub(r'([^0-9]+)([0-9\.]*)', r'\1-\2', platform)
106             name, version = tuple(platform.split('-', 1))
107         else:
108             name = 'macosx'
109             version = None
110
111         if version:
112             return (False, name, version)
113
114         # Infer the version, either from the SDK or the system itself.  For
115         # macosx, ignore the SDK version; what matters is what's at
116         # /usr/lib/libc++.dylib.
117         if name == 'macosx':
118             version = self.get_macosx_version()
119         else:
120             version = self.get_sdk_version(name)
121         return (True, name, version)
122
123     def add_locale_features(self, features):
124         add_common_locales(features, self.full_config.lit_config)
125
126     def add_cxx_compile_flags(self, flags):
127         if self.full_config.use_deployment:
128             _, name, _ = self.full_config.config.deployment
129             cmd = ['xcrun', '--sdk', name, '--show-sdk-path']
130         else:
131             cmd = ['xcrun', '--show-sdk-path']
132         out, err, exit_code = executeCommand(cmd)
133         if exit_code != 0:
134             self.full_config.lit_config.warning("Could not determine macOS SDK path! stderr was " + err)
135         if exit_code == 0 and out:
136             sdk_path = out.strip()
137             self.full_config.lit_config.note('using SDKROOT: %r' % sdk_path)
138             assert isinstance(sdk_path, str)
139             flags += ["-isysroot", sdk_path]
140
141     def add_cxx_link_flags(self, flags):
142         flags += ['-lSystem']
143
144     def configure_env(self, env):
145         library_paths = []
146         # Configure the library path for libc++
147         if self.full_config.cxx_runtime_root:
148             library_paths += [self.full_config.cxx_runtime_root]
149         elif self.full_config.use_system_cxx_lib:
150             if (os.path.isdir(str(self.full_config.use_system_cxx_lib))):
151                 library_paths += [self.full_config.use_system_cxx_lib]
152
153         # Configure the abi library path
154         if self.full_config.abi_library_root:
155             library_paths += [self.full_config.abi_library_root]
156         if library_paths:
157             env['DYLD_LIBRARY_PATH'] = ':'.join(library_paths)
158
159     def allow_cxxabi_link(self):
160         # FIXME: PR27405
161         # libc++ *should* export all of the symbols found in libc++abi on OS X.
162         # For this reason LibcxxConfiguration will not link libc++abi in OS X.
163         # However __cxa_throw_bad_new_array_length doesn't get exported into
164         # libc++ yet so we still need to explicitly link libc++abi when testing
165         # libc++abi
166         # See PR22654.
167         if(self.full_config.get_lit_conf('name', '') == 'libc++abi'):
168             return True
169         # Don't link libc++abi explicitly on OS X because the symbols
170         # should be available in libc++ directly.
171         return False
172
173
174 class FreeBSDLocalTI(DefaultTargetInfo):
175     def __init__(self, full_config):
176         super(FreeBSDLocalTI, self).__init__(full_config)
177
178     def add_locale_features(self, features):
179         add_common_locales(features, self.full_config.lit_config)
180
181     def add_cxx_link_flags(self, flags):
182         flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lcxxrt']
183
184
185 class NetBSDLocalTI(DefaultTargetInfo):
186     def __init__(self, full_config):
187         super(NetBSDLocalTI, self).__init__(full_config)
188
189     def add_locale_features(self, features):
190         add_common_locales(features, self.full_config.lit_config)
191
192     def add_cxx_link_flags(self, flags):
193         flags += ['-lc', '-lm', '-lpthread', '-lgcc_s', '-lc++abi',
194                   '-lunwind']
195
196
197 class LinuxLocalTI(DefaultTargetInfo):
198     def __init__(self, full_config):
199         super(LinuxLocalTI, self).__init__(full_config)
200
201     def platform(self):
202         return 'linux'
203
204     def platform_name(self):
205         name, _, _ = platform.linux_distribution()
206         # Some distros have spaces, e.g. 'SUSE Linux Enterprise Server'
207         # lit features can't have spaces
208         name = name.lower().strip().replace(' ', '-')
209         return name # Permitted to be None
210
211     def platform_ver(self):
212         _, ver, _ = platform.linux_distribution()
213         ver = ver.lower().strip().replace(' ', '-')
214         return ver # Permitted to be None.
215
216     def add_locale_features(self, features):
217         add_common_locales(features, self.full_config.lit_config)
218         # Some linux distributions have different locale data than others.
219         # Insert the distributions name and name-version into the available
220         # features to allow tests to XFAIL on them.
221         name = self.platform_name()
222         ver = self.platform_ver()
223         if name:
224             features.add(name)
225         if name and ver:
226             features.add('%s-%s' % (name, ver))
227
228     def add_cxx_compile_flags(self, flags):
229         flags += ['-D__STDC_FORMAT_MACROS',
230                   '-D__STDC_LIMIT_MACROS',
231                   '-D__STDC_CONSTANT_MACROS']
232
233     def add_cxx_link_flags(self, flags):
234         enable_threads = ('libcpp-has-no-threads' not in
235                           self.full_config.config.available_features)
236         llvm_unwinder = self.full_config.get_lit_bool('llvm_unwinder', False)
237         shared_libcxx = self.full_config.get_lit_bool('enable_shared', True)
238         # FIXME: Remove the need to link -lrt in all the tests, and instead
239         # limit it only to the filesystem tests. This ensures we don't cause an
240         # implicit dependency on librt except when filesystem is needed.
241         enable_fs = self.full_config.get_lit_bool('enable_filesystem',
242                                                   default=False)
243         flags += ['-lm']
244         if not llvm_unwinder:
245             flags += ['-lgcc_s', '-lgcc']
246         if enable_threads:
247             flags += ['-lpthread']
248             if not shared_libcxx or enable_fs:
249               flags += ['-lrt']
250         flags += ['-lc']
251         if llvm_unwinder:
252             flags += ['-lunwind', '-ldl']
253         else:
254             flags += ['-lgcc_s']
255         compiler_rt = self.full_config.get_lit_bool('compiler_rt', False)
256         if not compiler_rt:
257             flags += ['-lgcc']
258         use_libatomic = self.full_config.get_lit_bool('use_libatomic', False)
259         if use_libatomic:
260             flags += ['-latomic']
261         san = self.full_config.get_lit_conf('use_sanitizer', '').strip()
262         if san:
263             # The libraries and their order are taken from the
264             # linkSanitizerRuntimeDeps function in
265             # clang/lib/Driver/Tools.cpp
266             flags += ['-lpthread', '-lrt', '-lm', '-ldl']
267
268
269 class WindowsLocalTI(DefaultTargetInfo):
270     def __init__(self, full_config):
271         super(WindowsLocalTI, self).__init__(full_config)
272
273     def add_locale_features(self, features):
274         add_common_locales(features, self.full_config.lit_config,
275                            is_windows=True)
276
277     def use_lit_shell_default(self):
278         # Default to the internal shell on Windows, as bash on Windows is
279         # usually very slow.
280         return True
281
282
283 def make_target_info(full_config):
284     default = "libcxx.test.target_info.LocalTI"
285     info_str = full_config.get_lit_conf('target_info', default)
286     if info_str != default:
287         mod_path, _, info = info_str.rpartition('.')
288         mod = importlib.import_module(mod_path)
289         target_info = getattr(mod, info)(full_config)
290         full_config.lit_config.note("inferred target_info as: %r" % info_str)
291         return target_info
292     target_system = platform.system()
293     if target_system == 'Darwin':  return DarwinLocalTI(full_config)
294     if target_system == 'FreeBSD': return FreeBSDLocalTI(full_config)
295     if target_system == 'NetBSD':  return NetBSDLocalTI(full_config)
296     if target_system == 'Linux':   return LinuxLocalTI(full_config)
297     if target_system == 'Windows': return WindowsLocalTI(full_config)
298     return DefaultTargetInfo(full_config)