summaryrefslogtreecommitdiff
path: root/test/lit.common.cfg
blob: 5274b49c654fd43372d3323775cfcd172226a2af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# -*- Python -*-

# Configuration file for 'lit' test runner.
# This file contains common rules for various compiler-rt testsuites.
# It is mostly copied from lit.cfg used by Clang.
import os
import platform
import re
import subprocess
import json

import lit.formats
import lit.util

# Choose between lit's internal shell pipeline runner and a real shell.  If
# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
if use_lit_shell:
    # 0 is external, "" is default, and everything else is internal.
    execute_external = (use_lit_shell == "0")
else:
    # Otherwise we default to internal on Windows and external elsewhere, as
    # bash on Windows is usually very slow.
    execute_external = (not sys.platform in ['win32'])

# Setup test format.
config.test_format = lit.formats.ShTest(execute_external)
if execute_external:
  config.available_features.add('shell')

compiler_id = getattr(config, 'compiler_id', None)
if compiler_id == "Clang":
  if platform.system() != 'Windows':
    config.cxx_mode_flags = ["--driver-mode=g++"]
  else:
    config.cxx_mode_flags = []
  # We assume that sanitizers should provide good enough error
  # reports and stack traces even with minimal debug info.
  config.debug_info_flags = ["-gline-tables-only"]
  if platform.system() == 'Windows':
    # On Windows, use CodeView with column info instead of DWARF. Both VS and
    # windbg do not behave well when column info is enabled, but users have
    # requested it because it makes ASan reports more precise.
    config.debug_info_flags.append("-gcodeview")
    config.debug_info_flags.append("-gcolumn-info")
elif compiler_id == 'GNU':
  config.cxx_mode_flags = ["-x c++"]
  config.debug_info_flags = ["-g"]
else:
  lit_config.fatal("Unsupported compiler id: %r" % compiler_id)
# Add compiler ID to the list of available features.
config.available_features.add(compiler_id)

# If needed, add cflag for shadow scale.
if config.asan_shadow_scale != '':
  config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale

# BFD linker in 64-bit android toolchains fails to find libm.so, which is a
# transitive shared library dependency (via asan runtime).
if config.android:
  config.target_cflags += " -pie -fuse-ld=gold -Wl,--enable-new-dtags"

# Clear some environment variables that might affect Clang.
possibly_dangerous_env_vars = ['ASAN_OPTIONS', 'DFSAN_OPTIONS', 'LSAN_OPTIONS',
                               'MSAN_OPTIONS', 'UBSAN_OPTIONS',
                               'COMPILER_PATH', 'RC_DEBUG_OPTIONS',
                               'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH',
                               'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH',
                               'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH',
                               'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING',
                               'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
                               'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
                               'LIBCLANG_RESOURCE_USAGE',
                               'LIBCLANG_CODE_COMPLETION_LOGGING',
                               'XRAY_OPTIONS']
# Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
if platform.system() != 'Windows':
    possibly_dangerous_env_vars.append('INCLUDE')
for name in possibly_dangerous_env_vars:
  if name in config.environment:
    del config.environment[name]

# Tweak PATH to include llvm tools dir.
if (not config.llvm_tools_dir) or (not os.path.exists(config.llvm_tools_dir)):
  lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % config.llvm_tools_dir)
path = os.path.pathsep.join((config.llvm_tools_dir, config.environment['PATH']))
config.environment['PATH'] = path

# Help MSVS link.exe find the standard libraries.
# Make sure we only try to use it when targetting Windows.
if platform.system() == 'Windows' and '-win' in config.target_triple:
  config.environment['LIB'] = os.environ['LIB']

config.available_features.add(config.host_os.lower())

if re.match(r'^x86_64.*-linux', config.target_triple):
  config.available_features.add("x86_64-linux")

# Use ugly construction to explicitly prohibit "clang", "clang++" etc.
# in RUN lines.
config.substitutions.append(
    (' clang', """\n\n*** Do not use 'clangXXX' in tests,
     instead define '%clangXXX' substitution in lit config. ***\n\n""") )

# Allow tests to be executed on a simulator or remotely.
if config.emulator:
  config.substitutions.append( ('%run', config.emulator) )
  config.substitutions.append( ('%env ', "env ") )
  config.compile_wrapper = ""
elif config.host_os == 'Darwin' and config.apple_platform != "osx":
  # Darwin tests can be targetting macOS, a device or a simulator. All devices
  # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly,
  # all simulators are "iossim". See the table below.
  #
  # =========================================================================
  # Target             | Feature set
  # =========================================================================
  # macOS              | darwin
  # iOS device         | darwin, ios
  # iOS simulator      | darwin, ios, iossim
  # tvOS device        | darwin, ios, tvos
  # tvOS simulator     | darwin, ios, iossim, tvos, tvossim
  # watchOS device     | darwin, ios, watchos
  # watchOS simulator  | darwin, ios, iossim, watchos, watchossim
  # =========================================================================

  ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios"

  config.available_features.add('ios')
  if ios_or_iossim == "iossim":
    config.available_features.add('iossim')
  if config.apple_platform != "ios" and config.apple_platform != "iossim":
    config.available_features.add(config.apple_platform)

  ios_commands_dir = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands")

  device_id_env = "SANITIZER_" + ios_or_iossim.upper() + "_TEST_DEVICE_IDENTIFIER"
  run_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_run.py")
  env_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_env.py")
  compile_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_compile.py")
  prepare_script = os.path.join(ios_commands_dir, ios_or_iossim + "_prepare.py")

  if device_id_env in os.environ:
    config.environment[device_id_env] = os.environ[device_id_env]
  config.substitutions.append(('%run', run_wrapper))
  config.substitutions.append(('%env ', env_wrapper + " "))
  config.compile_wrapper = compile_wrapper

  prepare_output = subprocess.check_output([prepare_script, config.apple_platform, config.clang]).strip()
  if len(prepare_output) > 0: print(prepare_output)
  prepare_output_json = prepare_output.split("\n")[-1]
  prepare_output = json.loads(prepare_output_json)
  config.environment.update(prepare_output["env"])
elif config.android:
  config.available_features.add('android')
  compile_wrapper = os.path.join(config.compiler_rt_src_root, "test", "sanitizer_common", "android_commands", "android_compile.py") + " "
  config.compile_wrapper = compile_wrapper
  config.substitutions.append( ('%run', "") )
  config.substitutions.append( ('%env ', "env ") )
else:
  config.substitutions.append( ('%run', "") )
  config.substitutions.append( ('%env ', "env ") )
  config.compile_wrapper = ""

# Define CHECK-%os to check for OS-dependent output.
config.substitutions.append( ('CHECK-%os', ("CHECK-" + config.host_os)))

# Define %arch to check for architecture-dependent output.
config.substitutions.append( ('%arch', (config.host_arch)))

if config.host_os == 'Windows':
  # FIXME: This isn't quite right. Specifically, it will succeed if the program
  # does not crash but exits with a non-zero exit code. We ought to merge
  # KillTheDoctor and not --crash to make the latter more useful and remove the
  # need for this substitution.
  config.expect_crash = "not KillTheDoctor "
else:
  config.expect_crash = "not --crash "

config.substitutions.append( ("%expect_crash ", config.expect_crash) )

target_arch = getattr(config, 'target_arch', None)
if target_arch:
  config.available_features.add(target_arch + '-target-arch')
  if target_arch in ['x86_64', 'i386']:
    config.available_features.add('x86-target-arch')
  config.available_features.add(target_arch + '-' + config.host_os.lower())

compiler_rt_debug = getattr(config, 'compiler_rt_debug', False)
if not compiler_rt_debug:
  config.available_features.add('compiler-rt-optimized')

sanitizer_can_use_cxxabi = getattr(config, 'sanitizer_can_use_cxxabi', True)
if sanitizer_can_use_cxxabi:
  config.available_features.add('cxxabi')

if config.has_lld:
  config.available_features.add('lld-available')

if config.use_lld:
  config.available_features.add('lld')

if config.can_symbolize:
  config.available_features.add('can-symbolize')

lit.util.usePlatformSdkOnDarwin(config, lit_config)

if config.host_os == 'Darwin':
  osx_version = (10, 0, 0)
  try:
    osx_version = subprocess.check_output(["sw_vers", "-productVersion"])
    osx_version = tuple(int(x) for x in osx_version.split('.'))
    if len(osx_version) == 2: osx_version = (osx_version[0], osx_version[1], 0)
    if osx_version >= (10, 11):
      config.available_features.add('osx-autointerception')
      config.available_features.add('osx-ld64-live_support')
    else:
      # The ASAN initialization-bug.cc test should XFAIL on OS X systems
      # older than El Capitan. By marking the test as being unsupported with
      # this "feature", we can pass the test on newer OS X versions and other
      # platforms.
      config.available_features.add('osx-no-ld64-live_support')
  except:
    pass

  config.darwin_osx_version = osx_version

  # Detect x86_64h
  try:
    output = subprocess.check_output(["sysctl", "hw.cpusubtype"])
    output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)
    if output_re:
      cpu_subtype = int(output_re.group(1))
      if cpu_subtype == 8: # x86_64h
        config.available_features.add('x86_64h')
  except:
    pass

  config.substitutions.append( ("%macos_min_target_10_11", "-mmacosx-version-min=10.11") )

  isIOS = config.apple_platform != "osx"
  # rdar://problem/22207160
  config.substitutions.append( ("%darwin_min_target_with_full_runtime_arc_support",
      "-miphoneos-version-min=9.0" if isIOS else "-mmacosx-version-min=10.11") )

  # 32-bit iOS simulator is deprecated and removed in latest Xcode.
  if config.apple_platform == "iossim":
    if config.target_arch == "i386":
      config.unsupported = True
else:
  config.substitutions.append( ("%macos_min_target_10_11", "") )
  config.substitutions.append( ("%darwin_min_target_with_full_runtime_arc_support", "") )

if config.android:
  adb = os.environ.get('ADB', 'adb')
  try:
    android_api_level_str = subprocess.check_output([adb, "shell", "getprop", "ro.build.version.sdk"]).rstrip()
  except (subprocess.CalledProcessError, OSError):
    lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb)" % adb)
  try:
    android_api_level = int(android_api_level_str)
  except ValueError:
    lit_config.fatal("Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'" % (adb, android_api_level_str))
  if android_api_level >= 26:
    config.available_features.add('android-26')

sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov")
if os.path.exists(sancovcc_path):
  config.available_features.add("has_sancovcc")
  config.substitutions.append( ("%sancovcc ", sancovcc_path) )

def is_darwin_lto_supported():
  return os.path.exists(os.path.join(config.llvm_shlib_dir, 'libLTO.dylib'))

def is_linux_lto_supported():
  if config.use_lld:
    return True

  if not os.path.exists(os.path.join(config.llvm_shlib_dir, 'LLVMgold.so')):
    return False

  ld_cmd = subprocess.Popen([config.gold_executable, '--help'], stdout = subprocess.PIPE, env={'LANG': 'C'})
  ld_out = ld_cmd.stdout.read().decode()
  ld_cmd.wait()

  if not '-plugin' in ld_out:
    return False

  return True

def is_windows_lto_supported():
  return os.path.exists(os.path.join(config.llvm_tools_dir, 'lld-link.exe'))

if config.host_os == 'Darwin' and is_darwin_lto_supported():
  config.lto_supported = True
  config.lto_launch = ["env", "DYLD_LIBRARY_PATH=" + config.llvm_shlib_dir]
  config.lto_flags = []
elif config.host_os == 'Linux' and is_linux_lto_supported():
  config.lto_supported = True
  config.lto_launch = []
  if config.use_lld:
    config.lto_flags = ["-fuse-ld=lld"]
  else:
    config.lto_flags = ["-fuse-ld=gold"]
elif config.host_os == 'Windows' and is_windows_lto_supported():
  config.lto_supported = True
  config.lto_launch = []
  config.lto_flags = ["-fuse-ld=lld"]
else:
  config.lto_supported = False

if config.lto_supported:
  config.available_features.add('lto')
  if config.use_thinlto:
    config.available_features.add('thinlto')
    config.lto_flags += ["-flto=thin"]
  else:
    config.lto_flags += ["-flto"]
  if config.use_newpm:
    config.lto_flags += ["-fexperimental-new-pass-manager"]

# Ask llvm-config about assertion mode.
try:
  llvm_config_cmd = subprocess.Popen(
      [os.path.join(config.llvm_tools_dir, 'llvm-config'), '--assertion-mode'],
      stdout = subprocess.PIPE,
      env=config.environment)
except OSError:
  print("Could not find llvm-config in " + config.llvm_tools_dir)
  exit(42)

if re.search(r'ON', llvm_config_cmd.stdout.read().decode('ascii')):
  config.available_features.add('asserts')
llvm_config_cmd.wait()

# Sanitizer tests tend to be flaky on Windows due to PR24554, so add some
# retries. We don't do this on otther platforms because it's slower.
if platform.system() == 'Windows':
  config.test_retry_attempts = 2

# Only run up to 3 64-bit sanitized processes simultaneously on Darwin.
# Using more scales badly and hogs the system due to inefficient handling
# of large mmap'd regions (terabytes) by the kernel.
if platform.system() == 'Darwin':
  lit_config.parallelism_groups["darwin-64bit-sanitizer"] = 3

# The current implementation of the tools in sanitizer_common/ios_comamnds
# do not support parallel execution so force sequential execution of the
# tests on iOS devices.
if config.host_os == 'Darwin' and config.apple_platform != "osx" and not config.apple_platform.endswith("sim"):
  lit_config.warning("iOS device test cases being run sequentially")
  lit_config.parallelism_groups["darwin-ios-device-sanitizer"] = 1

# Multiple substitutions are necessary to support multiple shared objects used
# at once.
# Note that substitutions with numbers have to be defined first to avoid
# being subsumed by substitutions with smaller postfix.
for postfix in ["2", "1", ""]:
  if config.host_os == 'Darwin':
    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, '-Wl,-rpath,@executable_path/ %dynamiclib' + postfix) )
    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '-install_name @rpath/`basename %dynamiclib{}`'.format(postfix)) )
  elif config.host_os in ('FreeBSD', 'NetBSD', 'OpenBSD'):
    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )
  elif config.host_os == 'Linux':
    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )
  elif config.host_os == 'SunOS':
    config.substitutions.append( ("%ld_flags_rpath_exe" + postfix, "-Wl,-R\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix) )
    config.substitutions.append( ("%ld_flags_rpath_so" + postfix, '') )

  # Must be defined after the substitutions that use %dynamiclib.
  config.substitutions.append( ("%dynamiclib" + postfix, '%T/%xdynamiclib_filename' + postfix) )
  config.substitutions.append( ("%xdynamiclib_filename" + postfix, 'lib%xdynamiclib_namespec{}.so'.format(postfix)) )
  config.substitutions.append( ("%xdynamiclib_namespec", '%basename_t.dynamic') )

# Provide a substituion that can be used to tell Clang to use a static libstdc++.
# The substitution expands to nothing on non Linux platforms.
# FIXME: This should check the target OS, not the host OS.
if config.host_os == 'Linux':
  config.substitutions.append( ("%linux_static_libstdcplusplus", "-stdlib=libstdc++ -static-libstdc++") )
else:
  config.substitutions.append( ("%linux_static_libstdcplusplus", "") )

config.default_sanitizer_opts = []
if config.host_os == 'Darwin':
  # On Darwin, we default to `abort_on_error=1`, which would make tests run
  # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
  config.default_sanitizer_opts += ['abort_on_error=0']
  config.default_sanitizer_opts += ['log_to_syslog=0']
elif config.android:
  config.default_sanitizer_opts += ['abort_on_error=0']

# Allow tests to use REQUIRES=stable-runtime.  For use when you cannot use XFAIL
# because the test hangs or fails on one configuration and not the other.
if config.android or (config.target_arch not in ['arm', 'armhf', 'aarch64']):
  config.available_features.add('stable-runtime')

if config.asan_shadow_scale:
  config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale)
else:
  config.available_features.add("shadow-scale-3")

# Propagate the LLD/LTO into the clang config option, so nothing else is needed.
run_wrapper = []
target_cflags = [getattr(config, 'target_cflags', None)]
extra_cflags = []

if config.use_lto and config.lto_supported:
  run_wrapper += config.lto_launch
  extra_cflags += config.lto_flags
elif config.use_lto and (not config.lto_supported):
  config.unsupported = True

if config.use_lld and config.has_lld and not config.use_lto:
  extra_cflags += ["-fuse-ld=lld"]
elif config.use_lld and (not config.has_lld):
  config.unsupported = True

config.clang = " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " "
config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " "