1# -*- Python -*- 2 3# Configuration file for 'lit' test runner. 4# This file contains common rules for various compiler-rt testsuites. 5# It is mostly copied from lit.cfg.py used by Clang. 6import os 7import platform 8import re 9import shlex 10import subprocess 11import json 12 13import lit.formats 14import lit.util 15 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 = None 24 try: 25 result = subprocess.run( 26 clang_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True 27 ) 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 36 37 38def 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}" 46 ) 47 # TODO: Support other compilers. 48 return None 49 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 54 ) 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}." 63 ) 64 return None 65 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) 75 76 lit_config.warning("Failed to determine compiler's runtime directory") 77 return None 78 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_path 94 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_path 101 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_32 108 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_64 114 115 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. 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, as 124 # 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 substitutions 128config.recursiveExpansionLimit = 10 129 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 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") 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 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. 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_libdir 173 ) 174 elif config.target_arch == "x86_64": 175 config.compiler_rt_libdir = re.sub( 176 r"/i386(?=-[^/]+$)", "/x86_64", config.compiler_rt_libdir 177 ) 178 if config.target_arch == "sparc": 179 config.compiler_rt_libdir = re.sub( 180 r"/sparcv9(?=-[^/]+$)", "/sparc", config.compiler_rt_libdir 181 ) 182 elif config.target_arch == "sparcv9": 183 config.compiler_rt_libdir = re.sub( 184 r"/sparc(?=-[^/]+$)", "/sparcv9", config.compiler_rt_libdir 185 ) 186 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. 192test_cc_resource_dir, _ = get_path_from_clang( 193 shlex.split(config.target_cflags) + ["-print-resource-dir"], allow_failure=True 194) 195# Normalize the path for comparison 196if test_cc_resource_dir is not None: 197 test_cc_resource_dir = os.path.realpath(test_cc_resource_dir) 198if lit_config.debug: 199 lit_config.note(f"Resource dir for {config.clang} is {test_cc_resource_dir}") 200local_build_resource_dir = os.path.realpath(config.compiler_rt_output_dir) 201if 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}"' 207 ) 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}" 226 ) 227 228 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. 233compiler_libdir = find_compiler_libdir() 234if 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}"' 241 ) 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." 255 ) 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}"') 260 261# If needed, add cflag for shadow scale. 262if config.asan_shadow_scale != "": 263 config.target_cflags += " -mllvm -asan-mapping-scale=" + config.asan_shadow_scale 264if config.memprof_shadow_scale != "": 265 config.target_cflags += ( 266 " -mllvm -memprof-mapping-scale=" + config.memprof_shadow_scale 267 ) 268 269# Clear some environment variables that might affect Clang. 270possibly_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", 294] 295# Clang/MSVC may refer to %INCLUDE%. vsvarsall.bat sets it. 296if not (platform.system() == "Windows" and target_is_msvc): 297 possibly_dangerous_env_vars.append("INCLUDE") 298for name in possibly_dangerous_env_vars: 299 if name in config.environment: 300 del config.environment[name] 301 302# Tweak PATH to include llvm tools dir. 303if (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 306 ) 307path = os.path.pathsep.join((config.llvm_tools_dir, config.environment["PATH"])) 308config.environment["PATH"] = path 309 310# Help MSVS link.exe find the standard libraries. 311# Make sure we only try to use it when targetting Windows. 312if platform.system() == "Windows" and target_is_msvc: 313 config.environment["LIB"] = os.environ["LIB"] 314 315config.available_features.add(config.host_os.lower()) 316 317if config.target_triple.startswith("ppc") or config.target_triple.startswith("powerpc"): 318 config.available_features.add("ppc") 319 320if re.match(r"^x86_64.*-linux", config.target_triple): 321 config.available_features.add("x86_64-linux") 322 323config.available_features.add("host-byteorder-" + sys.byteorder + "-endian") 324 325if 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)) 329 330if config.have_internal_symbolizer: 331 config.available_features.add("internal_symbolizer") 332 333# Use ugly construction to explicitly prohibit "clang", "clang++" etc. 334# in RUN lines. 335config.substitutions.append( 336 ( 337 " clang", 338 """\n\n*** Do not use 'clangXXX' in tests, 339 instead define '%clangXXX' substitution in lit config. ***\n\n""", 340 ) 341) 342 343if config.host_os == "NetBSD": 344 nb_commands_dir = os.path.join( 345 config.compiler_rt_src_root, "test", "sanitizer_common", "netbsd_commands" 346 ) 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" 350 ) 351 config.substitutions.append(("%run_nomprotect", config.netbsd_nomprotect_prefix)) 352else: 353 config.substitutions.append(("%run_nomprotect", "%run")) 354 355# Copied from libcxx's config.py 356def 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 364 365 366emulator = get_lit_conf("emulator", None) 367 368 369def get_ios_commands_dir(): 370 return os.path.join( 371 config.compiler_rt_src_root, "test", "sanitizer_common", "ios_commands" 372 ) 373 374 375# Allow tests to be executed on a simulator or remotely. 376if 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 = "" 384elif 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. 388 # 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 # ========================================================================= 400 401 ios_or_iossim = "iossim" if config.apple_platform.endswith("sim") else "ios" 402 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 411 ) 412 ) 413 if config.apple_platform != "ios" and config.apple_platform != "iossim": 414 config.available_features.add(config.apple_platform) 415 416 ios_commands_dir = get_ios_commands_dir() 417 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") 422 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 431 432 try: 433 prepare_output = ( 434 subprocess.check_output( 435 [prepare_script, config.apple_platform, config.clang] 436 ) 437 .decode() 438 .strip() 439 ) 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"]) 449elif 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", 458 ) 459 + " " 460 ) 461 config.compile_wrapper = compile_wrapper 462 config.substitutions.append(("%run", "")) 463 config.substitutions.append(("%env ", "env ")) 464else: 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 = "" 470 471# Define CHECK-%os to check for OS-dependent output. 472config.substitutions.append(("CHECK-%os", ("CHECK-" + config.host_os))) 473 474# Define %arch to check for architecture-dependent output. 475config.substitutions.append(("%arch", (config.host_arch))) 476 477if 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 " 483else: 484 config.expect_crash = "not --crash " 485 486config.substitutions.append(("%expect_crash ", config.expect_crash)) 487 488target_arch = getattr(config, "target_arch", None) 489if 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()) 494 495compiler_rt_debug = getattr(config, "compiler_rt_debug", False) 496if not compiler_rt_debug: 497 config.available_features.add("compiler-rt-optimized") 498 499libdispatch = getattr(config, "compiler_rt_intercept_libdispatch", False) 500if libdispatch: 501 config.available_features.add("libdispatch") 502 503sanitizer_can_use_cxxabi = getattr(config, "sanitizer_can_use_cxxabi", True) 504if sanitizer_can_use_cxxabi: 505 config.available_features.add("cxxabi") 506 507if not getattr(config, "sanitizer_uses_static_cxxabi", False): 508 config.available_features.add("shared_cxxabi") 509 510if not getattr(config, "sanitizer_uses_static_unwind", False): 511 config.available_features.add("shared_unwind") 512 513if config.has_lld: 514 config.available_features.add("lld-available") 515 516if config.aarch64_sme: 517 config.available_features.add("aarch64-sme-available") 518 519if config.use_lld: 520 config.available_features.add("lld") 521 522if config.can_symbolize: 523 config.available_features.add("can-symbolize") 524 525if config.gwp_asan: 526 config.available_features.add("gwp_asan") 527 528lit.util.usePlatformSdkOnDarwin(config, lit_config) 529 530min_macos_deployment_target_substitutions = [ 531 (10, 11), 532 (10, 12), 533] 534# TLS requires watchOS 3+ 535config.substitutions.append( 536 ("%darwin_min_target_with_tls_support", "%min_macos_deployment_target=10.12") 537) 538 539if 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 544 ) 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 555 556 config.darwin_osx_version = osx_version 557 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 568 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 573 574 def get_macos_aligned_version(macos_vers): 575 platform = config.apple_platform 576 if platform == "osx": 577 return macos_vers 578 579 macos_major, macos_minor = macos_vers 580 assert macos_major >= 10 581 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 588 589 assert major >= 11 590 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)) 597 598 return (major, minor) 599 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 "" 608 609 config.substitutions.append( 610 ( 611 "%%min_macos_deployment_target=%s.%s" % vers, 612 "{}={}{}.{}{}".format(flag, apple_device, major, minor, sim), 613 ) 614 ) 615else: 616 for vers in min_macos_deployment_target_substitutions: 617 config.substitutions.append(("%%min_macos_deployment_target=%s.%s" % vers, "")) 618 619if 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 624 625 adb = os.environ.get("ADB", "adb") 626 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"])) 632 ) 633 config.substitutions.append( 634 ("%adb_shell ", "%s -s '%s' shell " % (adb, env["ANDROID_SERIAL"])) 635 ) 636 config.substitutions.append( 637 ("%device_rm", "%s -s '%s' shell 'rm ' " % (adb, env["ANDROID_SERIAL"])) 638 ) 639 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 647 ) 648 .rstrip() 649 .decode("utf-8") 650 ) 651 except (subprocess.CalledProcessError, OSError): 652 lit_config.fatal( 653 "Failed to read ro.build.version.sdk (using '%s' as adb)" % adb 654 ) 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) 661 ) 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" 669 ): 670 config.available_features.add("android-thread-properties-api") 671 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) 677else: 678 config.substitutions.append(("%device_rundir/", "")) 679 config.substitutions.append(("%push_to_device", "echo ")) 680 config.substitutions.append(("%adb_shell", "echo ")) 681 682if config.host_os == "Linux": 683 def add_glibc_versions(ver_string): 684 if config.android: 685 return 686 687 from distutils.version import LooseVersion 688 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", 700 ]: 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") 706 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"}, 724 ) 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 731 732sancovcc_path = os.path.join(config.llvm_tools_dir, "sancov") 733if os.path.exists(sancovcc_path): 734 config.available_features.add("has_sancovcc") 735 config.substitutions.append(("%sancovcc ", sancovcc_path)) 736 737 738def liblto_path(): 739 return os.path.join(config.llvm_shlib_dir, "libLTO.dylib") 740 741 742def is_darwin_lto_supported(): 743 return os.path.exists(liblto_path()) 744 745 746def is_binutils_lto_supported(): 747 if not os.path.exists(os.path.join(config.llvm_shlib_dir, "LLVMgold.so")): 748 return False 749 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"} 756 ) 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 763 764 return True 765 766 767def 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")) 772 773 774def 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")) 778 779 780if config.host_os == "Darwin" and is_darwin_lto_supported(): 781 config.lto_supported = True 782 config.lto_flags = ["-Wl,-lto_library," + liblto_path()] 783elif 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 790 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"] 796elif config.host_os == "Windows" and is_windows_lto_supported(): 797 config.lto_supported = True 798 config.lto_flags = ["-fuse-ld=lld"] 799else: 800 config.lto_supported = False 801 802if 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"] 809 810if config.have_rpc_xdr_h: 811 config.available_features.add("sunrpc") 812 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. 815if platform.system() == "Windows": 816 config.test_retry_attempts = 2 817 818# No throttling on non-Darwin platforms. 819lit_config.parallelism_groups["shadow-memory"] = None 820 821if platform.system() == "Darwin": 822 ios_device = config.apple_platform != "osx" and not config.apple_platform.endswith( 823 "sim" 824 ) 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" 830 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" 837 ) 838 lit_config.parallelism_groups["shadow-memory"] = 3 839 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. 844for postfix in ["2", "1", ""]: 845 if config.host_os == "Darwin": 846 config.substitutions.append( 847 ( 848 "%ld_flags_rpath_exe" + postfix, 849 "-Wl,-rpath,@executable_path/ %dynamiclib" + postfix, 850 ) 851 ) 852 config.substitutions.append( 853 ( 854 "%ld_flags_rpath_so" + postfix, 855 "-install_name @rpath/`basename %dynamiclib{}`".format(postfix), 856 ) 857 ) 858 elif config.host_os in ("FreeBSD", "NetBSD", "OpenBSD"): 859 config.substitutions.append( 860 ( 861 "%ld_flags_rpath_exe" + postfix, 862 r"-Wl,-z,origin -Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" 863 + postfix, 864 ) 865 ) 866 config.substitutions.append(("%ld_flags_rpath_so" + postfix, "")) 867 elif config.host_os == "Linux": 868 config.substitutions.append( 869 ( 870 "%ld_flags_rpath_exe" + postfix, 871 r"-Wl,-rpath,\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix, 872 ) 873 ) 874 config.substitutions.append(("%ld_flags_rpath_so" + postfix, "")) 875 elif config.host_os == "SunOS": 876 config.substitutions.append( 877 ( 878 "%ld_flags_rpath_exe" + postfix, 879 r"-Wl,-R\$ORIGIN -L%T -l%xdynamiclib_namespec" + postfix, 880 ) 881 ) 882 config.substitutions.append(("%ld_flags_rpath_so" + postfix, "")) 883 884 # Must be defined after the substitutions that use %dynamiclib. 885 config.substitutions.append( 886 ("%dynamiclib" + postfix, "%T/%xdynamiclib_filename" + postfix) 887 ) 888 config.substitutions.append( 889 ( 890 "%xdynamiclib_filename" + postfix, 891 "lib%xdynamiclib_namespec{}.so".format(postfix), 892 ) 893 ) 894 config.substitutions.append(("%xdynamiclib_namespec", "%basename_t.dynamic")) 895 896config.default_sanitizer_opts = [] 897if 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, 912 ) 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.") 919elif config.android: 920 config.default_sanitizer_opts += ["abort_on_error=0"] 921 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. 924if config.android or (config.target_arch not in ["arm", "armhf", "aarch64"]): 925 config.available_features.add("stable-runtime") 926 927if config.asan_shadow_scale: 928 config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale) 929else: 930 config.available_features.add("shadow-scale-3") 931 932if config.memprof_shadow_scale: 933 config.available_features.add( 934 "memprof-shadow-scale-%s" % config.memprof_shadow_scale 935 ) 936else: 937 config.available_features.add("memprof-shadow-scale-3") 938 939if config.expensive_checks: 940 config.available_features.add("expensive_checks") 941 942# Propagate the LLD/LTO into the clang config option, so nothing else is needed. 943run_wrapper = [] 944target_cflags = [getattr(config, "target_cflags", None)] 945extra_cflags = [] 946 947if config.use_lto and config.lto_supported: 948 extra_cflags += config.lto_flags 949elif config.use_lto and (not config.lto_supported): 950 config.unsupported = True 951 952if config.use_lld and config.has_lld and not config.use_lto: 953 extra_cflags += ["-fuse-ld=lld"] 954elif config.use_lld and (not config.has_lld): 955 config.unsupported = True 956 957if config.host_os == "Darwin": 958 if getattr(config, "darwin_linker_version", None): 959 extra_cflags += ["-mlinker-version=" + config.darwin_linker_version] 960 961# Append any extra flags passed in lit_config 962append_target_cflags = lit_config.params.get("append_target_cflags", None) 963if append_target_cflags: 964 lit_config.note('Appending to extra_cflags: "{}"'.format(append_target_cflags)) 965 extra_cflags += [append_target_cflags] 966 967config.clang = ( 968 " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " " 969) 970config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " " 971 972if config.host_os == "Darwin": 973 config.substitutions.append( 974 ( 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()), 979 ), 980 ) 981 ) 982 config.substitutions.append( 983 ( 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()), 988 ), 989 ) 990 ) 991 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). 997# 998# Only set this if we know we can still build for the target while disabling 999# default configs. 1000if config.has_no_default_config_flag: 1001 config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1" 1002 1003if 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}")) 1010else: 1011 config.substitutions.append(("%libatomic", "-latomic")) 1012 1013# Set LD_LIBRARY_PATH to pick dynamic runtime up properly. 1014push_dynamic_library_lookup_path(config, config.compiler_rt_libdir) 1015 1016# GCC-ASan uses dynamic runtime by default. 1017if 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) 1021 1022 1023# Help tests that make sure certain files are in-sync between compiler-rt and 1024# llvm. 1025config.substitutions.append(("%crt_src", config.compiler_rt_src_root)) 1026config.substitutions.append(("%llvm_src", config.llvm_src_root)) 1027