[lldb] Fix loading UUIDs from ELF headers. (#117028)
[llvm-project.git] / compiler-rt / test / lit.common.cfg.py
blobc6f27748ccb76e962ddb9af25ac7e605fb121fbf
1 # -*- Python -*-
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.
6 import os
7 import platform
8 import re
9 import shlex
10 import subprocess
11 import json
13 import lit.formats
14 import lit.util
17 def get_path_from_clang(args, allow_failure):
18 clang_cmd = [
19 config.clang.strip(),
20 f"--target={config.target_triple}",
21 *args,
23 path = None
24 try:
25 result = subprocess.run(
26 clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True
28 path = result.stdout.decode().strip()
29 except subprocess.CalledProcessError as e:
30 msg = f"Failed to run {clang_cmd}\nrc:{e.returncode}\nstdout:{e.stdout}\ne.stderr{e.stderr}"
31 if allow_failure:
32 lit_config.warning(msg)
33 else:
34 lit_config.fatal(msg)
35 return path, clang_cmd
38 def find_compiler_libdir():
39 """
40 Returns the path to library resource directory used
41 by the compiler.
42 """
43 if config.compiler_id != "Clang":
44 lit_config.warning(
45 f"Determining compiler's runtime directory is not supported for {config.compiler_id}"
47 # TODO: Support other compilers.
48 return None
50 # Try using `-print-runtime-dir`. This is only supported by very new versions of Clang.
51 # so allow failure here.
52 runtime_dir, clang_cmd = get_path_from_clang(
53 shlex.split(config.target_cflags) + ["-print-runtime-dir"], allow_failure=True
55 if runtime_dir:
56 if os.path.exists(runtime_dir):
57 return os.path.realpath(runtime_dir)
58 # TODO(dliew): This should be a fatal error but it seems to trip the `llvm-clang-win-x-aarch64`
59 # bot which is likely misconfigured
60 lit_config.warning(
61 f'Path reported by clang does not exist: "{runtime_dir}". '
62 f"This path was found by running {clang_cmd}."
64 return None
66 # Fall back for older AppleClang that doesn't support `-print-runtime-dir`
67 # Note `-print-file-name=<path to compiler-rt lib>` was broken for Apple
68 # platforms so we can't use that approach here (see https://reviews.llvm.org/D101682).
69 if config.host_os == "Darwin":
70 lib_dir, _ = get_path_from_clang(["-print-file-name=lib"], allow_failure=False)
71 runtime_dir = os.path.join(lib_dir, "darwin")
72 if not os.path.exists(runtime_dir):
73 lit_config.fatal(f"Path reported by clang does not exist: {runtime_dir}")
74 return os.path.realpath(runtime_dir)
76 lit_config.warning("Failed to determine compiler's runtime directory")
77 return None
80 def push_dynamic_library_lookup_path(config, new_path):
81 if platform.system() == "Windows":
82 dynamic_library_lookup_var = "PATH"
83 elif platform.system() == "Darwin":
84 dynamic_library_lookup_var = "DYLD_LIBRARY_PATH"
85 elif platform.system() == "Haiku":
86 dynamic_library_lookup_var = "LIBRARY_PATH"
87 else:
88 dynamic_library_lookup_var = "LD_LIBRARY_PATH"
90 new_ld_library_path = os.path.pathsep.join(
91 (new_path, config.environment.get(dynamic_library_lookup_var, ""))
93 config.environment[dynamic_library_lookup_var] = new_ld_library_path
95 if platform.system() == "FreeBSD":
96 dynamic_library_lookup_var = "LD_32_LIBRARY_PATH"
97 new_ld_32_library_path = os.path.pathsep.join(
98 (new_path, config.environment.get(dynamic_library_lookup_var, ""))
100 config.environment[dynamic_library_lookup_var] = new_ld_32_library_path
102 if platform.system() == "SunOS":
103 dynamic_library_lookup_var = "LD_LIBRARY_PATH_32"
104 new_ld_library_path_32 = os.path.pathsep.join(
105 (new_path, config.environment.get(dynamic_library_lookup_var, ""))
107 config.environment[dynamic_library_lookup_var] = new_ld_library_path_32
109 dynamic_library_lookup_var = "LD_LIBRARY_PATH_64"
110 new_ld_library_path_64 = os.path.pathsep.join(
111 (new_path, config.environment.get(dynamic_library_lookup_var, ""))
113 config.environment[dynamic_library_lookup_var] = new_ld_library_path_64
116 # Choose between lit's internal shell pipeline runner and a real shell. If
117 # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
118 use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
119 if use_lit_shell:
120 # 0 is external, "" is default, and everything else is internal.
121 execute_external = use_lit_shell == "0"
122 else:
123 # Otherwise we default to internal on Windows and external elsewhere, as
124 # bash on Windows is usually very slow.
125 execute_external = not sys.platform in ["win32"]
127 # Allow expanding substitutions that are based on other substitutions
128 config.recursiveExpansionLimit = 10
130 # Setup test format.
131 config.test_format = lit.formats.ShTest(execute_external)
132 if execute_external:
133 config.available_features.add("shell")
135 target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple))
136 target_is_windows = bool(re.match(r".*-windows.*$", config.target_triple))
138 compiler_id = getattr(config, "compiler_id", None)
139 if compiler_id == "Clang":
140 if not (platform.system() == "Windows" and target_is_msvc):
141 config.cxx_mode_flags = ["--driver-mode=g++"]
142 else:
143 config.cxx_mode_flags = []
144 # We assume that sanitizers should provide good enough error
145 # reports and stack traces even with minimal debug info.
146 config.debug_info_flags = ["-gline-tables-only"]
147 if platform.system() == "Windows" and target_is_msvc:
148 # On MSVC, use CodeView with column info instead of DWARF. Both VS and
149 # windbg do not behave well when column info is enabled, but users have
150 # requested it because it makes ASan reports more precise.
151 config.debug_info_flags.append("-gcodeview")
152 config.debug_info_flags.append("-gcolumn-info")
153 elif compiler_id == "MSVC":
154 config.debug_info_flags = ["/Z7"]
155 config.cxx_mode_flags = []
156 elif compiler_id == "GNU":
157 config.cxx_mode_flags = ["-x c++"]
158 config.debug_info_flags = ["-g"]
159 else:
160 lit_config.fatal("Unsupported compiler id: %r" % compiler_id)
161 # Add compiler ID to the list of available features.
162 config.available_features.add(compiler_id)
164 # When LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on, the initial value of
165 # config.compiler_rt_libdir (COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR) has the
166 # host triple as the trailing path component. The value is incorrect for 32-bit
167 # tests on 64-bit hosts and vice versa. Adjust config.compiler_rt_libdir
168 # accordingly.
169 if config.enable_per_target_runtime_dir:
170 if config.target_arch == "i386":
171 config.compiler_rt_libdir = re.sub(
172 r"/x86_64(?=-[^/]+$)", "/i386", config.compiler_rt_libdir
174 elif config.target_arch == "x86_64":
175 config.compiler_rt_libdir = re.sub(
176 r"/i386(?=-[^/]+$)", "/x86_64", config.compiler_rt_libdir
178 if config.target_arch == "sparc":
179 config.compiler_rt_libdir = re.sub(
180 r"/sparcv9(?=-[^/]+$)", "/sparc", config.compiler_rt_libdir
182 elif config.target_arch == "sparcv9":
183 config.compiler_rt_libdir = re.sub(
184 r"/sparc(?=-[^/]+$)", "/sparcv9", config.compiler_rt_libdir
187 # Check if the test compiler resource dir matches the local build directory
188 # (which happens with -DLLVM_ENABLE_PROJECTS=clang;compiler-rt) or if we are
189 # using an installed clang to test compiler-rt standalone. In the latter case
190 # we may need to override the resource dir to match the path of the just-built
191 # compiler-rt libraries.
192 test_cc_resource_dir, _ = get_path_from_clang(
193 shlex.split(config.target_cflags) + ["-print-resource-dir"], allow_failure=True
195 # Normalize the path for comparison
196 if test_cc_resource_dir is not None:
197 test_cc_resource_dir = os.path.realpath(test_cc_resource_dir)
198 if lit_config.debug:
199 lit_config.note(f"Resource dir for {config.clang} is {test_cc_resource_dir}")
200 local_build_resource_dir = os.path.realpath(config.compiler_rt_output_dir)
201 if test_cc_resource_dir != local_build_resource_dir and config.test_standalone_build_libs:
202 if config.compiler_id == "Clang":
203 if lit_config.debug:
204 lit_config.note(
205 f"Overriding test compiler resource dir to use "
206 f'libraries in "{config.compiler_rt_libdir}"'
208 # Ensure that we use the just-built static libraries when linking by
209 # overriding the Clang resource directory. Additionally, we want to use
210 # the builtin headers shipped with clang (e.g. stdint.h), so we
211 # explicitly add this as an include path (since the headers are not
212 # going to be in the current compiler-rt build directory).
213 # We also tell the linker to add an RPATH entry for the local library
214 # directory so that the just-built shared libraries are used.
215 config.target_cflags += f" -nobuiltininc"
216 config.target_cflags += f" -I{config.compiler_rt_src_root}/include"
217 config.target_cflags += f" -idirafter {test_cc_resource_dir}/include"
218 config.target_cflags += f" -resource-dir={config.compiler_rt_output_dir}"
219 if not target_is_windows:
220 # Avoid passing -rpath on Windows where it is not supported.
221 config.target_cflags += f" -Wl,-rpath,{config.compiler_rt_libdir}"
222 else:
223 lit_config.warning(
224 f"Cannot override compiler-rt library directory with non-Clang "
225 f"compiler: {config.compiler_id}"
229 # Ask the compiler for the path to libraries it is going to use. If this
230 # doesn't match config.compiler_rt_libdir then it means we might be testing the
231 # compiler's own runtime libraries rather than the ones we just built.
232 # Warn about this and handle appropriately.
233 compiler_libdir = find_compiler_libdir()
234 if compiler_libdir:
235 compiler_rt_libdir_real = os.path.realpath(config.compiler_rt_libdir)
236 if compiler_libdir != compiler_rt_libdir_real:
237 lit_config.warning(
238 "Compiler lib dir != compiler-rt lib dir\n"
239 f'Compiler libdir: "{compiler_libdir}"\n'
240 f'compiler-rt libdir: "{compiler_rt_libdir_real}"'
242 if config.test_standalone_build_libs:
243 # Use just built runtime libraries, i.e. the libraries this build just built.
244 if not config.test_suite_supports_overriding_runtime_lib_path:
245 # Test suite doesn't support this configuration.
246 # TODO(dliew): This should be an error but it seems several bots are
247 # testing incorrectly and having this as an error breaks them.
248 lit_config.warning(
249 "COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite "
250 "does not support testing the just-built runtime libraries "
251 "when the test compiler is configured to use different runtime "
252 "libraries. Either modify this test suite to support this test "
253 "configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF "
254 "to test the runtime libraries included in the compiler instead."
256 else:
257 # Use Compiler's resource library directory instead.
258 config.compiler_rt_libdir = compiler_libdir
259 lit_config.note(f'Testing using libraries in "{config.compiler_rt_libdir}"')
261 # If needed, add cflag for shadow scale.
262 if config.asan_shadow_scale != "":
263 config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale
264 if config.memprof_shadow_scale != "":
265 config.target_cflags += (
266 " -mllvm -memprof-mapping-scale=" + config.memprof_shadow_scale
269 # Clear some environment variables that might affect Clang.
270 possibly_dangerous_env_vars = [
271 "ASAN_OPTIONS",
272 "DFSAN_OPTIONS",
273 "HWASAN_OPTIONS",
274 "LSAN_OPTIONS",
275 "MSAN_OPTIONS",
276 "UBSAN_OPTIONS",
277 "COMPILER_PATH",
278 "RC_DEBUG_OPTIONS",
279 "CINDEXTEST_PREAMBLE_FILE",
280 "CPATH",
281 "C_INCLUDE_PATH",
282 "CPLUS_INCLUDE_PATH",
283 "OBJC_INCLUDE_PATH",
284 "OBJCPLUS_INCLUDE_PATH",
285 "LIBCLANG_TIMING",
286 "LIBCLANG_OBJTRACKING",
287 "LIBCLANG_LOGGING",
288 "LIBCLANG_BGPRIO_INDEX",
289 "LIBCLANG_BGPRIO_EDIT",
290 "LIBCLANG_NOTHREADS",
291 "LIBCLANG_RESOURCE_USAGE",
292 "LIBCLANG_CODE_COMPLETION_LOGGING",
293 "XRAY_OPTIONS",
295 # Clang/MSVC may refer to %INCLUDE%. vsvarsall.bat sets it.
296 if not (platform.system() == "Windows" and target_is_msvc):
297 possibly_dangerous_env_vars.append("INCLUDE")
298 for name in possibly_dangerous_env_vars:
299 if name in config.environment:
300 del config.environment[name]
302 # Tweak PATH to include llvm tools dir.
303 if (not config.llvm_tools_dir) or (not os.path.exists(config.llvm_tools_dir)):
304 lit_config.fatal(
305 "Invalid llvm_tools_dir config attribute: %r" % config.llvm_tools_dir
307 path = os.path.pathsep.join((config.llvm_tools_dir, config.environment["PATH"]))
308 config.environment["PATH"] = path
310 # Help MSVS link.exe find the standard libraries.
311 # Make sure we only try to use it when targetting Windows.
312 if platform.system() == "Windows" and target_is_msvc:
313 config.environment["LIB"] = os.environ["LIB"]
315 config.available_features.add(config.host_os.lower())
317 if config.target_triple.startswith("ppc") or config.target_triple.startswith("powerpc"):
318 config.available_features.add("ppc")
320 if re.match(r"^x86_64.*-linux", config.target_triple):
321 config.available_features.add("x86_64-linux")
323 config.available_features.add("host-byteorder-" + sys.byteorder + "-endian")
325 if config.have_zlib:
326 config.available_features.add("zlib")
327 config.substitutions.append(("%zlib_include_dir", config.zlib_include_dir))
328 config.substitutions.append(("%zlib_library", config.zlib_library))
330 if config.have_internal_symbolizer:
331 config.available_features.add("internal_symbolizer")
333 # Use ugly construction to explicitly prohibit "clang", "clang++" etc.
334 # in RUN lines.
335 config.substitutions.append(
337 " clang",
338 """\n\n*** Do not use 'clangXXX' in tests,
339 instead define '%clangXXX' substitution in lit config. ***\n\n""",
343 if config.host_os == "NetBSD":
344 nb_commands_dir = os.path.join(
345 config.compiler_rt_src_root, "test", "sanitizer_common", "netbsd_commands"
347 config.netbsd_noaslr_prefix = "sh " + os.path.join(nb_commands_dir, "run_noaslr.sh")
348 config.netbsd_nomprotect_prefix = "sh " + os.path.join(
349 nb_commands_dir, "run_nomprotect.sh"
351 config.substitutions.append(("%run_nomprotect", config.netbsd_nomprotect_prefix))
352 else:
353 config.substitutions.append(("%run_nomprotect", "%run"))
355 # Copied from libcxx's config.py
356 def get_lit_conf(name, default=None):
357 # Allow overriding on the command line using --param=<name>=<val>
358 val = lit_config.params.get(name, None)
359 if val is None:
360 val = getattr(config, name, None)
361 if val is None:
362 val = default
363 return val
366 emulator = get_lit_conf("emulator", None)
369 def get_ios_commands_dir():
370 return os.path.join(
371 config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands"
375 # Allow tests to be executed on a simulator or remotely.
376 if emulator:
377 config.substitutions.append(("%run", emulator))
378 config.substitutions.append(("%env ", "env "))
379 # TODO: Implement `%device_rm` to perform removal of files in the emulator.
380 # For now just make it a no-op.
381 lit_config.warning("%device_rm is not implemented")
382 config.substitutions.append(("%device_rm", "echo "))
383 config.compile_wrapper = ""
384 elif config.host_os == "Darwin" and config.apple_platform != "osx":
385 # Darwin tests can be targetting macOS, a device or a simulator. All devices
386 # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly,
387 # all simulators are "iossim". See the table below.
389 # =========================================================================
390 # Target | Feature set
391 # =========================================================================
392 # macOS | darwin
393 # iOS device | darwin, ios
394 # iOS simulator | darwin, ios, iossim
395 # tvOS device | darwin, ios, tvos
396 # tvOS simulator | darwin, ios, iossim, tvos, tvossim
397 # watchOS device | darwin, ios, watchos
398 # watchOS simulator | darwin, ios, iossim, watchos, watchossim
399 # =========================================================================
401 ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios"
403 config.available_features.add("ios")
404 device_id_env = "SANITIZER_" + ios_or_iossim.upper() + "_TEST_DEVICE_IDENTIFIER"
405 if ios_or_iossim == "iossim":
406 config.available_features.add("iossim")
407 if device_id_env not in os.environ:
408 lit_config.fatal(
409 "{} must be set in the environment when running iossim tests".format(
410 device_id_env
413 if config.apple_platform != "ios" and config.apple_platform != "iossim":
414 config.available_features.add(config.apple_platform)
416 ios_commands_dir = get_ios_commands_dir()
418 run_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_run.py")
419 env_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_env.py")
420 compile_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_compile.py")
421 prepare_script = os.path.join(ios_commands_dir, ios_or_iossim + "_prepare.py")
423 if device_id_env in os.environ:
424 config.environment[device_id_env] = os.environ[device_id_env]
425 config.substitutions.append(("%run", run_wrapper))
426 config.substitutions.append(("%env ", env_wrapper + " "))
427 # Current implementation of %device_rm uses the run_wrapper to do
428 # the work.
429 config.substitutions.append(("%device_rm", "{} rm ".format(run_wrapper)))
430 config.compile_wrapper = compile_wrapper
432 try:
433 prepare_output = (
434 subprocess.check_output(
435 [prepare_script, config.apple_platform, config.clang]
437 .decode()
438 .strip()
440 except subprocess.CalledProcessError as e:
441 print("Command failed:")
442 print(e.output)
443 raise e
444 if len(prepare_output) > 0:
445 print(prepare_output)
446 prepare_output_json = prepare_output.split("\n")[-1]
447 prepare_output = json.loads(prepare_output_json)
448 config.environment.update(prepare_output["env"])
449 elif config.android:
450 config.available_features.add("android")
451 compile_wrapper = (
452 os.path.join(
453 config.compiler_rt_src_root,
454 "test",
455 "sanitizer_common",
456 "android_commands",
457 "android_compile.py",
459 + " "
461 config.compile_wrapper = compile_wrapper
462 config.substitutions.append(("%run", ""))
463 config.substitutions.append(("%env ", "env "))
464 else:
465 config.substitutions.append(("%run", ""))
466 config.substitutions.append(("%env ", "env "))
467 # When running locally %device_rm is a no-op.
468 config.substitutions.append(("%device_rm", "echo "))
469 config.compile_wrapper = ""
471 # Define CHECK-%os to check for OS-dependent output.
472 config.substitutions.append(("CHECK-%os", ("CHECK-" + config.host_os)))
474 # Define %arch to check for architecture-dependent output.
475 config.substitutions.append(("%arch", (config.host_arch)))
477 if config.host_os == "Windows":
478 # FIXME: This isn't quite right. Specifically, it will succeed if the program
479 # does not crash but exits with a non-zero exit code. We ought to merge
480 # KillTheDoctor and not --crash to make the latter more useful and remove the
481 # need for this substitution.
482 config.expect_crash = "not KillTheDoctor "
483 else:
484 config.expect_crash = "not --crash "
486 config.substitutions.append(("%expect_crash ", config.expect_crash))
488 target_arch = getattr(config, "target_arch", None)
489 if target_arch:
490 config.available_features.add(target_arch + "-target-arch")
491 if target_arch in ["x86_64", "i386"]:
492 config.available_features.add("x86-target-arch")
493 config.available_features.add(target_arch + "-" + config.host_os.lower())
495 compiler_rt_debug = getattr(config, "compiler_rt_debug", False)
496 if not compiler_rt_debug:
497 config.available_features.add("compiler-rt-optimized")
499 libdispatch = getattr(config, "compiler_rt_intercept_libdispatch", False)
500 if libdispatch:
501 config.available_features.add("libdispatch")
503 sanitizer_can_use_cxxabi = getattr(config, "sanitizer_can_use_cxxabi", True)
504 if sanitizer_can_use_cxxabi:
505 config.available_features.add("cxxabi")
507 if not getattr(config, "sanitizer_uses_static_cxxabi", False):
508 config.available_features.add("shared_cxxabi")
510 if not getattr(config, "sanitizer_uses_static_unwind", False):
511 config.available_features.add("shared_unwind")
513 if config.has_lld:
514 config.available_features.add("lld-available")
516 if config.aarch64_sme:
517 config.available_features.add("aarch64-sme-available")
519 if config.use_lld:
520 config.available_features.add("lld")
522 if config.can_symbolize:
523 config.available_features.add("can-symbolize")
525 if config.gwp_asan:
526 config.available_features.add("gwp_asan")
528 lit.util.usePlatformSdkOnDarwin(config, lit_config)
530 min_macos_deployment_target_substitutions = [
531 (10, 11),
532 (10, 12),
534 # TLS requires watchOS 3+
535 config.substitutions.append(
536 ("%darwin_min_target_with_tls_support", "%min_macos_deployment_target=10.12")
539 if config.host_os == "Darwin":
540 osx_version = (10, 0, 0)
541 try:
542 osx_version = subprocess.check_output(
543 ["sw_vers", "-productVersion"], universal_newlines=True
545 osx_version = tuple(int(x) for x in osx_version.split("."))
546 if len(osx_version) == 2:
547 osx_version = (osx_version[0], osx_version[1], 0)
548 if osx_version >= (10, 11):
549 config.available_features.add("osx-autointerception")
550 config.available_features.add("osx-ld64-live_support")
551 if osx_version >= (13, 1):
552 config.available_features.add("jit-compatible-osx-swift-runtime")
553 except subprocess.CalledProcessError:
554 pass
556 config.darwin_osx_version = osx_version
558 # Detect x86_64h
559 try:
560 output = subprocess.check_output(["sysctl", "hw.cpusubtype"])
561 output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)
562 if output_re:
563 cpu_subtype = int(output_re.group(1))
564 if cpu_subtype == 8: # x86_64h
565 config.available_features.add("x86_64h")
566 except:
567 pass
569 # 32-bit iOS simulator is deprecated and removed in latest Xcode.
570 if config.apple_platform == "iossim":
571 if config.target_arch == "i386":
572 config.unsupported = True
574 def get_macos_aligned_version(macos_vers):
575 platform = config.apple_platform
576 if platform == "osx":
577 return macos_vers
579 macos_major, macos_minor = macos_vers
580 assert macos_major >= 10
582 if macos_major == 10: # macOS 10.x
583 major = macos_minor
584 minor = 0
585 else: # macOS 11+
586 major = macos_major + 5
587 minor = macos_minor
589 assert major >= 11
591 if platform.startswith("ios") or platform.startswith("tvos"):
592 major -= 2
593 elif platform.startswith("watch"):
594 major -= 9
595 else:
596 lit_config.fatal("Unsupported apple platform '{}'".format(platform))
598 return (major, minor)
600 for vers in min_macos_deployment_target_substitutions:
601 flag = config.apple_platform_min_deployment_target_flag
602 major, minor = get_macos_aligned_version(vers)
603 apple_device = ""
604 sim = ""
605 if "target" in flag:
606 apple_device = config.apple_platform.split("sim")[0]
607 sim = "-simulator" if "sim" in config.apple_platform else ""
609 config.substitutions.append(
611 "%%min_macos_deployment_target=%s.%s" % vers,
612 "{}={}{}.{}{}".format(flag, apple_device, major, minor, sim),
615 else:
616 for vers in min_macos_deployment_target_substitutions:
617 config.substitutions.append(("%%min_macos_deployment_target=%s.%s" % vers, ""))
619 if config.android:
620 env = os.environ.copy()
621 if config.android_serial:
622 env["ANDROID_SERIAL"] = config.android_serial
623 config.environment["ANDROID_SERIAL"] = config.android_serial
625 adb = os.environ.get("ADB", "adb")
627 # These are needed for tests to upload/download temp files, such as
628 # suppression-files, to device.
629 config.substitutions.append(("%device_rundir/", "/data/local/tmp/Output/"))
630 config.substitutions.append(
631 ("%push_to_device", "%s -s '%s' push " % (adb, env["ANDROID_SERIAL"]))
633 config.substitutions.append(
634 ("%adb_shell ", "%s -s '%s' shell " % (adb, env["ANDROID_SERIAL"]))
636 config.substitutions.append(
637 ("%device_rm", "%s -s '%s' shell 'rm ' " % (adb, env["ANDROID_SERIAL"]))
640 try:
641 android_api_level_str = subprocess.check_output(
642 [adb, "shell", "getprop", "ro.build.version.sdk"], env=env
643 ).rstrip()
644 android_api_codename = (
645 subprocess.check_output(
646 [adb, "shell", "getprop", "ro.build.version.codename"], env=env
648 .rstrip()
649 .decode("utf-8")
651 except (subprocess.CalledProcessError, OSError):
652 lit_config.fatal(
653 "Failed to read ro.build.version.sdk (using '%s' as adb)" % adb
655 try:
656 android_api_level = int(android_api_level_str)
657 except ValueError:
658 lit_config.fatal(
659 "Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'"
660 % (adb, android_api_level_str)
662 android_api_level = min(android_api_level, int(config.android_api_level))
663 for required in [26, 28, 29, 30]:
664 if android_api_level >= required:
665 config.available_features.add("android-%s" % required)
666 # FIXME: Replace with appropriate version when availible.
667 if android_api_level > 30 or (
668 android_api_level == 30 and android_api_codename == "S"
670 config.available_features.add("android-thread-properties-api")
672 # Prepare the device.
673 android_tmpdir = "/data/local/tmp/Output"
674 subprocess.check_call([adb, "shell", "mkdir", "-p", android_tmpdir], env=env)
675 for file in config.android_files_to_push:
676 subprocess.check_call([adb, "push", file, android_tmpdir], env=env)
677 else:
678 config.substitutions.append(("%device_rundir/", ""))
679 config.substitutions.append(("%push_to_device", "echo "))
680 config.substitutions.append(("%adb_shell", "echo "))
682 if config.host_os == "Linux":
683 def add_glibc_versions(ver_string):
684 if config.android:
685 return
687 from distutils.version import LooseVersion
689 ver = LooseVersion(ver_string)
690 any_glibc = False
691 for required in [
692 "2.19",
693 "2.27",
694 "2.30",
695 "2.33",
696 "2.34",
697 "2.37",
698 "2.38",
699 "2.40",
701 if ver >= LooseVersion(required):
702 config.available_features.add("glibc-" + required)
703 any_glibc = True
704 if any_glibc:
705 config.available_features.add("glibc")
707 # detect whether we are using glibc, and which version
708 cmd_args = [
709 config.clang.strip(),
710 f"--target={config.target_triple}",
711 "-xc",
712 "-",
713 "-o",
714 "-",
715 "-dM",
716 "-E",
717 ] + shlex.split(config.target_cflags)
718 cmd = subprocess.Popen(
719 cmd_args,
720 stdout=subprocess.PIPE,
721 stdin=subprocess.PIPE,
722 stderr=subprocess.DEVNULL,
723 env={"LANG": "C"},
725 try:
726 sout, _ = cmd.communicate(b"#include <features.h>")
727 m = dict(re.findall(r"#define (__GLIBC__|__GLIBC_MINOR__) (\d+)", str(sout)))
728 add_glibc_versions(f"{m['__GLIBC__']}.{m['__GLIBC_MINOR__']}")
729 except:
730 pass
732 sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov")
733 if os.path.exists(sancovcc_path):
734 config.available_features.add("has_sancovcc")
735 config.substitutions.append(("%sancovcc ", sancovcc_path))
738 def liblto_path():
739 return os.path.join(config.llvm_shlib_dir, "libLTO.dylib")
742 def is_darwin_lto_supported():
743 return os.path.exists(liblto_path())
746 def is_binutils_lto_supported():
747 if not os.path.exists(os.path.join(config.llvm_shlib_dir, "LLVMgold.so")):
748 return False
750 # We require both ld.bfd and ld.gold exist and support plugins. They are in
751 # the same repository 'binutils-gdb' and usually built together.
752 for exe in (config.gnu_ld_executable, config.gold_executable):
753 try:
754 ld_cmd = subprocess.Popen(
755 [exe, "--help"], stdout=subprocess.PIPE, env={"LANG": "C"}
757 ld_out = ld_cmd.stdout.read().decode()
758 ld_cmd.wait()
759 except OSError:
760 return False
761 if not "-plugin" in ld_out:
762 return False
764 return True
767 def is_lld_lto_supported():
768 # LLD does support LTO, but we require it to be built with the latest
769 # changes to claim support. Otherwise older copies of LLD may not
770 # understand new bitcode versions.
771 return os.path.exists(os.path.join(config.llvm_tools_dir, "lld"))
774 def is_windows_lto_supported():
775 if not target_is_msvc:
776 return True
777 return os.path.exists(os.path.join(config.llvm_tools_dir, "lld-link.exe"))
780 if config.host_os == "Darwin" and is_darwin_lto_supported():
781 config.lto_supported = True
782 config.lto_flags = ["-Wl,-lto_library," + liblto_path()]
783 elif config.host_os in ["Linux", "FreeBSD", "NetBSD"]:
784 config.lto_supported = False
785 if config.use_lld and is_lld_lto_supported():
786 config.lto_supported = True
787 if is_binutils_lto_supported():
788 config.available_features.add("binutils_lto")
789 config.lto_supported = True
791 if config.lto_supported:
792 if config.use_lld:
793 config.lto_flags = ["-fuse-ld=lld"]
794 else:
795 config.lto_flags = ["-fuse-ld=gold"]
796 elif config.host_os == "Windows" and is_windows_lto_supported():
797 config.lto_supported = True
798 config.lto_flags = ["-fuse-ld=lld"]
799 else:
800 config.lto_supported = False
802 if config.lto_supported:
803 config.available_features.add("lto")
804 if config.use_thinlto:
805 config.available_features.add("thinlto")
806 config.lto_flags += ["-flto=thin"]
807 else:
808 config.lto_flags += ["-flto"]
810 if config.have_rpc_xdr_h:
811 config.available_features.add("sunrpc")
813 # Sanitizer tests tend to be flaky on Windows due to PR24554, so add some
814 # retries. We don't do this on otther platforms because it's slower.
815 if platform.system() == "Windows":
816 config.test_retry_attempts = 2
818 # No throttling on non-Darwin platforms.
819 lit_config.parallelism_groups["shadow-memory"] = None
821 if platform.system() == "Darwin":
822 ios_device = config.apple_platform != "osx" and not config.apple_platform.endswith(
823 "sim"
825 # Force sequential execution when running tests on iOS devices.
826 if ios_device:
827 lit_config.warning("Forcing sequential execution for iOS device tests")
828 lit_config.parallelism_groups["ios-device"] = 1
829 config.parallelism_group = "ios-device"
831 # Only run up to 3 processes that require shadow memory simultaneously on
832 # 64-bit Darwin. Using more scales badly and hogs the system due to
833 # inefficient handling of large mmap'd regions (terabytes) by the kernel.
834 else:
835 lit_config.warning(
836 "Throttling sanitizer tests that require shadow memory on Darwin"
838 lit_config.parallelism_groups["shadow-memory"] = 3
840 # Multiple substitutions are necessary to support multiple shared objects used
841 # at once.
842 # Note that substitutions with numbers have to be defined first to avoid
843 # being subsumed by substitutions with smaller postfix.
844 for postfix in ["2", "1", ""]:
845 if config.host_os == "Darwin":
846 config.substitutions.append(
848 "%ld_flags_rpath_exe" + postfix,
849 "-Wl,-rpath,@executable_path/ %dynamiclib" + postfix,
852 config.substitutions.append(
854 "%ld_flags_rpath_so" + postfix,
855 "-install_name @rpath/`basename %dynamiclib{}`".format(postfix),
858 elif config.host_os in ("FreeBSD", "NetBSD", "OpenBSD"):
859 config.substitutions.append(
861 "%ld_flags_rpath_exe" + postfix,
862 r"-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec"
863 + postfix,
866 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))
867 elif config.host_os == "Linux":
868 config.substitutions.append(
870 "%ld_flags_rpath_exe" + postfix,
871 r"-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix,
874 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))
875 elif config.host_os == "SunOS":
876 config.substitutions.append(
878 "%ld_flags_rpath_exe" + postfix,
879 r"-Wl,-R\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix,
882 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))
884 # Must be defined after the substitutions that use %dynamiclib.
885 config.substitutions.append(
886 ("%dynamiclib" + postfix, "%T/%xdynamiclib_filename" + postfix)
888 config.substitutions.append(
890 "%xdynamiclib_filename" + postfix,
891 "lib%xdynamiclib_namespec{}.so".format(postfix),
894 config.substitutions.append(("%xdynamiclib_namespec", "%basename_t.dynamic"))
896 config.default_sanitizer_opts = []
897 if config.host_os == "Darwin":
898 # On Darwin, we default to `abort_on_error=1`, which would make tests run
899 # much slower. Let's override this and run lit tests with 'abort_on_error=0'.
900 config.default_sanitizer_opts += ["abort_on_error=0"]
901 config.default_sanitizer_opts += ["log_to_syslog=0"]
902 if lit.util.which("log"):
903 # Querying the log can only done by a privileged user so
904 # so check if we can query the log.
905 exit_code = -1
906 with open("/dev/null", "r") as f:
907 # Run a `log show` command the should finish fairly quickly and produce very little output.
908 exit_code = subprocess.call(
909 ["log", "show", "--last", "1m", "--predicate", "1 == 0"],
910 stdout=f,
911 stderr=f,
913 if exit_code == 0:
914 config.available_features.add("darwin_log_cmd")
915 else:
916 lit_config.warning("log command found but cannot queried")
917 else:
918 lit_config.warning("log command not found. Some tests will be skipped.")
919 elif config.android:
920 config.default_sanitizer_opts += ["abort_on_error=0"]
922 # Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL
923 # because the test hangs or fails on one configuration and not the other.
924 if config.android or (config.target_arch not in ["arm", "armhf", "aarch64"]):
925 config.available_features.add("stable-runtime")
927 if config.asan_shadow_scale:
928 config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale)
929 else:
930 config.available_features.add("shadow-scale-3")
932 if config.memprof_shadow_scale:
933 config.available_features.add(
934 "memprof-shadow-scale-%s" % config.memprof_shadow_scale
936 else:
937 config.available_features.add("memprof-shadow-scale-3")
939 if config.expensive_checks:
940 config.available_features.add("expensive_checks")
942 # Propagate the LLD/LTO into the clang config option, so nothing else is needed.
943 run_wrapper = []
944 target_cflags = [getattr(config, "target_cflags", None)]
945 extra_cflags = []
947 if config.use_lto and config.lto_supported:
948 extra_cflags += config.lto_flags
949 elif config.use_lto and (not config.lto_supported):
950 config.unsupported = True
952 if config.use_lld and config.has_lld and not config.use_lto:
953 extra_cflags += ["-fuse-ld=lld"]
954 elif config.use_lld and (not config.has_lld):
955 config.unsupported = True
957 if config.host_os == "Darwin":
958 if getattr(config, "darwin_linker_version", None):
959 extra_cflags += ["-mlinker-version=" + config.darwin_linker_version]
961 # Append any extra flags passed in lit_config
962 append_target_cflags = lit_config.params.get("append_target_cflags", None)
963 if append_target_cflags:
964 lit_config.note('Appending to extra_cflags: "{}"'.format(append_target_cflags))
965 extra_cflags += [append_target_cflags]
967 config.clang = (
968 " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " "
970 config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " "
972 if config.host_os == "Darwin":
973 config.substitutions.append(
975 "%get_pid_from_output",
976 "{} {}/get_pid_from_output.py".format(
977 shlex.quote(config.python_executable),
978 shlex.quote(get_ios_commands_dir()),
982 config.substitutions.append(
984 "%print_crashreport_for_pid",
985 "{} {}/print_crashreport_for_pid.py".format(
986 shlex.quote(config.python_executable),
987 shlex.quote(get_ios_commands_dir()),
992 # It is not realistically possible to account for all options that could
993 # possibly be present in system and user configuration files, so disable
994 # default configs for the test runs. In particular, anything hardening
995 # related is likely to cause issues with sanitizer tests, because it may
996 # preempt something we're looking to trap (e.g. _FORTIFY_SOURCE vs our ASAN).
998 # Only set this if we know we can still build for the target while disabling
999 # default configs.
1000 if config.has_no_default_config_flag:
1001 config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1"
1003 if config.has_compiler_rt_libatomic:
1004 base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.atomic%s.so"
1005 % config.target_suffix)
1006 if sys.platform in ['win32'] and execute_external:
1007 # Don't pass dosish path separator to msys bash.exe.
1008 base_lib = base_lib.replace('\\', '/')
1009 config.substitutions.append(("%libatomic", base_lib + f" -Wl,-rpath,{config.compiler_rt_libdir}"))
1010 else:
1011 config.substitutions.append(("%libatomic", "-latomic"))
1013 # Set LD_LIBRARY_PATH to pick dynamic runtime up properly.
1014 push_dynamic_library_lookup_path(config, config.compiler_rt_libdir)
1016 # GCC-ASan uses dynamic runtime by default.
1017 if config.compiler_id == "GNU":
1018 gcc_dir = os.path.dirname(config.clang)
1019 libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)
1020 push_dynamic_library_lookup_path(config, libasan_dir)
1023 # Help tests that make sure certain files are in-sync between compiler-rt and
1024 # llvm.
1025 config.substitutions.append(("%crt_src", config.compiler_rt_src_root))
1026 config.substitutions.append(("%llvm_src", config.llvm_src_root))