308 lines · python
1import os2import itertools3import platform4import re5import subprocess6import sys7 8import lit.util9from lit.formats import ShTest10from lit.llvm import llvm_config11from lit.llvm.subst import FindTool12from lit.llvm.subst import ToolSubst13 14import posixpath15 16def _get_lldb_init_path(config):17 return os.path.join(config.test_exec_root, "lit-lldb-init-quiet")18 19 20def _disallow(config, execName):21 warning = """22 echo '*** Do not use \'{0}\' in tests; use \'%''{0}\'. ***' &&23 exit 1 && echo24 """25 config.substitutions.append((" {0} ".format(execName), warning.format(execName)))26 27 28def get_lldb_args(config, suffix=""):29 lldb_args = []30 if "remote-linux" in config.available_features:31 lldb_args += [32 "-O",33 '"platform select remote-linux"',34 "-O",35 f'"platform connect {config.lldb_platform_url}"',36 ]37 if config.lldb_platform_working_dir:38 dir = posixpath.join(f"{config.lldb_platform_working_dir}", "shell")39 if suffix:40 dir += posixpath.join(dir, f"{suffix}")41 lldb_args += [42 "-O",43 f'"platform shell mkdir -p {dir}"',44 "-O",45 f'"platform settings -w {dir}"',46 ]47 lldb_args += ["--no-lldbinit", "-S", _get_lldb_init_path(config)]48 return lldb_args49 50 51class ShTestLldb(ShTest):52 def __init__(53 self, execute_external=False, extra_substitutions=[], preamble_commands=[]54 ):55 super().__init__(execute_external, extra_substitutions, preamble_commands)56 57 def execute(self, test, litConfig):58 # Run each Shell test in a separate directory (on remote).59 60 # Find directory change command in %lldb substitution.61 for i, t in enumerate(test.config.substitutions):62 if re.match(t[0], "%lldb"):63 cmd = t[1]64 if '-O "platform settings -w ' in cmd:65 # If command is present, it is added by get_lldb_args.66 # Replace the path with the tests' path in suite.67 # Example:68 # bin/lldb69 # -O "platform shell mkdir -p /home/user/shell"70 # -O "platform settings -w /home/user/shell" ...71 # =>72 # bin/lldb73 # -O "platform shell mkdir -p /home/user/shell/SymbolFile/Breakpad/inline-record.test"74 # -O "platform settings -w /home/user/shell/SymbolFile/Breakpad/inline-record.test" ...75 args_def = " ".join(get_lldb_args(test.config))76 args_unique = " ".join(77 get_lldb_args(78 test.config,79 posixpath.join(*test.path_in_suite),80 )81 )82 test.config.substitutions[i] = (83 t[0],84 cmd.replace(args_def, args_unique),85 )86 break87 return super().execute(test, litConfig)88 89 90def use_lldb_substitutions(config):91 # Set up substitutions for primary tools. These tools must come from config.lldb_tools_dir92 # which is basically the build output directory. We do not want to find these in path or93 # anywhere else, since they are specifically the programs which are actually being tested.94 95 dsname = "debugserver" if platform.system() in ["Darwin"] else "lldb-server"96 dsargs = [] if platform.system() in ["Darwin"] else ["gdbserver"]97 98 build_script = os.path.dirname(__file__)99 build_script = os.path.join(build_script, "build.py")100 build_script_args = [101 build_script,102 (103 "--compiler=clang" if config.enable_remote else "--compiler=any"104 ), # Default to best compiler105 "--arch=" + str(config.lldb_bitness),106 ]107 if config.lldb_lit_tools_dir:108 build_script_args.append("--tools-dir={0}".format(config.lldb_lit_tools_dir))109 if config.lldb_tools_dir:110 build_script_args.append("--tools-dir={0}".format(config.lldb_tools_dir))111 if config.llvm_libs_dir:112 build_script_args.append("--libs-dir={0}".format(config.llvm_libs_dir))113 if config.objc_gnustep_dir:114 build_script_args.append(115 '--objc-gnustep-dir="{0}"'.format(config.objc_gnustep_dir)116 )117 if config.cmake_sysroot:118 build_script_args.append("--sysroot={0}".format(config.cmake_sysroot))119 120 lldb_init = _get_lldb_init_path(config)121 122 primary_tools = [123 ToolSubst(124 "%lldb",125 command=FindTool("lldb"),126 extra_args=get_lldb_args(config),127 unresolved="fatal",128 ),129 ToolSubst(130 "%lldb-init",131 command=FindTool("lldb"),132 extra_args=["-S", lldb_init],133 unresolved="fatal",134 ),135 ToolSubst(136 "%lldb-noinit",137 command=FindTool("lldb"),138 extra_args=["--no-lldbinit"],139 unresolved="fatal",140 ),141 ToolSubst(142 "%lldb-server",143 command=FindTool("lldb-server"),144 extra_args=[],145 unresolved="ignore",146 ),147 ToolSubst(148 "%debugserver",149 command=FindTool(dsname),150 extra_args=dsargs,151 unresolved="ignore",152 ),153 ToolSubst(154 "%platformserver",155 command=FindTool("lldb-server"),156 extra_args=["platform"],157 unresolved="ignore",158 ),159 ToolSubst(160 "%lldb-rpc-gen",161 command=FindTool("lldb-rpc-gen"),162 # We need the LLDB build directory root to pass into the tool, not the test build root.163 extra_args=[164 "-p " + config.lldb_build_directory + "/..",165 '--extra-arg="-resource-dir=' + config.clang_resource_dir + '"',166 ],167 unresolved="ignore",168 ),169 "lldb-test",170 "lldb-dap",171 ToolSubst(172 "%build", command="'" + sys.executable + "'", extra_args=build_script_args173 ),174 ]175 176 _disallow(config, "lldb")177 _disallow(config, "lldb-server")178 _disallow(config, "debugserver")179 _disallow(config, "platformserver")180 181 llvm_config.add_tool_substitutions(primary_tools, [config.lldb_tools_dir])182 183 184def _use_msvc_substitutions(config):185 # If running from a Visual Studio Command prompt (e.g. vcvars), this will186 # detect the include and lib paths, and find cl.exe and link.exe and create187 # substitutions for each of them that explicitly specify /I and /L paths188 cl = lit.util.which("cl")189 190 if not cl:191 return192 193 # Don't use lit.util.which() for link.exe: In `git bash`, it will pick194 # up /usr/bin/link (another name for ln).195 link = os.path.join(os.path.dirname(cl), "link.exe")196 197 cl = '"' + cl + '"'198 link = '"' + link + '"'199 includes = os.getenv("INCLUDE", "").split(";")200 libs = os.getenv("LIB", "").split(";")201 202 config.available_features.add("msvc")203 compiler_flags = ['"/I{}"'.format(x) for x in includes if os.path.exists(x)]204 linker_flags = ['"/LIBPATH:{}"'.format(x) for x in libs if os.path.exists(x)]205 206 tools = [207 ToolSubst("%msvc_cl", command=cl, extra_args=compiler_flags),208 ToolSubst("%msvc_link", command=link, extra_args=linker_flags),209 ]210 llvm_config.add_tool_substitutions(tools)211 return212 213 214def use_support_substitutions(config):215 # Set up substitutions for support tools. These tools can be overridden at the CMake216 # level (by specifying -DLLDB_LIT_TOOLS_DIR), installed, or as a last resort, we can use217 # the just-built version.218 if config.enable_remote:219 host_flags = ["--target=" + config.target_triple]220 else:221 host_flags = ["--target=" + config.host_triple]222 if platform.system() in ["Darwin"]:223 try:224 out = subprocess.check_output(["xcrun", "--show-sdk-path"]).strip()225 res = 0226 except OSError:227 res = -1228 if res == 0 and out:229 sdk_path = lit.util.to_string(out)230 llvm_config.lit_config.note("using SDKROOT: %r" % sdk_path)231 host_flags += ["-isysroot", sdk_path]232 elif sys.platform != "win32":233 host_flags += ["-pthread"]234 235 if sys.platform.startswith("netbsd"):236 # needed e.g. to use freshly built libc++237 host_flags += [238 "-L" + config.llvm_libs_dir,239 "-Wl,-rpath," + config.llvm_libs_dir,240 ]241 242 # The clang module cache is used for building inferiors.243 host_flags += ["-fmodules-cache-path={}".format(config.clang_module_cache)]244 245 if config.cmake_sysroot:246 host_flags += ["--sysroot={}".format(config.cmake_sysroot)]247 248 if config.enable_remote and config.has_libcxx:249 host_flags += [250 "-L{}".format(config.libcxx_libs_dir),251 "-lc++",252 ]253 # By default, macOS doesn't allow injecting the ASAN runtime into system processes.254 if platform.system() in ["Darwin"] and config.llvm_use_sanitizer:255 system_clang = (256 subprocess.check_output(["xcrun", "-find", "clang"]).strip().decode("utf-8")257 )258 system_liblto = os.path.join(259 os.path.dirname(os.path.dirname(system_clang)), "lib", "libLTO.dylib"260 )261 host_flags += ["-Wl,-lto_library", "-Wl," + system_liblto]262 263 host_flags = " ".join(host_flags)264 config.substitutions.append(("%clang_host", "%clang " + host_flags))265 config.substitutions.append(("%clangxx_host", "%clangxx " + host_flags))266 config.substitutions.append(267 ("%clang_cl_host", "%clang_cl --target=" + config.host_triple)268 )269 270 additional_tool_dirs = []271 if config.lldb_lit_tools_dir:272 additional_tool_dirs.append(config.lldb_lit_tools_dir)273 274 llvm_config.use_clang(275 additional_flags=["--target=specify-a-target-or-use-a-_host-substitution"],276 additional_tool_dirs=additional_tool_dirs,277 required=True,278 use_installed=True,279 )280 if llvm_config.clang_has_bounds_safety():281 llvm_config.lit_config.note("clang has -fbounds-safety support")282 config.available_features.add("clang-bounds-safety")283 284 if sys.platform == "win32":285 _use_msvc_substitutions(config)286 287 have_lld = llvm_config.use_lld(288 additional_tool_dirs=additional_tool_dirs, required=False, use_installed=True289 )290 if have_lld:291 config.available_features.add("lld")292 293 support_tools = [294 "yaml2obj",295 "obj2yaml",296 "llvm-dwp",297 "llvm-pdbutil",298 "llvm-mc",299 "llvm-readobj",300 "llvm-objdump",301 "llvm-objcopy",302 "lli",303 ]304 additional_tool_dirs += [config.lldb_tools_dir, config.llvm_tools_dir]305 llvm_config.add_tool_substitutions(support_tools, additional_tool_dirs)306 307 _disallow(config, "clang")308