1074 lines · python
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 os7import platform8import re9import shlex10import subprocess11import json12 13import lit.formats14import lit.util15 16 17def get_path_from_clang(args, allow_failure):18 clang_cmd = [19 config.clang.strip(),20 f"--target={config.target_triple}",21 *args,22 ]23 path = None24 try:25 result = subprocess.run(26 clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True27 )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_cmd36 37 38def find_compiler_libdir():39 """40 Returns the path to library resource directory used41 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}"46 )47 # TODO: Support other compilers.48 return None49 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=True54 )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 misconfigured60 lit_config.warning(61 f'Path reported by clang does not exist: "{runtime_dir}". '62 f"This path was found by running {clang_cmd}."63 )64 return None65 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 Apple68 # platforms so we can't use that approach here (see https://reviews.llvm.org/D101682).69 if config.target_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)75 76 lit_config.warning("Failed to determine compiler's runtime directory")77 return None78 79 80def 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"89 90 new_ld_library_path = os.path.pathsep.join(91 (new_path, config.environment.get(dynamic_library_lookup_var, ""))92 )93 config.environment[dynamic_library_lookup_var] = new_ld_library_path94 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, ""))99 )100 config.environment[dynamic_library_lookup_var] = new_ld_32_library_path101 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, ""))106 )107 config.environment[dynamic_library_lookup_var] = new_ld_library_path_32108 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, ""))112 )113 config.environment[dynamic_library_lookup_var] = new_ld_library_path_64114 115 116# Choose between lit's internal shell pipeline runner and a real shell. If117# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.118use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")119if use_lit_shell:120 # 0 is external, "" is default, and everything else is internal.121 execute_external = use_lit_shell == "0"122else:123 # Otherwise we default to internal on Windows and external elsewhere, as124 # bash on Windows is usually very slow.125 execute_external = not sys.platform in ["win32"]126 127# Allow expanding substitutions that are based on other substitutions128config.recursiveExpansionLimit = 10129 130# Setup test format.131config.test_format = lit.formats.ShTest(execute_external)132if execute_external:133 config.available_features.add("shell")134 135target_is_msvc = bool(re.match(r".*-windows-msvc$", config.target_triple))136target_is_windows = bool(re.match(r".*-windows.*$", config.target_triple))137 138compiler_id = getattr(config, "compiler_id", None)139if 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 error145 # 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 and149 # windbg do not behave well when column info is enabled, but users have150 # requested it because it makes ASan reports more precise.151 config.debug_info_flags.append("-gcodeview")152 config.debug_info_flags.append("-gcolumn-info")153elif compiler_id == "MSVC":154 config.debug_info_flags = ["/Z7"]155 config.cxx_mode_flags = []156elif compiler_id == "GNU":157 config.cxx_mode_flags = ["-x c++"]158 config.debug_info_flags = ["-g"]159else:160 lit_config.fatal("Unsupported compiler id: %r" % compiler_id)161# Add compiler ID to the list of available features.162config.available_features.add(compiler_id)163 164# When LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=on, the initial value of165# config.compiler_rt_libdir (COMPILER_RT_RESOLVED_LIBRARY_OUTPUT_DIR) has the166# host triple as the trailing path component. The value is incorrect for 32-bit167# tests on 64-bit hosts and vice versa. Adjust config.compiler_rt_libdir168# accordingly.169if 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_libdir173 )174 elif config.target_arch == "x86_64":175 config.compiler_rt_libdir = re.sub(176 r"/i386(?=-[^/]+$)", "/x86_64", config.compiler_rt_libdir177 )178 if config.target_arch == "sparc":179 config.compiler_rt_libdir = re.sub(180 r"/sparcv9(?=-[^/]+$)", "/sparc", config.compiler_rt_libdir181 )182 elif config.target_arch == "sparcv9":183 config.compiler_rt_libdir = re.sub(184 r"/sparc(?=-[^/]+$)", "/sparcv9", config.compiler_rt_libdir185 )186 187# Check if the test compiler resource dir matches the local build directory188# (which happens with -DLLVM_ENABLE_PROJECTS=clang;compiler-rt) or if we are189# using an installed clang to test compiler-rt standalone. In the latter case190# we may need to override the resource dir to match the path of the just-built191# compiler-rt libraries.192test_cc_resource_dir, _ = get_path_from_clang(193 shlex.split(config.target_cflags) + ["-print-resource-dir"], allow_failure=True194)195# Normalize the path for comparison196if test_cc_resource_dir is not None:197 test_cc_resource_dir = os.path.realpath(test_cc_resource_dir)198lit_config.dbg(f"Resource dir for {config.clang} is {test_cc_resource_dir}")199local_build_resource_dir = os.path.realpath(config.compiler_rt_output_dir)200if test_cc_resource_dir != local_build_resource_dir and config.test_standalone_build_libs:201 if config.compiler_id == "Clang":202 lit_config.dbg(203 f"Overriding test compiler resource dir to use "204 f'libraries in "{config.compiler_rt_libdir}"'205 )206 # Ensure that we use the just-built static libraries when linking by207 # overriding the Clang resource directory. Additionally, we want to use208 # the builtin headers shipped with clang (e.g. stdint.h), so we209 # explicitly add this as an include path (since the headers are not210 # going to be in the current compiler-rt build directory).211 # We also tell the linker to add an RPATH entry for the local library212 # directory so that the just-built shared libraries are used.213 config.target_cflags += f" -nobuiltininc"214 config.target_cflags += f" -I{config.compiler_rt_src_root}/include"215 config.target_cflags += f" -idirafter {test_cc_resource_dir}/include"216 config.target_cflags += f" -resource-dir={config.compiler_rt_output_dir}"217 if not target_is_windows:218 # Avoid passing -rpath on Windows where it is not supported.219 config.target_cflags += f" -Wl,-rpath,{config.compiler_rt_libdir}"220 else:221 lit_config.warning(222 f"Cannot override compiler-rt library directory with non-Clang "223 f"compiler: {config.compiler_id}"224 )225 226 227# Ask the compiler for the path to libraries it is going to use. If this228# doesn't match config.compiler_rt_libdir then it means we might be testing the229# compiler's own runtime libraries rather than the ones we just built.230# Warn about this and handle appropriately.231compiler_libdir = find_compiler_libdir()232if compiler_libdir:233 compiler_rt_libdir_real = os.path.realpath(config.compiler_rt_libdir)234 if compiler_libdir != compiler_rt_libdir_real:235 lit_config.warning(236 "Compiler lib dir != compiler-rt lib dir\n"237 f'Compiler libdir: "{compiler_libdir}"\n'238 f'compiler-rt libdir: "{compiler_rt_libdir_real}"'239 )240 if config.test_standalone_build_libs:241 # Use just built runtime libraries, i.e. the libraries this build just built.242 if not config.test_suite_supports_overriding_runtime_lib_path:243 # Test suite doesn't support this configuration.244 # TODO(dliew): This should be an error but it seems several bots are245 # testing incorrectly and having this as an error breaks them.246 lit_config.warning(247 "COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=ON, but this test suite "248 "does not support testing the just-built runtime libraries "249 "when the test compiler is configured to use different runtime "250 "libraries. Either modify this test suite to support this test "251 "configuration, or set COMPILER_RT_TEST_STANDALONE_BUILD_LIBS=OFF "252 "to test the runtime libraries included in the compiler instead."253 )254 else:255 # Use Compiler's resource library directory instead.256 config.compiler_rt_libdir = compiler_libdir257 lit_config.note(f'Testing using libraries in "{config.compiler_rt_libdir}"')258 259# If needed, add cflag for shadow scale.260if config.asan_shadow_scale != "":261 config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale262if config.memprof_shadow_scale != "":263 config.target_cflags += (264 " -mllvm -memprof-mapping-scale=" + config.memprof_shadow_scale265 )266 267# Clear some environment variables that might affect Clang.268possibly_dangerous_env_vars = [269 "ASAN_OPTIONS",270 "DFSAN_OPTIONS",271 "HWASAN_OPTIONS",272 "LSAN_OPTIONS",273 "MSAN_OPTIONS",274 "UBSAN_OPTIONS",275 "COMPILER_PATH",276 "RC_DEBUG_OPTIONS",277 "CINDEXTEST_PREAMBLE_FILE",278 "CPATH",279 "C_INCLUDE_PATH",280 "CPLUS_INCLUDE_PATH",281 "OBJC_INCLUDE_PATH",282 "OBJCPLUS_INCLUDE_PATH",283 "LIBCLANG_TIMING",284 "LIBCLANG_OBJTRACKING",285 "LIBCLANG_LOGGING",286 "LIBCLANG_BGPRIO_INDEX",287 "LIBCLANG_BGPRIO_EDIT",288 "LIBCLANG_NOTHREADS",289 "LIBCLANG_RESOURCE_USAGE",290 "LIBCLANG_CODE_COMPLETION_LOGGING",291 "XRAY_OPTIONS",292]293# Clang/MSVC may refer to %INCLUDE%. vsvarsall.bat sets it.294if not (platform.system() == "Windows" and target_is_msvc):295 possibly_dangerous_env_vars.append("INCLUDE")296for name in possibly_dangerous_env_vars:297 if name in config.environment:298 del config.environment[name]299 300# Tweak PATH to include llvm tools dir.301if (not config.llvm_tools_dir) or (not os.path.exists(config.llvm_tools_dir)):302 lit_config.fatal(303 "Invalid llvm_tools_dir config attribute: %r" % config.llvm_tools_dir304 )305path = os.path.pathsep.join((config.llvm_tools_dir, config.environment["PATH"]))306config.environment["PATH"] = path307 308# Help MSVS link.exe find the standard libraries.309# Make sure we only try to use it when targetting Windows.310if platform.system() == "Windows" and target_is_msvc:311 config.environment["LIB"] = os.environ["LIB"]312 313config.available_features.add(config.target_os.lower())314 315if config.target_triple.startswith("ppc") or config.target_triple.startswith("powerpc"):316 config.available_features.add("ppc")317 318if re.match(r"^x86_64.*-linux", config.target_triple):319 config.available_features.add("x86_64-linux")320 321config.available_features.add("host-byteorder-" + sys.byteorder + "-endian")322 323if config.have_zlib:324 config.available_features.add("zlib")325 config.substitutions.append(("%zlib_include_dir", config.zlib_include_dir))326 config.substitutions.append(("%zlib_library", config.zlib_library))327 328if config.have_internal_symbolizer:329 config.available_features.add("internal_symbolizer")330 331if config.have_disable_symbolizer_path_search:332 config.available_features.add("disable_symbolizer_path_search")333 334 335# Use ugly construction to explicitly prohibit "clang", "clang++" etc.336# in RUN lines.337config.substitutions.append(338 (339 " clang",340 """\n\n*** Do not use 'clangXXX' in tests,341 instead define '%clangXXX' substitution in lit config. ***\n\n""",342 )343)344 345if config.target_os == "NetBSD":346 nb_commands_dir = os.path.join(347 config.compiler_rt_src_root, "test", "sanitizer_common", "netbsd_commands"348 )349 config.netbsd_noaslr_prefix = "sh " + os.path.join(nb_commands_dir, "run_noaslr.sh")350 config.netbsd_nomprotect_prefix = "sh " + os.path.join(351 nb_commands_dir, "run_nomprotect.sh"352 )353 config.substitutions.append(("%run_nomprotect", config.netbsd_nomprotect_prefix))354else:355 config.substitutions.append(("%run_nomprotect", "%run"))356 357# Copied from libcxx's config.py358def get_lit_conf(name, default=None):359 # Allow overriding on the command line using --param=<name>=<val>360 val = lit_config.params.get(name, None)361 if val is None:362 val = getattr(config, name, None)363 if val is None:364 val = default365 return val366 367 368emulator = get_lit_conf("emulator", None)369 370 371def get_ios_commands_dir():372 return os.path.join(373 config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands"374 )375 376 377# When cmake flag to disable path search is set, symbolizer is not allowed to search in $PATH,378# need to specify it via XXX_SYMBOLIZER_PATH379tool_symbolizer_path_list = [380 "ASAN_SYMBOLIZER_PATH",381 "HWASAN_SYMBOLIZER_PATH",382 "RTSAN_SYMBOLIZER_PATH",383 "TSAN_SYMBOLIZER_PATH",384 "MSAN_SYMBOLIZER_PATH",385 "LSAN_SYMBOLIZER_PATH",386 "UBSAN_SYMBOLIZER_PATH",387]388 389if config.have_disable_symbolizer_path_search:390 symbolizer_path = os.path.join(config.llvm_tools_dir, "llvm-symbolizer")391 392 for sanitizer in tool_symbolizer_path_list:393 if sanitizer not in config.environment:394 config.environment[sanitizer] = symbolizer_path395 396env_utility = "/opt/freeware/bin/env" if config.target_os == "AIX" else "env"397env_unset_command = " ".join(f"-u {var}" for var in tool_symbolizer_path_list)398config.substitutions.append(399 ("%env_unset_tool_symbolizer_path", f"{env_utility} {env_unset_command}")400)401 402# Allow tests to be executed on a simulator or remotely.403if emulator:404 config.substitutions.append(("%run", emulator))405 config.substitutions.append(("%env ", "env "))406 # TODO: Implement `%device_rm` to perform removal of files in the emulator.407 # For now just make it a no-op.408 lit_config.warning("%device_rm is not implemented")409 config.substitutions.append(("%device_rm", "echo "))410 config.compile_wrapper = ""411elif config.target_os == "Darwin" and config.apple_platform != "osx":412 # Darwin tests can be targetting macOS, a device or a simulator. All devices413 # are declared as "ios", even for iOS derivatives (tvOS, watchOS). Similarly,414 # all simulators are "iossim". See the table below.415 #416 # =========================================================================417 # Target | Feature set418 # =========================================================================419 # macOS | darwin420 # iOS device | darwin, ios421 # iOS simulator | darwin, ios, iossim422 # tvOS device | darwin, ios, tvos423 # tvOS simulator | darwin, ios, iossim, tvos, tvossim424 # watchOS device | darwin, ios, watchos425 # watchOS simulator | darwin, ios, iossim, watchos, watchossim426 # =========================================================================427 428 ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios"429 430 config.available_features.add("ios")431 device_id_env = "SANITIZER_" + ios_or_iossim.upper() + "_TEST_DEVICE_IDENTIFIER"432 if ios_or_iossim == "iossim":433 config.available_features.add("iossim")434 if device_id_env not in os.environ:435 lit_config.fatal(436 "{} must be set in the environment when running iossim tests".format(437 device_id_env438 )439 )440 if config.apple_platform != "ios" and config.apple_platform != "iossim":441 config.available_features.add(config.apple_platform)442 443 ios_commands_dir = get_ios_commands_dir()444 445 run_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_run.py")446 env_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_env.py")447 compile_wrapper = os.path.join(ios_commands_dir, ios_or_iossim + "_compile.py")448 prepare_script = os.path.join(ios_commands_dir, ios_or_iossim + "_prepare.py")449 450 if device_id_env in os.environ:451 config.environment[device_id_env] = os.environ[device_id_env]452 config.substitutions.append(("%run", run_wrapper))453 config.substitutions.append(("%env ", env_wrapper + " "))454 # Current implementation of %device_rm uses the run_wrapper to do455 # the work.456 config.substitutions.append(("%device_rm", "{} rm ".format(run_wrapper)))457 config.compile_wrapper = compile_wrapper458 459 try:460 prepare_output = (461 subprocess.check_output(462 [prepare_script, config.apple_platform, config.clang]463 )464 .decode()465 .strip()466 )467 except subprocess.CalledProcessError as e:468 print("Command failed:")469 print(e.output)470 raise e471 if len(prepare_output) > 0:472 print(prepare_output)473 prepare_output_json = prepare_output.split("\n")[-1]474 prepare_output = json.loads(prepare_output_json)475 config.environment.update(prepare_output["env"])476elif config.android:477 config.available_features.add("android")478 compile_wrapper = (479 os.path.join(480 config.compiler_rt_src_root,481 "test",482 "sanitizer_common",483 "android_commands",484 "android_compile.py",485 )486 + " "487 )488 config.compile_wrapper = compile_wrapper489 config.substitutions.append(("%run", ""))490 config.substitutions.append(("%env ", "env "))491else:492 config.substitutions.append(("%run", ""))493 config.substitutions.append(("%env ", "env "))494 # When running locally %device_rm is a no-op.495 config.substitutions.append(("%device_rm", "echo "))496 config.compile_wrapper = ""497 498# Define CHECK-%os to check for OS-dependent output.499config.substitutions.append(("CHECK-%os", ("CHECK-" + config.target_os)))500 501# Define %arch to check for architecture-dependent output.502config.substitutions.append(("%arch", (config.host_arch)))503 504if os.name == "nt":505 # FIXME: This isn't quite right. Specifically, it will succeed if the program506 # does not crash but exits with a non-zero exit code. We ought to merge507 # KillTheDoctor and not --crash to make the latter more useful and remove the508 # need for this substitution.509 config.expect_crash = "not KillTheDoctor "510else:511 config.expect_crash = "not --crash "512 513config.substitutions.append(("%expect_crash ", config.expect_crash))514 515target_arch = getattr(config, "target_arch", None)516if target_arch:517 config.available_features.add(target_arch + "-target-arch")518 if target_arch in ["x86_64", "i386"]:519 config.available_features.add("x86-target-arch")520 config.available_features.add(target_arch + "-" + config.target_os.lower())521 522compiler_rt_debug = getattr(config, "compiler_rt_debug", False)523if not compiler_rt_debug:524 config.available_features.add("compiler-rt-optimized")525 526libdispatch = getattr(config, "compiler_rt_intercept_libdispatch", False)527if libdispatch:528 config.available_features.add("libdispatch")529 530sanitizer_can_use_cxxabi = getattr(config, "sanitizer_can_use_cxxabi", True)531if sanitizer_can_use_cxxabi:532 config.available_features.add("cxxabi")533 534if not getattr(config, "sanitizer_uses_static_cxxabi", False):535 config.available_features.add("shared_cxxabi")536 537if not getattr(config, "sanitizer_uses_static_unwind", False):538 config.available_features.add("shared_unwind")539 540if config.has_lld:541 config.available_features.add("lld-available")542 543if config.aarch64_sme:544 config.available_features.add("aarch64-sme-available")545 546if config.use_lld:547 config.available_features.add("lld")548 549if config.can_symbolize:550 config.available_features.add("can-symbolize")551 552if config.gwp_asan:553 config.available_features.add("gwp_asan")554 555lit.util.usePlatformSdkOnDarwin(config, lit_config)556 557min_macos_deployment_target_substitutions = [558 (10, 11),559 (10, 12),560]561# TLS requires watchOS 3+562config.substitutions.append(563 ("%darwin_min_target_with_tls_support", "%min_macos_deployment_target=10.12")564)565 566if config.target_os == "Darwin":567 osx_version = (10, 0, 0)568 try:569 osx_version = subprocess.check_output(570 ["sw_vers", "-productVersion"], universal_newlines=True571 )572 osx_version = tuple(int(x) for x in osx_version.split("."))573 if len(osx_version) == 2:574 osx_version = (osx_version[0], osx_version[1], 0)575 if osx_version >= (10, 11):576 config.available_features.add("osx-autointerception")577 config.available_features.add("osx-ld64-live_support")578 if osx_version >= (13, 1):579 config.available_features.add("jit-compatible-osx-swift-runtime")580 except subprocess.CalledProcessError:581 pass582 583 config.darwin_osx_version = osx_version584 585 # Detect x86_64h586 try:587 output = subprocess.check_output(["sysctl", "hw.cpusubtype"])588 output_re = re.match("^hw.cpusubtype: ([0-9]+)$", output)589 if output_re:590 cpu_subtype = int(output_re.group(1))591 if cpu_subtype == 8: # x86_64h592 config.available_features.add("x86_64h")593 except:594 pass595 596 # 32-bit iOS simulator is deprecated and removed in latest Xcode.597 if config.apple_platform == "iossim":598 if config.target_arch == "i386":599 config.unsupported = True600 601 def get_macos_aligned_version(macos_vers):602 platform = config.apple_platform603 macos_major, macos_minor = macos_vers604 605 if platform == "osx" or macos_major >= 26:606 return macos_vers607 608 assert macos_major >= 10609 if macos_major == 10: # macOS 10.x610 major = macos_minor611 minor = 0612 else: # macOS 11+613 major = macos_major + 5614 minor = macos_minor615 616 assert major >= 11617 618 if platform.startswith("ios") or platform.startswith("tvos"):619 major -= 2620 elif platform.startswith("watch"):621 major -= 9622 else:623 lit_config.fatal("Unsupported apple platform '{}'".format(platform))624 625 return (major, minor)626 627 for vers in min_macos_deployment_target_substitutions:628 flag = config.apple_platform_min_deployment_target_flag629 major, minor = get_macos_aligned_version(vers)630 apple_device = ""631 sim = ""632 if "target" in flag:633 apple_device = config.apple_platform.split("sim")[0]634 sim = "-simulator" if "sim" in config.apple_platform else ""635 636 config.substitutions.append(637 (638 "%%min_macos_deployment_target=%s.%s" % vers,639 "{}={}{}.{}{}".format(flag, apple_device, major, minor, sim),640 )641 )642else:643 for vers in min_macos_deployment_target_substitutions:644 config.substitutions.append(("%%min_macos_deployment_target=%s.%s" % vers, ""))645 646if config.android:647 env = os.environ.copy()648 if config.android_serial:649 env["ANDROID_SERIAL"] = config.android_serial650 config.environment["ANDROID_SERIAL"] = config.android_serial651 652 adb = os.environ.get("ADB", "adb")653 654 # These are needed for tests to upload/download temp files, such as655 # suppression-files, to device.656 config.substitutions.append(("%device_rundir/", "/data/local/tmp/Output/"))657 config.substitutions.append(658 ("%push_to_device", "%s -s '%s' push " % (adb, env["ANDROID_SERIAL"]))659 )660 config.substitutions.append(661 ("%adb_shell ", "%s -s '%s' shell " % (adb, env["ANDROID_SERIAL"]))662 )663 config.substitutions.append(664 ("%device_rm", "%s -s '%s' shell 'rm ' " % (adb, env["ANDROID_SERIAL"]))665 )666 667 try:668 android_api_level_str = subprocess.check_output(669 [adb, "shell", "getprop", "ro.build.version.sdk"], env=env670 ).rstrip()671 android_api_codename = (672 subprocess.check_output(673 [adb, "shell", "getprop", "ro.build.version.codename"], env=env674 )675 .rstrip()676 .decode("utf-8")677 )678 except (subprocess.CalledProcessError, OSError):679 lit_config.fatal(680 "Failed to read ro.build.version.sdk (using '%s' as adb)" % adb681 )682 try:683 android_api_level = int(android_api_level_str)684 except ValueError:685 lit_config.fatal(686 "Failed to read ro.build.version.sdk (using '%s' as adb): got '%s'"687 % (adb, android_api_level_str)688 )689 android_api_level = min(android_api_level, int(config.android_api_level))690 for required in [26, 28, 29, 30]:691 if android_api_level >= required:692 config.available_features.add("android-%s" % required)693 # FIXME: Replace with appropriate version when availible.694 if android_api_level > 30 or (695 android_api_level == 30 and android_api_codename == "S"696 ):697 config.available_features.add("android-thread-properties-api")698 699 # Prepare the device.700 android_tmpdir = "/data/local/tmp/Output"701 subprocess.check_call([adb, "shell", "mkdir", "-p", android_tmpdir], env=env)702 for file in config.android_files_to_push:703 subprocess.check_call([adb, "push", file, android_tmpdir], env=env)704else:705 config.substitutions.append(("%device_rundir/", ""))706 config.substitutions.append(("%push_to_device", "echo "))707 config.substitutions.append(("%adb_shell", "echo "))708 709if config.target_os == "Linux" and not config.android:710 # detect whether we are using glibc, and which version711 cmd_args = [712 config.clang.strip(),713 f"--target={config.target_triple}",714 "-xc",715 "-",716 "-o",717 "-",718 "-dM",719 "-E",720 ] + shlex.split(config.target_cflags)721 cmd = subprocess.Popen(722 cmd_args,723 stdout=subprocess.PIPE,724 stdin=subprocess.PIPE,725 stderr=subprocess.DEVNULL,726 env={"LANG": "C"},727 )728 try:729 sout, _ = cmd.communicate(b"#include <features.h>")730 m = dict(re.findall(r"#define (__GLIBC__|__GLIBC_MINOR__) (\d+)", str(sout)))731 major = int(m["__GLIBC__"])732 minor = int(m["__GLIBC_MINOR__"])733 any_glibc = False734 for required in [735 (2, 19),736 (2, 27),737 (2, 30),738 (2, 33),739 (2, 34),740 (2, 37),741 (2, 38),742 (2, 40),743 ]:744 if (major, minor) >= required:745 (required_major, required_minor) = required746 config.available_features.add(747 f"glibc-{required_major}.{required_minor}"748 )749 any_glibc = True750 if any_glibc:751 config.available_features.add("glibc")752 except:753 pass754 755sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov")756if os.path.exists(sancovcc_path):757 config.available_features.add("has_sancovcc")758 config.substitutions.append(("%sancovcc ", sancovcc_path))759 760 761def liblto_path():762 return os.path.join(config.llvm_shlib_dir, "libLTO.dylib")763 764 765def is_darwin_lto_supported():766 return os.path.exists(liblto_path())767 768 769def is_binutils_lto_supported():770 if not os.path.exists(os.path.join(config.llvm_shlib_dir, "LLVMgold.so")):771 return False772 773 # We require both ld.bfd and ld.gold exist and support plugins. They are in774 # the same repository 'binutils-gdb' and usually built together.775 for exe in (config.gnu_ld_executable, config.gold_executable):776 try:777 ld_cmd = subprocess.Popen(778 [exe, "--help"], stdout=subprocess.PIPE, env={"LANG": "C"}779 )780 ld_out = ld_cmd.stdout.read().decode()781 ld_cmd.wait()782 except OSError:783 return False784 if not "-plugin" in ld_out:785 return False786 787 return True788 789 790def is_lld_lto_supported():791 # LLD does support LTO, but we require it to be built with the latest792 # changes to claim support. Otherwise older copies of LLD may not793 # understand new bitcode versions.794 return os.path.exists(os.path.join(config.llvm_tools_dir, "lld"))795 796 797def is_windows_lto_supported():798 if not target_is_msvc:799 return True800 return os.path.exists(os.path.join(config.llvm_tools_dir, "lld-link.exe"))801 802 803if config.target_os == "Darwin" and is_darwin_lto_supported():804 config.lto_supported = True805 config.lto_flags = ["-Wl,-lto_library," + liblto_path()]806elif config.target_os in ["Linux", "FreeBSD", "NetBSD"]:807 config.lto_supported = False808 if config.use_lld and is_lld_lto_supported():809 config.lto_supported = True810 if is_binutils_lto_supported():811 config.available_features.add("binutils_lto")812 config.lto_supported = True813 814 if config.lto_supported:815 if config.use_lld:816 config.lto_flags = ["-fuse-ld=lld"]817 else:818 config.lto_flags = ["-fuse-ld=gold"]819elif config.target_os == "Windows" and is_windows_lto_supported():820 config.lto_supported = True821 config.lto_flags = ["-fuse-ld=lld"]822else:823 config.lto_supported = False824 825if config.lto_supported:826 config.available_features.add("lto")827 if config.use_thinlto:828 config.available_features.add("thinlto")829 config.lto_flags += ["-flto=thin"]830 else:831 config.lto_flags += ["-flto"]832 833if config.have_rpc_xdr_h:834 config.available_features.add("sunrpc")835 836# Sanitizer tests tend to be flaky on Windows due to PR24554, so add some837# retries. We don't do this on otther platforms because it's slower.838if platform.system() == "Windows":839 config.test_retry_attempts = 2840 841# No throttling on non-Darwin platforms.842lit_config.parallelism_groups["shadow-memory"] = None843 844if platform.system() == "Darwin":845 ios_device = config.apple_platform != "osx" and not config.apple_platform.endswith(846 "sim"847 )848 # Force sequential execution when running tests on iOS devices.849 if ios_device:850 lit_config.warning("Forcing sequential execution for iOS device tests")851 lit_config.parallelism_groups["ios-device"] = 1852 config.parallelism_group = "ios-device"853 854 # Only run up to 3 processes that require shadow memory simultaneously on855 # 64-bit Darwin. Using more scales badly and hogs the system due to856 # inefficient handling of large mmap'd regions (terabytes) by the kernel.857 else:858 lit_config.warning(859 "Throttling sanitizer tests that require shadow memory on Darwin"860 )861 lit_config.parallelism_groups["shadow-memory"] = 3862 863# Multiple substitutions are necessary to support multiple shared objects used864# at once.865# Note that substitutions with numbers have to be defined first to avoid866# being subsumed by substitutions with smaller postfix.867for postfix in ["2", "1", ""]:868 if config.target_os == "Darwin":869 config.substitutions.append(870 (871 "%ld_flags_rpath_exe" + postfix,872 "-Wl,-rpath,@executable_path/ %dynamiclib" + postfix,873 )874 )875 config.substitutions.append(876 (877 "%ld_flags_rpath_so" + postfix,878 "-install_name @rpath/%base_dynamiclib{}".format(postfix),879 )880 )881 elif config.target_os in ("FreeBSD", "NetBSD", "OpenBSD"):882 config.substitutions.append(883 (884 "%ld_flags_rpath_exe" + postfix,885 r"-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%t.dir -l%xdynamiclib_namespec"886 + postfix,887 )888 )889 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))890 elif config.target_os == "Linux":891 config.substitutions.append(892 (893 "%ld_flags_rpath_exe" + postfix,894 r"-Wl,-rpath,\$ORIGIN -L%t.dir -l%xdynamiclib_namespec" + postfix,895 )896 )897 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))898 elif config.target_os == "SunOS":899 config.substitutions.append(900 (901 "%ld_flags_rpath_exe" + postfix,902 r"-Wl,-R\$ORIGIN -L%t.dir -l%xdynamiclib_namespec" + postfix,903 )904 )905 config.substitutions.append(("%ld_flags_rpath_so" + postfix, ""))906 907 # Must be defined after the substitutions that use %dynamiclib.908 config.substitutions.append(909 ("%dynamiclib" + postfix, "%t.dir/%xdynamiclib_filename" + postfix)910 )911 config.substitutions.append(912 ("%base_dynamiclib" + postfix, "%xdynamiclib_filename" + postfix)913 )914 config.substitutions.append(915 (916 "%xdynamiclib_filename" + postfix,917 "lib%xdynamiclib_namespec{}.so".format(postfix),918 )919 )920 config.substitutions.append(("%xdynamiclib_namespec", "%basename_t.dynamic"))921 922config.default_sanitizer_opts = []923if config.target_os == "Darwin":924 # On Darwin, we default to `abort_on_error=1`, which would make tests run925 # much slower. Let's override this and run lit tests with 'abort_on_error=0'.926 config.default_sanitizer_opts += ["abort_on_error=0"]927 config.default_sanitizer_opts += ["log_to_syslog=0"]928 if lit.util.which("log"):929 # Querying the log can only done by a privileged user so930 # so check if we can query the log.931 exit_code = -1932 with open("/dev/null", "r") as f:933 # Run a `log show` command the should finish fairly quickly and produce very little output.934 exit_code = subprocess.call(935 ["log", "show", "--last", "1m", "--predicate", "1 == 0"],936 stdout=f,937 stderr=f,938 )939 if exit_code == 0:940 config.available_features.add("darwin_log_cmd")941 else:942 lit_config.warning("log command found but cannot queried")943 else:944 lit_config.warning("log command not found. Some tests will be skipped.")945elif config.android:946 config.default_sanitizer_opts += ["abort_on_error=0"]947 948# Allow tests to use REQUIRES=stable-runtime. For use when you cannot use XFAIL949# because the test hangs or fails on one configuration and not the other.950if config.android or (config.target_arch not in ["arm", "armhf", "aarch64"]):951 config.available_features.add("stable-runtime")952 953if config.asan_shadow_scale:954 config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale)955else:956 config.available_features.add("shadow-scale-3")957 958if config.memprof_shadow_scale:959 config.available_features.add(960 "memprof-shadow-scale-%s" % config.memprof_shadow_scale961 )962else:963 config.available_features.add("memprof-shadow-scale-3")964 965 966def target_page_size():967 try:968 proc = subprocess.Popen(969 f"{emulator or ''} python3",970 shell=True,971 stdin=subprocess.PIPE,972 stdout=subprocess.PIPE,973 )974 out, err = proc.communicate(975 b'import os; print(os.sysconf("SC_PAGESIZE") if hasattr(os, "sysconf") else "")'976 )977 return int(out)978 except:979 return 4096980 981 982config.available_features.add(f"page-size-{target_page_size()}")983 984if config.expensive_checks:985 config.available_features.add("expensive_checks")986 987# Propagate the LLD/LTO into the clang config option, so nothing else is needed.988run_wrapper = []989target_cflags = [getattr(config, "target_cflags", None)]990extra_cflags = []991 992if config.use_lto and config.lto_supported:993 extra_cflags += config.lto_flags994elif config.use_lto and (not config.lto_supported):995 config.unsupported = True996 997if config.use_lld and config.has_lld and not config.use_lto:998 extra_cflags += ["-fuse-ld=lld"]999elif config.use_lld and (not config.has_lld):1000 config.unsupported = True1001 1002if config.target_os == "Darwin":1003 if getattr(config, "darwin_linker_version", None):1004 extra_cflags += ["-mlinker-version=" + config.darwin_linker_version]1005 1006# Append any extra flags passed in lit_config1007append_target_cflags = lit_config.params.get("append_target_cflags", None)1008if append_target_cflags:1009 lit_config.note('Appending to extra_cflags: "{}"'.format(append_target_cflags))1010 extra_cflags += [append_target_cflags]1011 1012config.clang = (1013 " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " "1014)1015config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " "1016 1017if config.target_os == "Darwin":1018 config.substitutions.append(1019 (1020 "%get_pid_from_output",1021 "{} {}/get_pid_from_output.py".format(1022 shlex.quote(config.python_executable),1023 shlex.quote(get_ios_commands_dir()),1024 ),1025 )1026 )1027 config.substitutions.append(1028 (1029 "%print_crashreport_for_pid",1030 "{} {}/print_crashreport_for_pid.py".format(1031 shlex.quote(config.python_executable),1032 shlex.quote(get_ios_commands_dir()),1033 ),1034 )1035 )1036 1037# It is not realistically possible to account for all options that could1038# possibly be present in system and user configuration files, so disable1039# default configs for the test runs. In particular, anything hardening1040# related is likely to cause issues with sanitizer tests, because it may1041# preempt something we're looking to trap (e.g. _FORTIFY_SOURCE vs our ASAN).1042#1043# Only set this if we know we can still build for the target while disabling1044# default configs.1045if config.has_no_default_config_flag:1046 config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1"1047 1048if config.has_compiler_rt_libatomic:1049 base_lib = os.path.join(config.compiler_rt_libdir, "libclang_rt.atomic%s.so"1050 % config.target_suffix)1051 if sys.platform in ['win32'] and execute_external:1052 # Don't pass dosish path separator to msys bash.exe.1053 base_lib = base_lib.replace('\\', '/')1054 config.substitutions.append(("%libatomic", base_lib + f" -Wl,-rpath,{config.compiler_rt_libdir}"))1055else:1056 config.substitutions.append(("%libatomic", "-latomic"))1057 1058# Set LD_LIBRARY_PATH to pick dynamic runtime up properly.1059push_dynamic_library_lookup_path(config, config.compiler_rt_libdir)1060 1061# GCC-ASan uses dynamic runtime by default.1062if config.compiler_id == "GNU":1063 gcc_dir = os.path.dirname(config.clang)1064 libasan_dir = os.path.join(gcc_dir, "..", "lib" + config.bits)1065 push_dynamic_library_lookup_path(config, libasan_dir)1066 1067 1068# Help tests that make sure certain files are in-sync between compiler-rt and1069# llvm.1070config.substitutions.append(("%crt_src", config.compiler_rt_src_root))1071config.substitutions.append(("%llvm_src", config.llvm_src_root))1072 1073config.substitutions.append(("%python", '"%s"' % (sys.executable)))1074