brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.1 KiB · dce01cc Raw
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