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