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
10import locale
11import os
12import platform
13import pkgutil
14import pipes
15import re
16import shlex
17import shutil
18import sys
19
20from libcxx.compiler import CXXCompiler
21from libcxx.test.target_info import make_target_info
22from libcxx.test.executor import *
23from libcxx.test.tracing import *
24import libcxx.util
25
26def loadSiteConfig(lit_config, config, param_name, env_name):
27    # We haven't loaded the site specific configuration (the user is
28    # probably trying to run on a test file directly, and either the site
29    # configuration hasn't been created by the build system, or we are in an
30    # out-of-tree build situation).
31    site_cfg = lit_config.params.get(param_name,
32                                     os.environ.get(env_name))
33    if not site_cfg:
34        lit_config.warning('No site specific configuration file found!'
35                           ' Running the tests in the default configuration.')
36    elif not os.path.isfile(site_cfg):
37        lit_config.fatal(
38            "Specified site configuration file does not exist: '%s'" %
39            site_cfg)
40    else:
41        lit_config.note('using site specific configuration at %s' % site_cfg)
42        ld_fn = lit_config.load_config
43
44        # Null out the load_config function so that lit.site.cfg doesn't
45        # recursively load a config even if it tries.
46        # TODO: This is one hell of a hack. Fix it.
47        def prevent_reload_fn(*args, **kwargs):
48            pass
49        lit_config.load_config = prevent_reload_fn
50        ld_fn(config, site_cfg)
51        lit_config.load_config = ld_fn
52
53class Configuration(object):
54    # pylint: disable=redefined-outer-name
55    def __init__(self, lit_config, config):
56        self.lit_config = lit_config
57        self.config = config
58        self.is_windows = platform.system() == 'Windows'
59        self.cxx = None
60        self.cxx_is_clang_cl = None
61        self.cxx_stdlib_under_test = None
62        self.project_obj_root = None
63        self.libcxx_src_root = None
64        self.libcxx_obj_root = None
65        self.cxx_library_root = None
66        self.cxx_runtime_root = None
67        self.abi_library_root = None
68        self.link_shared = self.get_lit_bool('enable_shared', default=True)
69        self.debug_build = self.get_lit_bool('debug_build',   default=False)
70        self.exec_env = dict(os.environ)
71        self.use_target = False
72        self.use_system_cxx_lib = False
73        self.use_clang_verify = False
74        self.long_tests = None
75        self.execute_external = False
76
77    def get_lit_conf(self, name, default=None):
78        val = self.lit_config.params.get(name, None)
79        if val is None:
80            val = getattr(self.config, name, None)
81            if val is None:
82                val = default
83        return val
84
85    def get_lit_bool(self, name, default=None, env_var=None):
86        def check_value(value, var_name):
87            if value is None:
88                return default
89            if isinstance(value, bool):
90                return value
91            if not isinstance(value, str):
92                raise TypeError('expected bool or string')
93            if value.lower() in ('1', 'true'):
94                return True
95            if value.lower() in ('', '0', 'false'):
96                return False
97            self.lit_config.fatal(
98                "parameter '{}' should be true or false".format(var_name))
99
100        conf_val = self.get_lit_conf(name)
101        if env_var is not None and env_var in os.environ and \
102                os.environ[env_var] is not None:
103            val = os.environ[env_var]
104            if conf_val is not None:
105                self.lit_config.warning(
106                    'Environment variable %s=%s is overriding explicit '
107                    '--param=%s=%s' % (env_var, val, name, conf_val))
108            return check_value(val, env_var)
109        return check_value(conf_val, name)
110
111    def get_modules_enabled(self):
112        return self.get_lit_bool('enable_modules',
113                                default=False,
114                                env_var='LIBCXX_ENABLE_MODULES')
115
116    def make_static_lib_name(self, name):
117        """Return the full filename for the specified library name"""
118        if self.is_windows:
119            assert name == 'c++'  # Only allow libc++ to use this function for now.
120            return 'lib' + name + '.lib'
121        else:
122            return 'lib' + name + '.a'
123
124    def configure(self):
125        self.configure_executor()
126        self.configure_use_system_cxx_lib()
127        self.configure_target_info()
128        self.configure_cxx()
129        self.configure_triple()
130        self.configure_deployment()
131        self.configure_availability()
132        self.configure_src_root()
133        self.configure_obj_root()
134        self.configure_cxx_stdlib_under_test()
135        self.configure_cxx_library_root()
136        self.configure_use_clang_verify()
137        self.configure_use_thread_safety()
138        self.configure_execute_external()
139        self.configure_ccache()
140        self.configure_compile_flags()
141        self.configure_filesystem_compile_flags()
142        self.configure_link_flags()
143        self.configure_env()
144        self.configure_color_diagnostics()
145        self.configure_debug_mode()
146        self.configure_warnings()
147        self.configure_sanitizer()
148        self.configure_coverage()
149        self.configure_modules()
150        self.configure_coroutines()
151        self.configure_substitutions()
152        self.configure_features()
153
154    def print_config_info(self):
155        # Print the final compile and link flags.
156        self.lit_config.note('Using compiler: %s' % self.cxx.path)
157        self.lit_config.note('Using flags: %s' % self.cxx.flags)
158        if self.cxx.use_modules:
159            self.lit_config.note('Using modules flags: %s' %
160                                 self.cxx.modules_flags)
161        self.lit_config.note('Using compile flags: %s'
162                             % self.cxx.compile_flags)
163        if len(self.cxx.warning_flags):
164            self.lit_config.note('Using warnings: %s' % self.cxx.warning_flags)
165        self.lit_config.note('Using link flags: %s' % self.cxx.link_flags)
166        # Print as list to prevent "set([...])" from being printed.
167        self.lit_config.note('Using available_features: %s' %
168                             list(self.config.available_features))
169        show_env_vars = {}
170        for k,v in self.exec_env.items():
171            if k not in os.environ or os.environ[k] != v:
172                show_env_vars[k] = v
173        self.lit_config.note('Adding environment variables: %r' % show_env_vars)
174        sys.stderr.flush()  # Force flushing to avoid broken output on Windows
175
176    def get_test_format(self):
177        from libcxx.test.format import LibcxxTestFormat
178        return LibcxxTestFormat(
179            self.cxx,
180            self.use_clang_verify,
181            self.execute_external,
182            self.executor,
183            exec_env=self.exec_env)
184
185    def configure_executor(self):
186        exec_str = self.get_lit_conf('executor', "None")
187        te = eval(exec_str)
188        if te:
189            self.lit_config.note("Using executor: %r" % exec_str)
190            if self.lit_config.useValgrind:
191                # We have no way of knowing where in the chain the
192                # ValgrindExecutor is supposed to go. It is likely
193                # that the user wants it at the end, but we have no
194                # way of getting at that easily.
195                selt.lit_config.fatal("Cannot infer how to create a Valgrind "
196                                      " executor.")
197        else:
198            te = LocalExecutor()
199            if self.lit_config.useValgrind:
200                te = ValgrindExecutor(self.lit_config.valgrindArgs, te)
201        self.executor = te
202
203    def configure_target_info(self):
204        self.target_info = make_target_info(self)
205
206    def configure_cxx(self):
207        # Gather various compiler parameters.
208        cxx = self.get_lit_conf('cxx_under_test')
209        self.cxx_is_clang_cl = cxx is not None and \
210                               os.path.basename(cxx) == 'clang-cl.exe'
211        # If no specific cxx_under_test was given, attempt to infer it as
212        # clang++.
213        if cxx is None or self.cxx_is_clang_cl:
214            search_paths = self.config.environment['PATH']
215            if cxx is not None and os.path.isabs(cxx):
216                search_paths = os.path.dirname(cxx)
217            clangxx = libcxx.util.which('clang++', search_paths)
218            if clangxx:
219                cxx = clangxx
220                self.lit_config.note(
221                    "inferred cxx_under_test as: %r" % cxx)
222            elif self.cxx_is_clang_cl:
223                self.lit_config.fatal('Failed to find clang++ substitution for'
224                                      ' clang-cl')
225        if not cxx:
226            self.lit_config.fatal('must specify user parameter cxx_under_test '
227                                  '(e.g., --param=cxx_under_test=clang++)')
228        self.cxx = CXXCompiler(cxx) if not self.cxx_is_clang_cl else \
229                   self._configure_clang_cl(cxx)
230        cxx_type = self.cxx.type
231        if cxx_type is not None:
232            assert self.cxx.version is not None
233            maj_v, min_v, _ = self.cxx.version
234            self.config.available_features.add(cxx_type)
235            self.config.available_features.add('%s-%s' % (cxx_type, maj_v))
236            self.config.available_features.add('%s-%s.%s' % (
237                cxx_type, maj_v, min_v))
238        self.cxx.compile_env = dict(os.environ)
239        # 'CCACHE_CPP2' prevents ccache from stripping comments while
240        # preprocessing. This is required to prevent stripping of '-verify'
241        # comments.
242        self.cxx.compile_env['CCACHE_CPP2'] = '1'
243
244    def _configure_clang_cl(self, clang_path):
245        def _split_env_var(var):
246            return [p.strip() for p in os.environ.get(var, '').split(';') if p.strip()]
247
248        def _prefixed_env_list(var, prefix):
249            from itertools import chain
250            return list(chain.from_iterable((prefix, path) for path in _split_env_var(var)))
251
252        assert self.cxx_is_clang_cl
253        flags = []
254        compile_flags = _prefixed_env_list('INCLUDE', '-isystem')
255        link_flags = _prefixed_env_list('LIB', '-L')
256        for path in _split_env_var('LIB'):
257            self.add_path(self.exec_env, path)
258        return CXXCompiler(clang_path, flags=flags,
259                           compile_flags=compile_flags,
260                           link_flags=link_flags)
261
262    def _dump_macros_verbose(self, *args, **kwargs):
263        macros_or_error = self.cxx.dumpMacros(*args, **kwargs)
264        if isinstance(macros_or_error, tuple):
265            cmd, out, err, rc = macros_or_error
266            report = libcxx.util.makeReport(cmd, out, err, rc)
267            report += "Compiler failed unexpectedly when dumping macros!"
268            self.lit_config.fatal(report)
269            return None
270        assert isinstance(macros_or_error, dict)
271        return macros_or_error
272
273    def configure_src_root(self):
274        self.libcxx_src_root = self.get_lit_conf(
275            'libcxx_src_root', os.path.dirname(self.config.test_source_root))
276
277    def configure_obj_root(self):
278        self.project_obj_root = self.get_lit_conf('project_obj_root')
279        self.libcxx_obj_root = self.get_lit_conf('libcxx_obj_root')
280        if not self.libcxx_obj_root and self.project_obj_root is not None:
281            possible_root = os.path.join(self.project_obj_root, 'projects', 'libcxx')
282            if os.path.isdir(possible_root):
283                self.libcxx_obj_root = possible_root
284            else:
285                self.libcxx_obj_root = self.project_obj_root
286
287    def configure_cxx_library_root(self):
288        self.cxx_library_root = self.get_lit_conf('cxx_library_root',
289                                                  self.libcxx_obj_root)
290        self.cxx_runtime_root = self.get_lit_conf('cxx_runtime_root',
291                                                   self.cxx_library_root)
292
293    def configure_use_system_cxx_lib(self):
294        # This test suite supports testing against either the system library or
295        # the locally built one; the former mode is useful for testing ABI
296        # compatibility between the current headers and a shipping dynamic
297        # library.
298        # Default to testing against the locally built libc++ library.
299        self.use_system_cxx_lib = self.get_lit_conf('use_system_cxx_lib')
300        if self.use_system_cxx_lib == 'true':
301            self.use_system_cxx_lib = True
302        elif self.use_system_cxx_lib == 'false':
303            self.use_system_cxx_lib = False
304        elif self.use_system_cxx_lib:
305            assert os.path.isdir(self.use_system_cxx_lib)
306        self.lit_config.note(
307            "inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib)
308
309    def configure_availability(self):
310        # See http://llvm.org/docs/AvailabilityMarkup.html
311        self.with_availability = self.get_lit_bool('with_availability', False)
312        self.lit_config.note(
313            "inferred with_availability as: %r" % self.with_availability)
314
315    def configure_cxx_stdlib_under_test(self):
316        self.cxx_stdlib_under_test = self.get_lit_conf(
317            'cxx_stdlib_under_test', 'libc++')
318        if self.cxx_stdlib_under_test not in \
319                ['libc++', 'libstdc++', 'msvc', 'cxx_default']:
320            self.lit_config.fatal(
321                'unsupported value for "cxx_stdlib_under_test": %s'
322                % self.cxx_stdlib_under_test)
323        self.config.available_features.add(self.cxx_stdlib_under_test)
324        if self.cxx_stdlib_under_test == 'libstdc++':
325            self.config.available_features.add('libstdc++')
326            # Manually enable the experimental and filesystem tests for libstdc++
327            # if the options aren't present.
328            # FIXME this is a hack.
329            if self.get_lit_conf('enable_experimental') is None:
330                self.config.enable_experimental = 'true'
331            if self.get_lit_conf('enable_filesystem') is None:
332                self.config.enable_filesystem = 'true'
333
334    def configure_use_clang_verify(self):
335        '''If set, run clang with -verify on failing tests.'''
336        if self.with_availability:
337            self.use_clang_verify = False
338            return
339        self.use_clang_verify = self.get_lit_bool('use_clang_verify')
340        if self.use_clang_verify is None:
341            # NOTE: We do not test for the -verify flag directly because
342            #   -verify will always exit with non-zero on an empty file.
343            self.use_clang_verify = self.cxx.isVerifySupported()
344            self.lit_config.note(
345                "inferred use_clang_verify as: %r" % self.use_clang_verify)
346        if self.use_clang_verify:
347                self.config.available_features.add('verify-support')
348
349    def configure_use_thread_safety(self):
350        '''If set, run clang with -verify on failing tests.'''
351        has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety')
352        if has_thread_safety:
353            self.cxx.compile_flags += ['-Werror=thread-safety']
354            self.config.available_features.add('thread-safety')
355            self.lit_config.note("enabling thread-safety annotations")
356
357    def configure_execute_external(self):
358        # Choose between lit's internal shell pipeline runner and a real shell.
359        # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the
360        # default value. Otherwise we ask the target_info.
361        use_lit_shell_default = os.environ.get('LIT_USE_INTERNAL_SHELL')
362        if use_lit_shell_default is not None:
363            use_lit_shell_default = use_lit_shell_default != '0'
364        else:
365            use_lit_shell_default = self.target_info.use_lit_shell_default()
366        # Check for the command line parameter using the default value if it is
367        # not present.
368        use_lit_shell = self.get_lit_bool('use_lit_shell',
369                                          use_lit_shell_default)
370        self.execute_external = not use_lit_shell
371
372    def configure_ccache(self):
373        use_ccache_default = os.environ.get('LIBCXX_USE_CCACHE') is not None
374        use_ccache = self.get_lit_bool('use_ccache', use_ccache_default)
375        if use_ccache:
376            self.cxx.use_ccache = True
377            self.lit_config.note('enabling ccache')
378
379    def add_deployment_feature(self, feature):
380        (arch, name, version) = self.config.deployment
381        self.config.available_features.add('%s=%s-%s' % (feature, arch, name))
382        self.config.available_features.add('%s=%s' % (feature, name))
383        self.config.available_features.add('%s=%s%s' % (feature, name, version))
384
385    def configure_features(self):
386        additional_features = self.get_lit_conf('additional_features')
387        if additional_features:
388            for f in additional_features.split(','):
389                self.config.available_features.add(f.strip())
390        self.target_info.add_locale_features(self.config.available_features)
391
392        target_platform = self.target_info.platform()
393
394        # Write an "available feature" that combines the triple when
395        # use_system_cxx_lib is enabled. This is so that we can easily write
396        # XFAIL markers for tests that are known to fail with versions of
397        # libc++ as were shipped with a particular triple.
398        if self.use_system_cxx_lib:
399            self.config.available_features.add('with_system_cxx_lib')
400            self.config.available_features.add(
401                'with_system_cxx_lib=%s' % self.config.target_triple)
402
403            # Add subcomponents individually.
404            target_components = self.config.target_triple.split('-')
405            for component in target_components:
406                self.config.available_features.add(
407                    'with_system_cxx_lib=%s' % component)
408
409            # Add available features for more generic versions of the target
410            # triple attached to  with_system_cxx_lib.
411            if self.use_deployment:
412                self.add_deployment_feature('with_system_cxx_lib')
413
414        # Configure the availability markup checks features.
415        if self.with_availability:
416            self.config.available_features.add('availability_markup')
417            self.add_deployment_feature('availability_markup')
418
419        if self.use_system_cxx_lib or self.with_availability:
420            self.config.available_features.add('availability')
421            self.add_deployment_feature('availability')
422
423        if platform.system() == 'Darwin':
424            self.config.available_features.add('apple-darwin')
425
426        # Insert the platform name into the available features as a lower case.
427        self.config.available_features.add(target_platform)
428
429        # Simulator testing can take a really long time for some of these tests
430        # so add a feature check so we can REQUIRES: long_tests in them
431        self.long_tests = self.get_lit_bool('long_tests')
432        if self.long_tests is None:
433            # Default to running long tests.
434            self.long_tests = True
435            self.lit_config.note(
436                "inferred long_tests as: %r" % self.long_tests)
437
438        if self.long_tests:
439            self.config.available_features.add('long_tests')
440
441        # Run a compile test for the -fsized-deallocation flag. This is needed
442        # in test/std/language.support/support.dynamic/new.delete
443        if self.cxx.hasCompileFlag('-fsized-deallocation'):
444            self.config.available_features.add('fsized-deallocation')
445
446        if self.cxx.hasCompileFlag('-faligned-allocation'):
447            self.config.available_features.add('-faligned-allocation')
448        else:
449            # FIXME remove this once more than just clang-4.0 support
450            # C++17 aligned allocation.
451            self.config.available_features.add('no-aligned-allocation')
452
453        if self.cxx.hasCompileFlag('-fdelayed-template-parsing'):
454            self.config.available_features.add('fdelayed-template-parsing')
455
456        if self.get_lit_bool('has_libatomic', False):
457            self.config.available_features.add('libatomic')
458
459        macros = self._dump_macros_verbose()
460        if '__cpp_if_constexpr' not in macros:
461            self.config.available_features.add('libcpp-no-if-constexpr')
462
463        if '__cpp_structured_bindings' not in macros:
464            self.config.available_features.add('libcpp-no-structured-bindings')
465
466        if '__cpp_deduction_guides' not in macros:
467            self.config.available_features.add('libcpp-no-deduction-guides')
468
469        if self.is_windows:
470            self.config.available_features.add('windows')
471            if self.cxx_stdlib_under_test == 'libc++':
472                # LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
473                # initial Windows failures until they can be properly diagnosed
474                # and fixed. This allows easier detection of new test failures
475                # and regressions. Note: New failures should not be suppressed
476                # using this feature. (Also see llvm.org/PR32730)
477                self.config.available_features.add('LIBCXX-WINDOWS-FIXME')
478
479        # Attempt to detect the glibc version by querying for __GLIBC__
480        # in 'features.h'.
481        macros = self.cxx.dumpMacros(flags=['-include', 'features.h'])
482        if isinstance(macros, dict) and '__GLIBC__' in macros:
483            maj_v, min_v = (macros['__GLIBC__'], macros['__GLIBC_MINOR__'])
484            self.config.available_features.add('glibc')
485            self.config.available_features.add('glibc-%s' % maj_v)
486            self.config.available_features.add('glibc-%s.%s' % (maj_v, min_v))
487
488        # Support Objective-C++ only on MacOS and if the compiler supports it.
489        if self.target_info.platform() == "darwin" and \
490           self.target_info.is_host_macosx() and \
491           self.cxx.hasCompileFlag(["-x", "objective-c++", "-fobjc-arc"]):
492            self.config.available_features.add("objective-c++")
493
494    def configure_compile_flags(self):
495        no_default_flags = self.get_lit_bool('no_default_flags', False)
496        if not no_default_flags:
497            self.configure_default_compile_flags()
498        # This include is always needed so add so add it regardless of
499        # 'no_default_flags'.
500        support_path = os.path.join(self.libcxx_src_root, 'test/support')
501        self.cxx.compile_flags += ['-I' + support_path]
502        # Configure extra flags
503        compile_flags_str = self.get_lit_conf('compile_flags', '')
504        self.cxx.compile_flags += shlex.split(compile_flags_str)
505        if self.is_windows:
506            # FIXME: Can we remove this?
507            self.cxx.compile_flags += ['-D_CRT_SECURE_NO_WARNINGS']
508            # Required so that tests using min/max don't fail on Windows,
509            # and so that those tests don't have to be changed to tolerate
510            # this insanity.
511            self.cxx.compile_flags += ['-DNOMINMAX']
512
513    def configure_default_compile_flags(self):
514        # Try and get the std version from the command line. Fall back to
515        # default given in lit.site.cfg is not present. If default is not
516        # present then force c++11.
517        std = self.get_lit_conf('std')
518        if not std:
519            # Choose the newest possible language dialect if none is given.
520            possible_stds = ['c++2a', 'c++17', 'c++1z', 'c++14', 'c++11',
521                             'c++03']
522            if self.cxx.type == 'gcc':
523                maj_v, _, _ = self.cxx.version
524                maj_v = int(maj_v)
525                if maj_v < 7:
526                    possible_stds.remove('c++1z')
527                # FIXME: How many C++14 tests actually fail under GCC 5 and 6?
528                # Should we XFAIL them individually instead?
529                if maj_v <= 6:
530                    possible_stds.remove('c++14')
531            for s in possible_stds:
532                if self.cxx.hasCompileFlag('-std=%s' % s):
533                    std = s
534                    self.lit_config.note(
535                        'inferred language dialect as: %s' % std)
536                    break
537            if not std:
538                self.lit_config.fatal(
539                    'Failed to infer a supported language dialect from one of %r'
540                    % possible_stds)
541        self.cxx.compile_flags += ['-std={0}'.format(std)]
542        std_feature = std.replace('gnu++', 'c++')
543        std_feature = std.replace('1z', '17')
544        self.config.available_features.add(std_feature)
545        # Configure include paths
546        self.configure_compile_flags_header_includes()
547        self.target_info.add_cxx_compile_flags(self.cxx.compile_flags)
548        # Configure feature flags.
549        self.configure_compile_flags_exceptions()
550        self.configure_compile_flags_rtti()
551        self.configure_compile_flags_abi_version()
552        enable_32bit = self.get_lit_bool('enable_32bit', False)
553        if enable_32bit:
554            self.cxx.flags += ['-m32']
555        # Use verbose output for better errors
556        self.cxx.flags += ['-v']
557        sysroot = self.get_lit_conf('sysroot')
558        if sysroot:
559            self.cxx.flags += ['--sysroot', sysroot]
560        gcc_toolchain = self.get_lit_conf('gcc_toolchain')
561        if gcc_toolchain:
562            self.cxx.flags += ['-gcc-toolchain', gcc_toolchain]
563        # NOTE: the _DEBUG definition must preceed the triple check because for
564        # the Windows build of libc++, the forced inclusion of a header requires
565        # that _DEBUG is defined.  Incorrect ordering will result in -target
566        # being elided.
567        if self.is_windows and self.debug_build:
568            self.cxx.compile_flags += ['-D_DEBUG']
569        if self.use_target:
570            if not self.cxx.addFlagIfSupported(
571                    ['-target', self.config.target_triple]):
572                self.lit_config.warning('use_target is true but -target is '\
573                        'not supported by the compiler')
574        if self.use_deployment:
575            arch, name, version = self.config.deployment
576            self.cxx.flags += ['-arch', arch]
577            self.cxx.flags += ['-m' + name + '-version-min=' + version]
578
579        # Disable availability unless explicitely requested
580        if not self.with_availability:
581            self.cxx.flags += ['-D_LIBCPP_DISABLE_AVAILABILITY']
582        # FIXME(EricWF): variant_size.pass.cpp requires a slightly larger
583        # template depth with older Clang versions.
584        self.cxx.addFlagIfSupported('-ftemplate-depth=270')
585
586    def configure_compile_flags_header_includes(self):
587        support_path = os.path.join(self.libcxx_src_root, 'test', 'support')
588        self.configure_config_site_header()
589        if self.cxx_stdlib_under_test != 'libstdc++' and \
590           not self.is_windows:
591            self.cxx.compile_flags += [
592                '-include', os.path.join(support_path, 'nasty_macros.hpp')]
593        if self.cxx_stdlib_under_test == 'msvc':
594            self.cxx.compile_flags += [
595                '-include', os.path.join(support_path,
596                                         'msvc_stdlib_force_include.hpp')]
597            pass
598        if self.is_windows and self.debug_build and \
599                self.cxx_stdlib_under_test != 'msvc':
600            self.cxx.compile_flags += [
601                '-include', os.path.join(support_path,
602                                         'set_windows_crt_report_mode.h')
603            ]
604        cxx_headers = self.get_lit_conf('cxx_headers')
605        if cxx_headers == '' or (cxx_headers is None
606                                 and self.cxx_stdlib_under_test != 'libc++'):
607            self.lit_config.note('using the system cxx headers')
608            return
609        self.cxx.compile_flags += ['-nostdinc++']
610        if cxx_headers is None:
611            cxx_headers = os.path.join(self.libcxx_src_root, 'include')
612        if not os.path.isdir(cxx_headers):
613            self.lit_config.fatal("cxx_headers='%s' is not a directory."
614                                  % cxx_headers)
615        self.cxx.compile_flags += ['-I' + cxx_headers]
616        if self.libcxx_obj_root is not None:
617            cxxabi_headers = os.path.join(self.libcxx_obj_root, 'include',
618                                          'c++build')
619            if os.path.isdir(cxxabi_headers):
620                self.cxx.compile_flags += ['-I' + cxxabi_headers]
621
622    def configure_config_site_header(self):
623        # Check for a possible __config_site in the build directory. We
624        # use this if it exists.
625        if self.libcxx_obj_root is None:
626            return
627        config_site_header = os.path.join(self.libcxx_obj_root, '__config_site')
628        if not os.path.isfile(config_site_header):
629            return
630        contained_macros = self.parse_config_site_and_add_features(
631            config_site_header)
632        self.lit_config.note('Using __config_site header %s with macros: %r'
633            % (config_site_header, contained_macros))
634        # FIXME: This must come after the call to
635        # 'parse_config_site_and_add_features(...)' in order for it to work.
636        self.cxx.compile_flags += ['-include', config_site_header]
637
638    def parse_config_site_and_add_features(self, header):
639        """ parse_config_site_and_add_features - Deduce and add the test
640            features that that are implied by the #define's in the __config_site
641            header. Return a dictionary containing the macros found in the
642            '__config_site' header.
643        """
644        # Parse the macro contents of __config_site by dumping the macros
645        # using 'c++ -dM -E' and filtering the predefines.
646        predefines = self._dump_macros_verbose()
647        macros = self._dump_macros_verbose(header)
648        feature_macros_keys = set(macros.keys()) - set(predefines.keys())
649        feature_macros = {}
650        for k in feature_macros_keys:
651            feature_macros[k] = macros[k]
652        # We expect the header guard to be one of the definitions
653        assert '_LIBCPP_CONFIG_SITE' in feature_macros
654        del feature_macros['_LIBCPP_CONFIG_SITE']
655        # The __config_site header should be non-empty. Otherwise it should
656        # have never been emitted by CMake.
657        assert len(feature_macros) > 0
658        # FIXME: This is a hack that should be fixed using module maps (or something)
659        # If modules are enabled then we have to lift all of the definitions
660        # in __config_site onto the command line.
661        modules_enabled = self.get_modules_enabled()
662        self.cxx.compile_flags += ['-Wno-macro-redefined']
663        # Transform each macro name into the feature name used in the tests.
664        # Ex. _LIBCPP_HAS_NO_THREADS -> libcpp-has-no-threads
665        for m in feature_macros:
666            if modules_enabled:
667                define = '-D%s' % m
668                if feature_macros[m]:
669                    define += '=%s' % (feature_macros[m])
670                self.cxx.compile_flags += [define]
671            if m == '_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS':
672                continue
673            if m == '_LIBCPP_ABI_VERSION':
674                self.config.available_features.add('libcpp-abi-version-v%s'
675                    % feature_macros[m])
676                continue
677            if m == '_LIBCPP_NO_VCRUNTIME':
678                self.config.available_features.add('libcpp-no-vcruntime')
679                continue
680            assert m.startswith('_LIBCPP_HAS_') or m.startswith('_LIBCPP_ABI_')
681            m = m.lower()[1:].replace('_', '-')
682            self.config.available_features.add(m)
683        return feature_macros
684
685
686
687    def configure_compile_flags_exceptions(self):
688        enable_exceptions = self.get_lit_bool('enable_exceptions', True)
689        if not enable_exceptions:
690            self.config.available_features.add('libcpp-no-exceptions')
691            self.cxx.compile_flags += ['-fno-exceptions']
692
693    def configure_compile_flags_rtti(self):
694        enable_rtti = self.get_lit_bool('enable_rtti', True)
695        if not enable_rtti:
696            self.config.available_features.add('libcpp-no-rtti')
697            self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI']
698
699    def configure_compile_flags_abi_version(self):
700        abi_version = self.get_lit_conf('abi_version', '').strip()
701        abi_unstable = self.get_lit_bool('abi_unstable')
702        # Only add the ABI version when it is non-default.
703        # FIXME(EricWF): Get the ABI version from the "__config_site".
704        if abi_version and abi_version != '1':
705          self.cxx.compile_flags += ['-D_LIBCPP_ABI_VERSION=' + abi_version]
706        if abi_unstable:
707          self.config.available_features.add('libcpp-abi-unstable')
708          self.cxx.compile_flags += ['-D_LIBCPP_ABI_UNSTABLE']
709
710    def configure_filesystem_compile_flags(self):
711        enable_fs = self.get_lit_bool('enable_filesystem', default=False)
712        if not enable_fs:
713            return
714        enable_experimental = self.get_lit_bool('enable_experimental', default=False)
715        if not enable_experimental:
716            self.lit_config.fatal(
717                'filesystem is enabled but libc++experimental.a is not.')
718        self.config.available_features.add('c++filesystem')
719        static_env = os.path.join(self.libcxx_src_root, 'test', 'std',
720                                  'experimental', 'filesystem', 'Inputs', 'static_test_env')
721        static_env = os.path.realpath(static_env)
722        assert os.path.isdir(static_env)
723        self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env]
724
725        dynamic_env = os.path.join(self.config.test_exec_root,
726                                   'filesystem', 'Output', 'dynamic_env')
727        dynamic_env = os.path.realpath(dynamic_env)
728        if not os.path.isdir(dynamic_env):
729            os.makedirs(dynamic_env)
730        self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env]
731        self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
732
733        dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
734                                      'filesystem_dynamic_test_helper.py')
735        assert os.path.isfile(dynamic_helper)
736
737        self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"'
738                                   % (sys.executable, dynamic_helper)]
739
740
741    def configure_link_flags(self):
742        no_default_flags = self.get_lit_bool('no_default_flags', False)
743        if not no_default_flags:
744            # Configure library path
745            self.configure_link_flags_cxx_library_path()
746            self.configure_link_flags_abi_library_path()
747
748            # Configure libraries
749            if self.cxx_stdlib_under_test == 'libc++':
750                self.cxx.link_flags += ['-nodefaultlibs']
751                # FIXME: Handle MSVCRT as part of the ABI library handling.
752                if self.is_windows:
753                    self.cxx.link_flags += ['-nostdlib']
754                self.configure_link_flags_cxx_library()
755                self.configure_link_flags_abi_library()
756                self.configure_extra_library_flags()
757            elif self.cxx_stdlib_under_test == 'libstdc++':
758                enable_fs = self.get_lit_bool('enable_filesystem',
759                                              default=False)
760                if enable_fs:
761                    self.config.available_features.add('c++experimental')
762                    self.cxx.link_flags += ['-lstdc++fs']
763                self.cxx.link_flags += ['-lm', '-pthread']
764            elif self.cxx_stdlib_under_test == 'msvc':
765                # FIXME: Correctly setup debug/release flags here.
766                pass
767            elif self.cxx_stdlib_under_test == 'cxx_default':
768                self.cxx.link_flags += ['-pthread']
769            else:
770                self.lit_config.fatal(
771                    'unsupported value for "use_stdlib_type": %s'
772                    %  use_stdlib_type)
773
774        link_flags_str = self.get_lit_conf('link_flags', '')
775        self.cxx.link_flags += shlex.split(link_flags_str)
776
777    def configure_link_flags_cxx_library_path(self):
778        if not self.use_system_cxx_lib:
779            if self.cxx_library_root:
780                self.cxx.link_flags += ['-L' + self.cxx_library_root]
781                if self.is_windows and self.link_shared:
782                    self.add_path(self.cxx.compile_env, self.cxx_library_root)
783            if self.cxx_runtime_root:
784                if not self.is_windows:
785                    self.cxx.link_flags += ['-Wl,-rpath,' +
786                                            self.cxx_runtime_root]
787                elif self.is_windows and self.link_shared:
788                    self.add_path(self.exec_env, self.cxx_runtime_root)
789        elif os.path.isdir(str(self.use_system_cxx_lib)):
790            self.cxx.link_flags += ['-L' + self.use_system_cxx_lib]
791            if not self.is_windows:
792                self.cxx.link_flags += ['-Wl,-rpath,' +
793                                        self.use_system_cxx_lib]
794            if self.is_windows and self.link_shared:
795                self.add_path(self.cxx.compile_env, self.use_system_cxx_lib)
796
797    def configure_link_flags_abi_library_path(self):
798        # Configure ABI library paths.
799        self.abi_library_root = self.get_lit_conf('abi_library_path')
800        if self.abi_library_root:
801            self.cxx.link_flags += ['-L' + self.abi_library_root]
802            if not self.is_windows:
803                self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root]
804            else:
805                self.add_path(self.exec_env, self.abi_library_root)
806
807    def configure_link_flags_cxx_library(self):
808        libcxx_experimental = self.get_lit_bool('enable_experimental', default=False)
809        if libcxx_experimental:
810            self.config.available_features.add('c++experimental')
811            self.cxx.link_flags += ['-lc++experimental']
812        if self.link_shared:
813            self.cxx.link_flags += ['-lc++']
814        else:
815            cxx_library_root = self.get_lit_conf('cxx_library_root')
816            if cxx_library_root:
817                libname = self.make_static_lib_name('c++')
818                abs_path = os.path.join(cxx_library_root, libname)
819                assert os.path.exists(abs_path) and \
820                       "static libc++ library does not exist"
821                self.cxx.link_flags += [abs_path]
822            else:
823                self.cxx.link_flags += ['-lc++']
824
825    def configure_link_flags_abi_library(self):
826        cxx_abi = self.get_lit_conf('cxx_abi', 'libcxxabi')
827        if cxx_abi == 'libstdc++':
828            self.cxx.link_flags += ['-lstdc++']
829        elif cxx_abi == 'libsupc++':
830            self.cxx.link_flags += ['-lsupc++']
831        elif cxx_abi == 'libcxxabi':
832            if self.target_info.allow_cxxabi_link():
833                libcxxabi_shared = self.get_lit_bool('libcxxabi_shared', default=True)
834                if libcxxabi_shared:
835                    self.cxx.link_flags += ['-lc++abi']
836                else:
837                    cxxabi_library_root = self.get_lit_conf('abi_library_path')
838                    if cxxabi_library_root:
839                        libname = self.make_static_lib_name('c++abi')
840                        abs_path = os.path.join(cxxabi_library_root, libname)
841                        self.cxx.link_flags += [abs_path]
842                    else:
843                        self.cxx.link_flags += ['-lc++abi']
844        elif cxx_abi == 'libcxxrt':
845            self.cxx.link_flags += ['-lcxxrt']
846        elif cxx_abi == 'vcruntime':
847            debug_suffix = 'd' if self.debug_build else ''
848            self.cxx.link_flags += ['-l%s%s' % (lib, debug_suffix) for lib in
849                                    ['vcruntime', 'ucrt', 'msvcrt']]
850        elif cxx_abi == 'none' or cxx_abi == 'default':
851            if self.is_windows:
852                debug_suffix = 'd' if self.debug_build else ''
853                self.cxx.link_flags += ['-lmsvcrt%s' % debug_suffix]
854        else:
855            self.lit_config.fatal(
856                'C++ ABI setting %s unsupported for tests' % cxx_abi)
857
858    def configure_extra_library_flags(self):
859        if self.get_lit_bool('cxx_ext_threads', default=False):
860            self.cxx.link_flags += ['-lc++external_threads']
861        self.target_info.add_cxx_link_flags(self.cxx.link_flags)
862
863    def configure_color_diagnostics(self):
864        use_color = self.get_lit_conf('color_diagnostics')
865        if use_color is None:
866            use_color = os.environ.get('LIBCXX_COLOR_DIAGNOSTICS')
867        if use_color is None:
868            return
869        if use_color != '':
870            self.lit_config.fatal('Invalid value for color_diagnostics "%s".'
871                                  % use_color)
872        color_flag = '-fdiagnostics-color=always'
873        # Check if the compiler supports the color diagnostics flag. Issue a
874        # warning if it does not since color diagnostics have been requested.
875        if not self.cxx.hasCompileFlag(color_flag):
876            self.lit_config.warning(
877                'color diagnostics have been requested but are not supported '
878                'by the compiler')
879        else:
880            self.cxx.flags += [color_flag]
881
882    def configure_debug_mode(self):
883        debug_level = self.get_lit_conf('debug_level', None)
884        if not debug_level:
885            return
886        if debug_level not in ['0', '1']:
887            self.lit_config.fatal('Invalid value for debug_level "%s".'
888                                  % debug_level)
889        self.cxx.compile_flags += ['-D_LIBCPP_DEBUG=%s' % debug_level]
890
891    def configure_warnings(self):
892        # Turn on warnings by default for Clang based compilers when C++ >= 11
893        default_enable_warnings = self.cxx.type in ['clang', 'apple-clang'] \
894            and len(self.config.available_features.intersection(
895                ['c++11', 'c++14', 'c++17', 'c++2a'])) != 0
896        enable_warnings = self.get_lit_bool('enable_warnings',
897                                            default_enable_warnings)
898        self.cxx.useWarnings(enable_warnings)
899        self.cxx.warning_flags += [
900            '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER',
901            '-Wall', '-Wextra', '-Werror'
902        ]
903        if self.cxx.hasWarningFlag('-Wuser-defined-warnings'):
904            self.cxx.warning_flags += ['-Wuser-defined-warnings']
905            self.config.available_features.add('diagnose-if-support')
906        self.cxx.addWarningFlagIfSupported('-Wshadow')
907        self.cxx.addWarningFlagIfSupported('-Wno-unused-command-line-argument')
908        self.cxx.addWarningFlagIfSupported('-Wno-attributes')
909        self.cxx.addWarningFlagIfSupported('-Wno-pessimizing-move')
910        self.cxx.addWarningFlagIfSupported('-Wno-c++11-extensions')
911        self.cxx.addWarningFlagIfSupported('-Wno-user-defined-literals')
912        self.cxx.addWarningFlagIfSupported('-Wno-noexcept-type')
913        self.cxx.addWarningFlagIfSupported('-Wno-aligned-allocation-unavailable')
914        # These warnings should be enabled in order to support the MSVC
915        # team using the test suite; They enable the warnings below and
916        # expect the test suite to be clean.
917        self.cxx.addWarningFlagIfSupported('-Wsign-compare')
918        self.cxx.addWarningFlagIfSupported('-Wunused-variable')
919        self.cxx.addWarningFlagIfSupported('-Wunused-parameter')
920        self.cxx.addWarningFlagIfSupported('-Wunreachable-code')
921        # FIXME: Enable the two warnings below.
922        self.cxx.addWarningFlagIfSupported('-Wno-conversion')
923        self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
924        # FIXME: Remove this warning once the min/max handling patch lands
925        # See https://reviews.llvm.org/D33080
926        self.cxx.addWarningFlagIfSupported('-Wno-#warnings')
927        std = self.get_lit_conf('std', None)
928        if std in ['c++98', 'c++03']:
929            # The '#define static_assert' provided by libc++ in C++03 mode
930            # causes an unused local typedef whenever it is used.
931            self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef')
932
933    def configure_sanitizer(self):
934        san = self.get_lit_conf('use_sanitizer', '').strip()
935        if san:
936            self.target_info.add_sanitizer_features(san, self.config.available_features)
937            # Search for llvm-symbolizer along the compiler path first
938            # and then along the PATH env variable.
939            symbolizer_search_paths = os.environ.get('PATH', '')
940            cxx_path = libcxx.util.which(self.cxx.path)
941            if cxx_path is not None:
942                symbolizer_search_paths = (
943                    os.path.dirname(cxx_path) +
944                    os.pathsep + symbolizer_search_paths)
945            llvm_symbolizer = libcxx.util.which('llvm-symbolizer',
946                                                symbolizer_search_paths)
947
948            def add_ubsan():
949                self.cxx.flags += ['-fsanitize=undefined',
950                                   '-fno-sanitize=vptr,function,float-divide-by-zero',
951                                   '-fno-sanitize-recover=all']
952                self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
953                self.config.available_features.add('ubsan')
954
955            # Setup the sanitizer compile flags
956            self.cxx.flags += ['-g', '-fno-omit-frame-pointer']
957            if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address':
958                self.cxx.flags += ['-fsanitize=address']
959                if llvm_symbolizer is not None:
960                    self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
961                # FIXME: Turn ODR violation back on after PR28391 is resolved
962                # https://bugs.llvm.org/show_bug.cgi?id=28391
963                self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
964                self.config.available_features.add('asan')
965                self.config.available_features.add('sanitizer-new-delete')
966                self.cxx.compile_flags += ['-O1']
967                if san == 'Address;Undefined' or san == 'Undefined;Address':
968                    add_ubsan()
969            elif san == 'Memory' or san == 'MemoryWithOrigins':
970                self.cxx.flags += ['-fsanitize=memory']
971                if san == 'MemoryWithOrigins':
972                    self.cxx.compile_flags += [
973                        '-fsanitize-memory-track-origins']
974                if llvm_symbolizer is not None:
975                    self.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
976                self.config.available_features.add('msan')
977                self.config.available_features.add('sanitizer-new-delete')
978                self.cxx.compile_flags += ['-O1']
979            elif san == 'Undefined':
980                add_ubsan()
981                self.cxx.compile_flags += ['-O2']
982            elif san == 'Thread':
983                self.cxx.flags += ['-fsanitize=thread']
984                self.config.available_features.add('tsan')
985                self.config.available_features.add('sanitizer-new-delete')
986            else:
987                self.lit_config.fatal('unsupported value for '
988                                      'use_sanitizer: {0}'.format(san))
989            san_lib = self.get_lit_conf('sanitizer_library')
990            if san_lib:
991                self.cxx.link_flags += [
992                    san_lib, '-Wl,-rpath,%s' % os.path.dirname(san_lib)]
993
994    def configure_coverage(self):
995        self.generate_coverage = self.get_lit_bool('generate_coverage', False)
996        if self.generate_coverage:
997            self.cxx.flags += ['-g', '--coverage']
998            self.cxx.compile_flags += ['-O0']
999
1000    def configure_coroutines(self):
1001        if self.cxx.hasCompileFlag('-fcoroutines-ts'):
1002            macros = self._dump_macros_verbose(flags=['-fcoroutines-ts'])
1003            if '__cpp_coroutines' not in macros:
1004                self.lit_config.warning('-fcoroutines-ts is supported but '
1005                    '__cpp_coroutines is not defined')
1006            # Consider coroutines supported only when the feature test macro
1007            # reflects a recent value.
1008            val = macros['__cpp_coroutines'].replace('L', '')
1009            if int(val) >= 201703:
1010                self.config.available_features.add('fcoroutines-ts')
1011
1012    def configure_modules(self):
1013        modules_flags = ['-fmodules']
1014        if platform.system() != 'Darwin':
1015            modules_flags += ['-Xclang', '-fmodules-local-submodule-visibility']
1016        supports_modules = self.cxx.hasCompileFlag(modules_flags)
1017        enable_modules = self.get_modules_enabled()
1018        if enable_modules and not supports_modules:
1019            self.lit_config.fatal(
1020                '-fmodules is enabled but not supported by the compiler')
1021        if not supports_modules:
1022            return
1023        self.config.available_features.add('modules-support')
1024        module_cache = os.path.join(self.config.test_exec_root,
1025                                   'modules.cache')
1026        module_cache = os.path.realpath(module_cache)
1027        if os.path.isdir(module_cache):
1028            shutil.rmtree(module_cache)
1029        os.makedirs(module_cache)
1030        self.cxx.modules_flags = modules_flags + \
1031            ['-fmodules-cache-path=' + module_cache]
1032        if enable_modules:
1033            self.config.available_features.add('-fmodules')
1034            self.cxx.useModules()
1035
1036    def configure_substitutions(self):
1037        sub = self.config.substitutions
1038        cxx_path = pipes.quote(self.cxx.path)
1039        # Configure compiler substitutions
1040        sub.append(('%cxx', cxx_path))
1041        sub.append(('%libcxx_src_root', self.libcxx_src_root))
1042        # Configure flags substitutions
1043        flags_str = ' '.join([pipes.quote(f) for f in self.cxx.flags])
1044        compile_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.compile_flags])
1045        link_flags_str = ' '.join([pipes.quote(f) for f in self.cxx.link_flags])
1046        all_flags = '%s %s %s' % (flags_str, compile_flags_str, link_flags_str)
1047        sub.append(('%flags', flags_str))
1048        sub.append(('%compile_flags', compile_flags_str))
1049        sub.append(('%link_flags', link_flags_str))
1050        sub.append(('%all_flags', all_flags))
1051        if self.cxx.isVerifySupported():
1052            verify_str = ' ' + ' '.join(self.cxx.verify_flags) + ' '
1053            sub.append(('%verify', verify_str))
1054        # Add compile and link shortcuts
1055        compile_str = (cxx_path + ' -o %t.o %s -c ' + flags_str
1056                       + ' ' + compile_flags_str)
1057        link_str = (cxx_path + ' -o %t.exe %t.o ' + flags_str + ' '
1058                    + link_flags_str)
1059        assert type(link_str) is str
1060        build_str = cxx_path + ' -o %t.exe %s ' + all_flags
1061        if self.cxx.use_modules:
1062            sub.append(('%compile_module', compile_str))
1063            sub.append(('%build_module', build_str))
1064        elif self.cxx.modules_flags is not None:
1065            modules_str = ' '.join(self.cxx.modules_flags) + ' '
1066            sub.append(('%compile_module', compile_str + ' ' + modules_str))
1067            sub.append(('%build_module', build_str + ' ' + modules_str))
1068        sub.append(('%compile', compile_str))
1069        sub.append(('%link', link_str))
1070        sub.append(('%build', build_str))
1071        # Configure exec prefix substitutions.
1072        # Configure run env substitution.
1073        sub.append(('%run', '%t.exe'))
1074        # Configure not program substitutions
1075        not_py = os.path.join(self.libcxx_src_root, 'utils', 'not.py')
1076        not_str = '%s %s ' % (pipes.quote(sys.executable), pipes.quote(not_py))
1077        sub.append(('not ', not_str))
1078
1079    def can_use_deployment(self):
1080        # Check if the host is on an Apple platform using clang.
1081        if not self.target_info.platform() == "darwin":
1082            return False
1083        if not self.target_info.is_host_macosx():
1084            return False
1085        if not self.cxx.type.endswith('clang'):
1086            return False
1087        return True
1088
1089    def configure_triple(self):
1090        # Get or infer the target triple.
1091        target_triple = self.get_lit_conf('target_triple')
1092        self.use_target = self.get_lit_bool('use_target', False)
1093        if self.use_target and target_triple:
1094            self.lit_config.warning('use_target is true but no triple is specified')
1095
1096        # Use deployment if possible.
1097        self.use_deployment = not self.use_target and self.can_use_deployment()
1098        if self.use_deployment:
1099            return
1100
1101        # Save the triple (and warn on Apple platforms).
1102        self.config.target_triple = target_triple
1103        if self.use_target and 'apple' in target_triple:
1104            self.lit_config.warning('consider using arch and platform instead'
1105                                    ' of target_triple on Apple platforms')
1106
1107        # If no target triple was given, try to infer it from the compiler
1108        # under test.
1109        if not self.config.target_triple:
1110            target_triple = self.cxx.getTriple()
1111            # Drop sub-major version components from the triple, because the
1112            # current XFAIL handling expects exact matches for feature checks.
1113            # Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14
1114            # The 5th group handles triples greater than 3 parts
1115            # (ex x86_64-pc-linux-gnu).
1116            target_triple = re.sub(r'([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)',
1117                                   r'\1-\2-\3\5', target_triple)
1118            # linux-gnu is needed in the triple to properly identify linuxes
1119            # that use GLIBC. Handle redhat and opensuse triples as special
1120            # cases and append the missing `-gnu` portion.
1121            if (target_triple.endswith('redhat-linux') or
1122                target_triple.endswith('suse-linux')):
1123                target_triple += '-gnu'
1124            self.config.target_triple = target_triple
1125            self.lit_config.note(
1126                "inferred target_triple as: %r" % self.config.target_triple)
1127
1128    def configure_deployment(self):
1129        assert not self.use_deployment is None
1130        assert not self.use_target is None
1131        if not self.use_deployment:
1132            # Warn about ignored parameters.
1133            if self.get_lit_conf('arch'):
1134                self.lit_config.warning('ignoring arch, using target_triple')
1135            if self.get_lit_conf('platform'):
1136                self.lit_config.warning('ignoring platform, using target_triple')
1137            return
1138
1139        assert not self.use_target
1140        assert self.target_info.is_host_macosx()
1141
1142        # Always specify deployment explicitly on Apple platforms, since
1143        # otherwise a platform is picked up from the SDK.  If the SDK version
1144        # doesn't match the system version, tests that use the system library
1145        # may fail spuriously.
1146        arch = self.get_lit_conf('arch')
1147        if not arch:
1148            arch = self.cxx.getTriple().split('-', 1)[0]
1149            self.lit_config.note("inferred arch as: %r" % arch)
1150
1151        inferred_platform, name, version = self.target_info.get_platform()
1152        if inferred_platform:
1153            self.lit_config.note("inferred platform as: %r" % (name + version))
1154        self.config.deployment = (arch, name, version)
1155
1156        # Set the target triple for use by lit.
1157        self.config.target_triple = arch + '-apple-' + name + version
1158        self.lit_config.note(
1159            "computed target_triple as: %r" % self.config.target_triple)
1160
1161    def configure_env(self):
1162        self.target_info.configure_env(self.exec_env)
1163
1164    def add_path(self, dest_env, new_path):
1165        if 'PATH' not in dest_env:
1166            dest_env['PATH'] = new_path
1167        else:
1168            split_char = ';' if self.is_windows else ':'
1169            dest_env['PATH'] = '%s%s%s' % (new_path, split_char,
1170                                           dest_env['PATH'])
1171