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