1import os 2import platform 3import re 4import subprocess 5import sys 6 7import lit.formats 8import lit.util 9 10from lit.llvm import llvm_config 11from lit.llvm.subst import ToolSubst 12 13# Configuration file for the 'lit' test runner. 14 15# name: The name of this test suite. 16config.name = "cross-project-tests" 17 18# testFormat: The test format to use to interpret tests. 19config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) 20 21# suffixes: A list of file extensions to treat as test files. 22config.suffixes = [".c", ".cl", ".cpp", ".m"] 23 24# excludes: A list of directories to exclude from the testsuite. The 'Inputs' 25# subdirectories contain auxiliary inputs for various tests in their parent 26# directories. 27config.excludes = ["Inputs"] 28 29# test_source_root: The root path where tests are located. 30config.test_source_root = config.cross_project_tests_src_root 31 32# test_exec_root: The root path where tests should be run. 33config.test_exec_root = config.cross_project_tests_obj_root 34 35llvm_config.use_default_substitutions() 36 37tools = [ 38 ToolSubst( 39 "%test_debuginfo", 40 command=os.path.join( 41 config.cross_project_tests_src_root, 42 "debuginfo-tests", 43 "llgdb-tests", 44 "test_debuginfo.pl", 45 ), 46 ), 47 ToolSubst("%llvm_src_root", config.llvm_src_root), 48 ToolSubst("%llvm_tools_dir", config.llvm_tools_dir), 49] 50 51 52def get_required_attr(config, attr_name): 53 attr_value = getattr(config, attr_name, None) 54 if attr_value is None: 55 lit_config.fatal( 56 "No attribute %r in test configuration! You may need to run " 57 "tests from your build directory or add this attribute " 58 "to lit.site.cfg " % attr_name 59 ) 60 return attr_value 61 62 63# If this is an MSVC environment, the tests at the root of the tree are 64# unsupported. The local win_cdb test suite, however, is supported. 65is_msvc = get_required_attr(config, "is_msvc") 66if is_msvc: 67 config.available_features.add("msvc") 68 # FIXME: We should add some llvm lit utility code to find the Windows SDK 69 # and set up the environment appopriately. 70 win_sdk = "C:/Program Files (x86)/Windows Kits/10/" 71 arch = "x64" 72 llvm_config.with_system_environment(["LIB", "LIBPATH", "INCLUDE"]) 73 # Clear _NT_SYMBOL_PATH to prevent cdb from attempting to load symbols from 74 # the network. 75 llvm_config.with_environment("_NT_SYMBOL_PATH", "") 76 tools.append( 77 ToolSubst("%cdb", '"%s"' % os.path.join(win_sdk, "Debuggers", arch, "cdb.exe")) 78 ) 79 80# clang_src_dir and lld_src_dir are not used by these tests, but are required by 81# use_clang() and use_lld() respectively, so set them to "", if needed. 82if not hasattr(config, "clang_src_dir"): 83 config.clang_src_dir = "" 84llvm_config.use_clang(required=("clang" in config.llvm_enabled_projects)) 85 86if not hasattr(config, "lld_src_dir"): 87 config.lld_src_dir = "" 88llvm_config.use_lld(required=("lld" in config.llvm_enabled_projects)) 89 90if "compiler-rt" in config.llvm_enabled_projects: 91 config.available_features.add("compiler-rt") 92 93# Check which debuggers are available: 94lldb_path = llvm_config.use_llvm_tool("lldb", search_env="LLDB") 95 96if lldb_path is not None: 97 config.available_features.add("lldb") 98 99 100def configure_dexter_substitutions(): 101 """Configure substitutions for host platform and return list of dependencies""" 102 # Produce dexter path, lldb path, and combine into the %dexter substitution 103 # for running a test. 104 dexter_path = os.path.join( 105 config.cross_project_tests_src_root, "debuginfo-tests", "dexter", "dexter.py" 106 ) 107 dexter_test_cmd = '"{}" "{}" test'.format(sys.executable, dexter_path) 108 if lldb_path is not None: 109 dexter_test_cmd += ' --lldb-executable "{}"'.format(lldb_path) 110 tools.append(ToolSubst("%dexter", dexter_test_cmd)) 111 112 # For testing other bits of dexter that aren't under the "test" subcommand, 113 # have a %dexter_base substitution. 114 dexter_base_cmd = '"{}" "{}"'.format(sys.executable, dexter_path) 115 tools.append(ToolSubst("%dexter_base", dexter_base_cmd)) 116 117 # Set up commands for DexTer regression tests. 118 # Builder, debugger, optimisation level and several other flags differ 119 # depending on whether we're running a unix like or windows os. 120 if platform.system() == "Windows": 121 # The Windows builder script uses lld. 122 dependencies = ["clang", "lld-link"] 123 dexter_regression_test_builder = "clang-cl" 124 dexter_regression_test_debugger = "dbgeng" 125 dexter_regression_test_flags = "/Zi /Od" 126 else: 127 # Use lldb as the debugger on non-Windows platforms. 128 dependencies = ["clang", "lldb"] 129 dexter_regression_test_builder = "clang++" 130 dexter_regression_test_debugger = "lldb" 131 dexter_regression_test_flags = "-O0 -glldb -std=gnu++11" 132 133 tools.append( 134 ToolSubst("%dexter_regression_test_builder", dexter_regression_test_builder) 135 ) 136 tools.append( 137 ToolSubst("%dexter_regression_test_debugger", dexter_regression_test_debugger) 138 ) 139 # We don't need to distinguish cflags and ldflags because for Dexter 140 # regression tests we use clang to drive the linker, and so all flags will be 141 # passed in a single command. 142 tools.append( 143 ToolSubst("%dexter_regression_test_flags", dexter_regression_test_flags) 144 ) 145 146 # Typical command would take the form: 147 # ./path_to_py/python.exe ./path_to_dex/dexter.py test --fail-lt 1.0 -w --binary %t --debugger lldb --cflags '-O0 -g' 148 dexter_regression_test_run = " ".join( 149 # "python", "dexter.py", test, fail_mode, builder, debugger, cflags, ldflags 150 [ 151 '"{}"'.format(sys.executable), 152 '"{}"'.format(dexter_path), 153 "test", 154 "--fail-lt 1.0 -w", 155 "--debugger", 156 dexter_regression_test_debugger, 157 ] 158 ) 159 tools.append(ToolSubst("%dexter_regression_test_run", dexter_regression_test_run)) 160 161 # Include build flags for %dexter_regression_test. 162 dexter_regression_test_build = " ".join( 163 [ 164 dexter_regression_test_builder, 165 dexter_regression_test_flags, 166 ] 167 ) 168 tools.append(ToolSubst("%dexter_regression_test_build", dexter_regression_test_build)) 169 return dependencies 170 171 172def add_host_triple(clang): 173 return "{} --target={}".format(clang, config.host_triple) 174 175 176# The set of arches we can build. 177targets = set(config.targets_to_build) 178# Add aliases to the target set. 179if "AArch64" in targets: 180 targets.add("arm64") 181if "ARM" in config.targets_to_build: 182 targets.add("thumbv7") 183 184 185def can_target_host(): 186 # Check if the targets set contains anything that looks like our host arch. 187 # The arch name in the triple and targets set may be spelled differently 188 # (e.g. x86 vs X86). 189 return any(config.host_triple.lower().startswith(x.lower()) for x in targets) 190 191 192# Dexter tests run on the host machine. If the host arch is supported add 193# 'dexter' as an available feature and force the dexter tests to use the host 194# triple. 195if can_target_host(): 196 if config.host_triple != config.target_triple: 197 print("Forcing dexter tests to use host triple {}.".format(config.host_triple)) 198 dependencies = configure_dexter_substitutions() 199 if all(d in config.available_features for d in dependencies): 200 config.available_features.add("dexter") 201 llvm_config.with_environment( 202 "PATHTOCLANG", add_host_triple(llvm_config.config.clang) 203 ) 204 llvm_config.with_environment( 205 "PATHTOCLANGPP", add_host_triple(llvm_config.use_llvm_tool("clang++")) 206 ) 207 llvm_config.with_environment( 208 "PATHTOCLANGCL", add_host_triple(llvm_config.use_llvm_tool("clang-cl")) 209 ) 210else: 211 print( 212 "Host triple {} not supported. Skipping dexter tests in the " 213 "debuginfo-tests project.".format(config.host_triple) 214 ) 215 216tool_dirs = [config.llvm_tools_dir] 217 218llvm_config.add_tool_substitutions(tools, tool_dirs) 219 220lit.util.usePlatformSdkOnDarwin(config, lit_config) 221 222if platform.system() == "Darwin": 223 xcode_lldb_vers = subprocess.check_output(["xcrun", "lldb", "--version"]).decode( 224 "utf-8" 225 ) 226 match = re.search(r"lldb-(\d+)", xcode_lldb_vers) 227 if match: 228 apple_lldb_vers = int(match.group(1)) 229 if apple_lldb_vers < 1000: 230 config.available_features.add("apple-lldb-pre-1000") 231 232 233def get_gdb_version_string(): 234 """Return gdb's version string, or None if gdb cannot be found or the 235 --version output is formatted unexpectedly. 236 """ 237 # See if we can get a gdb version, e.g. 238 # $ gdb --version 239 # GNU gdb (GDB) 10.2 240 # ...More stuff... 241 try: 242 gdb_vers_lines = ( 243 subprocess.check_output(["gdb", "--version"]).decode().splitlines() 244 ) 245 except: 246 return None # We coudln't find gdb or something went wrong running it. 247 if len(gdb_vers_lines) < 1: 248 print("Unkown GDB version format (too few lines)", file=sys.stderr) 249 return None 250 match = re.search(r"GNU gdb \(.*?\) ((\d|\.)+)", gdb_vers_lines[0].strip()) 251 if match is None: 252 print(f"Unkown GDB version format: {gdb_vers_lines[0]}", file=sys.stderr) 253 return None 254 return match.group(1) 255 256 257def get_clang_default_dwarf_version_string(triple): 258 """Return the default dwarf version string for clang on this (host) platform 259 or None if we can't work it out. 260 """ 261 # Get the flags passed by the driver and look for -dwarf-version. 262 cmd = f'{llvm_config.use_llvm_tool("clang")} -g -xc -c - -v -### --target={triple}' 263 stderr = subprocess.run(cmd.split(), stderr=subprocess.PIPE).stderr.decode() 264 match = re.search(r"-dwarf-version=(\d+)", stderr) 265 if match is None: 266 print("Cannot determine default dwarf version", file=sys.stderr) 267 return None 268 return match.group(1) 269 270 271# Some cross-project-tests use gdb, but not all versions of gdb are compatible 272# with clang's dwarf. Add feature `gdb-clang-incompatibility` to signal that 273# there's an incompatibility between clang's default dwarf version for this 274# platform and the installed gdb version. 275dwarf_version_string = get_clang_default_dwarf_version_string(config.host_triple) 276gdb_version_string = get_gdb_version_string() 277if dwarf_version_string and gdb_version_string: 278 if int(dwarf_version_string) >= 5: 279 try: 280 from packaging import version 281 except: 282 lit_config.fatal("Running gdb tests requires the packaging package") 283 if version.parse(gdb_version_string) < version.parse("10.1"): 284 # Example for llgdb-tests, which use lldb on darwin but gdb elsewhere: 285 # XFAIL: !system-darwin && gdb-clang-incompatibility 286 config.available_features.add("gdb-clang-incompatibility") 287 print( 288 "XFAIL some tests: use gdb version >= 10.1 to restore test coverage", 289 file=sys.stderr, 290 ) 291 292llvm_config.feature_config([("--build-mode", {"Debug|RelWithDebInfo": "debug-info"})]) 293 294# Allow 'REQUIRES: XXX-registered-target' in tests. 295for arch in config.targets_to_build: 296 config.available_features.add(arch.lower() + "-registered-target") 297