1# -*- Python -*-
2
3# Configuration file for 'lit' test runner.
4# This file contains common rules for various compiler-rt testsuites.
5# It is mostly copied from lit.cfg.py used by Clang.
6import os
7import platform
8import re
9import subprocess
10import json
11
12import lit.formats
13import lit.util
14
15# Choose between lit's internal shell pipeline runner and a real shell.  If
16# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
17use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
18if use_lit_shell:
19    # 0 is external, "" is default, and everything else is internal.
20    execute_external = (use_lit_shell == "0")
21else:
22    # Otherwise we default to internal on Windows and external elsewhere, as
23    # bash on Windows is usually very slow.
24    execute_external = (not sys.platform in ['win32'])
25
26# Setup test format.
27config.test_format = lit.formats.ShTest(execute_external)
28if execute_external:
29  config.available_features.add('shell')
30
31compiler_id = getattr(config, 'compiler_id', None)
32if compiler_id == "Clang":
33  if platform.system() != 'Windows':
34    config.cxx_mode_flags = ["--driver-mode=g++"]
35  else:
36    config.cxx_mode_flags = []
37  # We assume that sanitizers should provide good enough error
38  # reports and stack traces even with minimal debug info.
39  config.debug_info_flags = ["-gline-tables-only"]
40  if platform.system() == 'Windows':
41    # On Windows, use CodeView with column info instead of DWARF. Both VS and
42    # windbg do not behave well when column info is enabled, but users have
43    # requested it because it makes ASan reports more precise.
44    config.debug_info_flags.append("-gcodeview")
45    config.debug_info_flags.append("-gcolumn-info")
46elif compiler_id == 'GNU':
47  config.cxx_mode_flags = ["-x c++"]
48  config.debug_info_flags = ["-g"]
49else:
50  lit_config.fatal("Unsupported compiler id: %r" % compiler_id)
51# Add compiler ID to the list of available features.
52config.available_features.add(compiler_id)
53
54# If needed, add cflag for shadow scale.
55if config.asan_shadow_scale != '':
56  config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale
57
58# BFD linker in 64-bit android toolchains fails to find libc++_shared.so, which
59# is a transitive shared library dependency (via asan runtime).
60if config.android:
61  # Prepend the flag so that it can be overridden.
62  config.target_cflags = "-pie -fuse-ld=gold " + config.target_cflags
63  if config.android_ndk_version < 19:
64    # With a new compiler and NDK < r19 this flag ends up meaning "link against
65    # libc++", but NDK r19 makes this mean "link against the stub libstdc++ that
66    # just contains a handful of ABI functions", which makes most C++ code fail
67    # to link. In r19 and later we just use the default which is libc++.
68    config.cxx_mode_flags.append('-stdlib=libstdc++')
69
70config.environment = dict(os.environ)
71
72# Clear some environment variables that might affect Clang.
73possibly_dangerous_env_vars = ['ASAN_OPTIONS', 'DFSAN_OPTIONS', 'LSAN_OPTIONS',
74                               'MSAN_OPTIONS', 'UBSAN_OPTIONS',
75                               'COMPILER_PATH', 'RC_DEBUG_OPTIONS',
76                               'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH',
77                               'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH',
78                               'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH',
79                               'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING',
80                               'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
81                               'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
82                               'LIBCLANG_RESOURCE_USAGE',
83                               'LIBCLANG_CODE_COMPLETION_LOGGING',
84                               'XRAY_OPTIONS']
85# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
86if platform.system() != 'Windows':
87    possibly_dangerous_env_vars.append('INCLUDE')
88for name in possibly_dangerous_env_vars:
89  if name in config.environment:
90    del config.environment[name]
91
92# Tweak PATH to include llvm tools dir.
93if (not config.llvm_tools_dir) or (not os.path.exists(config.llvm_tools_dir)):
94  lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % config.llvm_tools_dir)
95path = os.path.pathsep.join((config.llvm_tools_dir, config.environment['PATH']))
96config.environment['PATH'] = path
97
98# Help MSVS link.exe find the standard libraries.
99# Make sure we only try to use it when targetting Windows.
100if platform.system() == 'Windows' and '-win' in config.target_triple:
101  config.environment['LIB'] = os.environ['LIB']
102
103config.available_features.add(config.host_os.lower())
104
105if re.match(r'^x86_64.*-linux', config.target_triple):
106  config.available_features.add("x86_64-linux")
107
108config.available_features.add("host-byteorder-" + sys.byteorder + "-endian")
109
110if config.have_zlib == "1":
111  config.available_features.add("zlib")
112
113# Use ugly construction to explicitly prohibit "clang", "clang++" etc.
114# in RUN lines.
115config.substitutions.append(
116    (' clang', """\n\n*** Do not use 'clangXXX' in tests,
117     instead define '%clangXXX' substitution in lit config. ***\n\n""") )
118
119if config.host_os == 'NetBSD':
120  nb_commands_dir = os.path.join(config.compiler_rt_src_root,
121                                 "test", "sanitizer_common", "netbsd_commands")
122  config.netbsd_noaslr_prefix = ('sh ' +
123                                 os.path.join(nb_commands_dir, 'run_noaslr.sh'))
124  config.netbsd_nomprotect_prefix = ('sh ' +
125                                     os.path.join(nb_commands_dir,
126                                                  'run_nomprotect.sh'))
127  config.substitutions.append( ('%run_nomprotect',
128                                config.netbsd_nomprotect_prefix) )
129else:
130  config.substitutions.append( ('%run_nomprotect', '%run') )
131
132# Allow tests to be executed on a simulator or remotely.
133if config.emulator:
134  config.substitutions.append( ('%run', config.emulator) )
135  config.substitutions.append( ('%env ', "env ") )
136  # TODO: Implement `%device_rm` to perform removal of files in the emulator.
137  # For now just make it a no-op.
138  lit_config.warning('%device_rm is not implemented')
139  config.substitutions.append( ('%device_rm', 'echo ') )
140  config.compile_wrapper = ""
141elif config.host_os == 'Darwin' and config.apple_platform != "osx":
142  # Darwin tests can be targetting macOS, a device or a simulator. All devices
143  # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly,
144  # all simulators are "iossim". See the table below.
145  #
146  # =========================================================================
147  # Target             | Feature set
148  # =========================================================================
149  # macOS              | darwin
150  # iOS device         | darwin, ios
151  # iOS simulator      | darwin, ios, iossim
152  # tvOS device        | darwin, ios, tvos
153  # tvOS simulator     | darwin, ios, iossim, tvos, tvossim
154  # watchOS device     | darwin, ios, watchos
155  # watchOS simulator  | darwin, ios, iossim, watchos, watchossim
156  # =========================================================================
157
158  ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios"
159
160  config.available_features.add('ios')
161  device_id_env = "SANITIZER_" + ios_or_iossim.upper() + "_TEST_DEVICE_IDENTIFIER"
162  if ios_or_iossim == "iossim":
163    config.available_features.add('iossim')
164    if device_id_env not in os.environ:
165      lit_config.fatal(
166        '{} must be set in the environment when running iossim tests'.format(
167          device_id_env))
168  if config.apple_platform != "ios" and config.apple_platform != "iossim":
169    config.available_features.add(config.apple_platform)
170
171  ios_commands_dir = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands")
172
173  run_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_run.py")
174  env_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_env.py")
175  compile_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_compile.py")
176  prepare_script = os.path.join(ios_commands_dir, ios_or_iossim + "_prepare.py")
177
178  if device_id_env in os.environ:
179    config.environment[device_id_env] = os.environ[device_id_env]
180  config.substitutions.append(('%run', run_wrapper))
181  config.substitutions.append(('%env ', env_wrapper + " "))
182  # Current implementation of %device_rm uses the run_wrapper to do
183  # the work.
184  config.substitutions.append(('%device_rm', '{} rm '.format(run_wrapper)))
185  config.compile_wrapper = compile_wrapper
186
187  try:
188    prepare_output = subprocess.check_output([prepare_script, config.apple_platform, config.clang]).decode().strip()
189  except subprocess.CalledProcessError as e:
190    print("Command failed:")
191    print(e.output)
192    raise e
193  if len(prepare_output) > 0: print(prepare_output)
194  prepare_output_json = prepare_output.split("\n")[-1]
195  prepare_output = json.loads(prepare_output_json)
196  config.environment.update(prepare_output["env"])
197elif config.android:
198  config.available_features.add('android')
199  compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " "
200  config.compile_wrapper = compile_wrapper
201  config.substitutions.append( ('%run', "") )
202  config.substitutions.append( ('%env ', "env ") )
203  # TODO: Implement `%device_rm` to perform removal of files on a device.  For
204  # now just make it a no-op.
205  lit_config.warning('%device_rm is not implemented')
206  config.substitutions.append( ('%device_rm', 'echo ') )
207else:
208  config.substitutions.append( ('%run', "") )
209  config.substitutions.append( ('%env ', "env ") )
210  # When running locally %device_rm is a no-op.
211  config.substitutions.append( ('%device_rm', 'echo ') )
212  config.compile_wrapper = ""
213
214# Define CHECK-%os to check for OS-dependent output.
215config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))
216
217# Define %arch to check for architecture-dependent output.
218config.substitutions.append( ('%arch', (config.host_arch)))
219
220if config.host_os == 'Windows':
221  # FIXME: This isn't quite right. Specifically, it will succeed if the program
222  # does not crash but exits with a non-zero exit code. We ought to merge
223  # KillTheDoctor and not --crash to make the latter more useful and remove the
224  # need for this substitution.
225  config.expect_crash = "not KillTheDoctor "
226else:
227  config.expect_crash = "not --crash "
228
229config.substitutions.append( ("%expect_crash ", config.expect_crash) )
230
231target_arch = getattr(config, 'target_arch', None)
232if target_arch:
233  config.available_features.add(target_arch + '-target-arch')
234  if target_arch in ['x86_64', 'i386']:
235    config.available_features.add('x86-target-arch')
236  config.available_features.add(target_arch + '-' + config.host_os.lower())
237
238compiler_rt_debug = getattr(config, 'compiler_rt_debug', False)
239if not compiler_rt_debug:
240  config.available_features.add('compiler-rt-optimized')
241
242libdispatch = getattr(config, 'compiler_rt_intercept_libdispatch', False)
243if libdispatch:
244  config.available_features.add('libdispatch')
245
246sanitizer_can_use_cxxabi = getattr(config, 'sanitizer_can_use_cxxabi', True)
247if sanitizer_can_use_cxxabi:
248  config.available_features.add('cxxabi')
249
250if config.has_lld:
251  config.available_features.add('lld-available')
252
253if config.use_lld:
254  config.available_features.add('lld')
255
256if config.can_symbolize:
257  config.available_features.add('can-symbolize')
258
259if config.gwp_asan:
260  config.available_features.add('gwp_asan')
261
262lit.util.usePlatformSdkOnDarwin(config, lit_config)
263
264# Maps a lit substitution name for the minimum target OS flag
265# to the macOS version that first contained the relevant feature.
266darwin_min_deployment_target_substitutions = {
267  '%macos_min_target_10_11': '10.11',
268  # rdar://problem/22207160
269  '%darwin_min_target_with_full_runtime_arc_support': '10.11',
270  '%darwin_min_target_with_tls_support': '10.12',
271}
272
273if config.host_os == 'Darwin':
274  def get_apple_platform_version_aligned_with(macos_version, apple_platform):
275    """
276      Given a macOS version (`macos_version`) returns the corresponding version for
277      the specified Apple platform if it exists.
278
279      `macos_version` - The macOS version as a string.
280      `apple_platform` - The Apple platform name as a string.
281
282      Returns the corresponding version as a string if it exists, otherwise
283      `None` is returned.
284    """
285    m = re.match(r'^10\.(?P<min>\d+)(\.(?P<patch>\d+))?$', macos_version)
286    if not m:
287      raise Exception('Could not parse macOS version: "{}"'.format(macos_version))
288    ver_min = int(m.group('min'))
289    ver_patch = m.group('patch')
290    if ver_patch:
291      ver_patch = int(ver_patch)
292    else:
293      ver_patch = 0
294    result_str = ''
295    if apple_platform == 'osx':
296      # Drop patch for now.
297      result_str = '10.{}'.format(ver_min)
298    elif apple_platform.startswith('ios') or apple_platform.startswith('tvos'):
299      result_maj = ver_min - 2
300      if result_maj < 1:
301        return None
302      result_str = '{}.{}'.format(result_maj, ver_patch)
303    elif apple_platform.startswith('watch'):
304      result_maj = ver_min - 9
305      if result_maj < 1:
306        return None
307      result_str = '{}.{}'.format(result_maj, ver_patch)
308    else:
309      raise Exception('Unsuported apple platform "{}"'.format(apple_platform))
310    return result_str
311
312  osx_version = (10, 0, 0)
313  try:
314    osx_version = subprocess.check_output(["sw_vers", "-productVersion"],
315                                          universal_newlines=True)
316    osx_version = tuple(int(x) for x in osx_version.split('.'))
317    if len(osx_version) == 2: osx_version = (osx_version[0], osx_version[1], 0)
318    if osx_version >= (10, 11):
319      config.available_features.add('osx-autointerception')
320      config.available_features.add('osx-ld64-live_support')
321    else:
322      # The ASAN initialization-bug.cpp test should XFAIL on OS X systems
323      # older than El Capitan. By marking the test as being unsupported with
324      # this "feature", we can pass the test on newer OS X versions and other
325      # platforms.
326      config.available_features.add('osx-no-ld64-live_support')
327  except subprocess.CalledProcessError:
328    pass
329
330  config.darwin_osx_version = osx_version
331
332  # Detect x86_64h
333  try:
334    output = subprocess.check_output(["sysctl", "hw.cpusubtype"])
335    output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)
336    if output_re:
337      cpu_subtype = int(output_re.group(1))
338      if cpu_subtype == 8: # x86_64h
339        config.available_features.add('x86_64h')
340  except:
341    pass
342
343  def get_apple_min_deploy_target_flag_aligned_with_osx(version):
344    min_os_aligned_with_osx_v = get_apple_platform_version_aligned_with(version, config.apple_platform)
345    min_os_aligned_with_osx_v_flag = ''
346    if min_os_aligned_with_osx_v:
347      min_os_aligned_with_osx_v_flag = '{flag}={version}'.format(
348        flag=config.apple_platform_min_deployment_target_flag,
349        version=min_os_aligned_with_osx_v)
350    else:
351      lit_config.warning('Could not find a version of {} that corresponds with macOS {}'.format(
352        config.apple_platform,
353        version))
354    return min_os_aligned_with_osx_v_flag
355
356  for substitution, osx_version in darwin_min_deployment_target_substitutions.items():
357    config.substitutions.append( (substitution, get_apple_min_deploy_target_flag_aligned_with_osx(osx_version)) )
358
359  # 32-bit iOS simulator is deprecated and removed in latest Xcode.
360  if config.apple_platform == "iossim":
361    if config.target_arch == "i386":
362      config.unsupported = True
363else:
364  for substitution in darwin_min_deployment_target_substitutions.keys():
365    config.substitutions.append( (substitution, "") )
366
367if config.android:
368  env = os.environ.copy()
369  if config.android_serial:
370    env['ANDROID_SERIAL'] = config.android_serial
371    config.environment['ANDROID_SERIAL'] = config.android_serial
372
373  adb = os.environ.get('ADB', 'adb')
374  try:
375    android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"], env=env).rstrip()
376  except (subprocess.CalledProcessError, OSError):
377    lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb)
378  try:
379    android_api_level = int(android_api_level_str)
380  except ValueError:
381    lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str))
382  if android_api_level >= 26:
383    config.available_features.add('android-26')
384  if android_api_level >= 28:
385    config.available_features.add('android-28')
386
387  # Prepare the device.
388  android_tmpdir = '/data/local/tmp/Output'
389  subprocess.check_call([adb, "shell", "mkdir", "-p", android_tmpdir], env=env)
390  for file in config.android_files_to_push:
391    subprocess.check_call([adb, "push", file, android_tmpdir], env=env)
392
393if config.host_os == 'Linux':
394  # detect whether we are using glibc, and which version
395  # NB: 'ldd' is just one of the tools commonly installed as part of glibc
396  ldd_ver_cmd = subprocess.Popen(['ldd', '--version'],
397                                 stdout=subprocess.PIPE,
398                                 env={'LANG': 'C'})
399  sout, _ = ldd_ver_cmd.communicate()
400  ver_line = sout.splitlines()[0]
401  if ver_line.startswith(b"ldd "):
402    from distutils.version import LooseVersion
403    ver = LooseVersion(ver_line.split()[-1].decode())
404    # 2.27 introduced some incompatibilities
405    if ver >= LooseVersion("2.27"):
406      config.available_features.add("glibc-2.27")
407
408sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov")
409if os.path.exists(sancovcc_path):
410  config.available_features.add("has_sancovcc")
411  config.substitutions.append( ("%sancovcc ", sancovcc_path) )
412
413def is_darwin_lto_supported():
414  return os.path.exists(os.path.join(config.llvm_shlib_dir, 'libLTO.dylib'))
415
416def is_linux_lto_supported():
417  if config.use_lld:
418    return True
419
420  if not os.path.exists(os.path.join(config.llvm_shlib_dir, 'LLVMgold.so')):
421    return False
422
423  ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE, env={'LANG': 'C'})
424  ld_out = ld_cmd.stdout.read().decode()
425  ld_cmd.wait()
426
427  if not '-plugin' in ld_out:
428    return False
429
430  return True
431
432def is_windows_lto_supported():
433  return os.path.exists(os.path.join(config.llvm_tools_dir, 'lld-link.exe'))
434
435if config.host_os == 'Darwin' and is_darwin_lto_supported():
436  config.lto_supported = True
437  config.lto_launch = ["env", "DYLD_LIBRARY_PATH=" + config.llvm_shlib_dir]
438  config.lto_flags = []
439elif config.host_os in ['Linux', 'FreeBSD', 'NetBSD'] and is_linux_lto_supported():
440  config.lto_supported = True
441  config.lto_launch = []
442  if config.use_lld:
443    config.lto_flags = ["-fuse-ld=lld"]
444  else:
445    config.lto_flags = ["-fuse-ld=gold"]
446elif config.host_os == 'Windows' and is_windows_lto_supported():
447  config.lto_supported = True
448  config.lto_launch = []
449  config.lto_flags = ["-fuse-ld=lld"]
450else:
451  config.lto_supported = False
452
453if config.lto_supported:
454  config.available_features.add('lto')
455  if config.use_thinlto:
456    config.available_features.add('thinlto')
457    config.lto_flags += ["-flto=thin"]
458  else:
459    config.lto_flags += ["-flto"]
460  if config.use_newpm:
461    config.lto_flags += ["-fexperimental-new-pass-manager"]
462
463if config.have_rpc_xdr_h:
464  config.available_features.add('sunrpc')
465
466# Ask llvm-config about assertion mode.
467try:
468  llvm_config_cmd = subprocess.Popen(
469      [os.path.join(config.llvm_tools_dir, 'llvm-config'), '--assertion-mode'],
470      stdout = subprocess.PIPE,
471      env=config.environment)
472except OSError as e:
473  print("Could not launch llvm-config in " + config.llvm_tools_dir)
474  print("    Failed with error #{0}: {1}".format(e.errno, e.strerror))
475  exit(42)
476
477if re.search(r'ON', llvm_config_cmd.stdout.read().decode('ascii')):
478  config.available_features.add('asserts')
479llvm_config_cmd.wait()
480
481# Sanitizer tests tend to be flaky on Windows due to PR24554, so add some
482# retries. We don't do this on otther platforms because it's slower.
483if platform.system() == 'Windows':
484  config.test_retry_attempts = 2
485
486# No throttling on non-Darwin platforms.
487lit_config.parallelism_groups['shadow-memory'] = None
488
489if platform.system() == 'Darwin':
490  ios_device = config.apple_platform != 'osx' and not config.apple_platform.endswith('sim')
491  # Force sequential execution when running tests on iOS devices.
492  if ios_device:
493    lit_config.warning('Forcing sequential execution for iOS device tests')
494    lit_config.parallelism_groups['ios-device'] = 1
495    config.parallelism_group = 'ios-device'
496
497  # Only run up to 3 processes that require shadow memory simultaneously on
498  # 64-bit Darwin. Using more scales badly and hogs the system due to
499  # inefficient handling of large mmap'd regions (terabytes) by the kernel.
500  elif config.target_arch in ['x86_64', 'x86_64h']:
501    lit_config.warning('Throttling sanitizer tests that require shadow memory on Darwin 64bit')
502    lit_config.parallelism_groups['shadow-memory'] = 3
503
504# Multiple substitutions are necessary to support multiple shared objects used
505# at once.
506# Note that substitutions with numbers have to be defined first to avoid
507# being subsumed by substitutions with smaller postfix.
508for postfix in ["2", "1", ""]:
509  if config.host_os == 'Darwin':
510    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, '-Wl,-rpath,@executable_path/ %dynamiclib' + postfix) )
511    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '-install_name @rpath/`basename %dynamiclib{}`'.format(postfix)) )
512  elif config.host_os in ('FreeBSD', 'NetBSD', 'OpenBSD'):
513    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
514    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )
515  elif config.host_os == 'Linux':
516    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
517    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )
518  elif config.host_os == 'SunOS':
519    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-R\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
520    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )
521
522  # Must be defined after the substitutions that use %dynamiclib.
523  config.substitutions.append( ("%dynamiclib" + postfix, '%T/%xdynamiclib_filename' + postfix) )
524  config.substitutions.append( ("%xdynamiclib_filename" + postfix, 'lib%xdynamiclib_namespec{}.so'.format(postfix)) )
525  config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') )
526
527# Provide a substituion that can be used to tell Clang to use a static libstdc++.
528# The substitution expands to nothing on non Linux platforms.
529# FIXME: This should check the target OS, not the host OS.
530if config.host_os == 'Linux':
531  config.substitutions.append( ("%linux_static_libstdcplusplus", "-stdlib=libstdc++ -static-libstdc++") )
532else:
533  config.substitutions.append( ("%linux_static_libstdcplusplus", "") )
534
535config.default_sanitizer_opts = []
536if config.host_os == 'Darwin':
537  # On Darwin, we default to `abort_on_error=1`, which would make tests run
538  # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
539  config.default_sanitizer_opts += ['abort_on_error=0']
540  config.default_sanitizer_opts += ['log_to_syslog=0']
541  if lit.util.which('log'):
542    # Querying the log can only done by a privileged user so
543    # so check if we can query the log.
544    exit_code = -1
545    with open('/dev/null', 'r') as f:
546      # Run a `log show` command the should finish fairly quickly and produce very little output.
547      exit_code = subprocess.call(['log', 'show', '--last', '1m', '--predicate', '1 == 0'], stdout=f, stderr=f)
548    if exit_code == 0:
549      config.available_features.add('darwin_log_cmd')
550    else:
551      lit_config.warning('log command found but cannot queried')
552  else:
553    lit_config.warning('log command not found. Some tests will be skipped.')
554elif config.android:
555  config.default_sanitizer_opts += ['abort_on_error=0']
556
557# Allow tests to use REQUIRES=stable-runtime.  For use when you cannot use XFAIL
558# because the test hangs or fails on one configuration and not the other.
559if config.android or (config.target_arch not in ['arm', 'armhf', 'aarch64']):
560  config.available_features.add('stable-runtime')
561
562if config.asan_shadow_scale:
563  config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale)
564else:
565  config.available_features.add("shadow-scale-3")
566
567if config.expensive_checks:
568  config.available_features.add("expensive_checks")
569
570# Propagate the LLD/LTO into the clang config option, so nothing else is needed.
571run_wrapper = []
572target_cflags = [getattr(config, 'target_cflags', None)]
573extra_cflags = []
574
575if config.use_lto and config.lto_supported:
576  run_wrapper += config.lto_launch
577  extra_cflags += config.lto_flags
578elif config.use_lto and (not config.lto_supported):
579  config.unsupported = True
580
581if config.use_lld and config.has_lld and not config.use_lto:
582  extra_cflags += ["-fuse-ld=lld"]
583elif config.use_lld and (not config.has_lld):
584  config.unsupported = True
585
586config.clang = " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " "
587config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " "
588