| import os | |
| import itertools | |
| import platform | |
| import re | |
| import subprocess | |
| import sys | |
| import lit.util | |
| from lit.formats import ShTest | |
| from lit.llvm import llvm_config | |
| from lit.llvm.subst import FindTool | |
| from lit.llvm.subst import ToolSubst | |
| import lldbflakes | |
| import posixpath | |
| def _get_lldb_init_path(config): | |
| return os.path.join(config.test_exec_root, "lit-lldb-init-quiet") | |
| def _disallow(config, execName): | |
| warning = """ | |
| echo '*** Do not use \'{0}\' in tests; use \'%''{0}\'. ***' && | |
| exit 1 && echo | |
| """ | |
| config.substitutions.append((" {0} ".format(execName), warning.format(execName))) | |
| def get_lldb_args(config, suffix=""): | |
| lldb_args = [] | |
| if "remote-linux" in config.available_features: | |
| lldb_args += [ | |
| "-O", | |
| '"platform select remote-linux"', | |
| "-O", | |
| f'"platform connect {config.lldb_platform_url}"', | |
| ] | |
| if config.lldb_platform_working_dir: | |
| dir = posixpath.join(f"{config.lldb_platform_working_dir}", "shell") | |
| if suffix: | |
| dir += posixpath.join(dir, f"{suffix}") | |
| lldb_args += [ | |
| "-O", | |
| f'"platform shell mkdir -p {dir}"', | |
| "-O", | |
| f'"platform settings -w {dir}"', | |
| ] | |
| lldb_args += ["--no-lldbinit", "-S", _get_lldb_init_path(config)] | |
| return lldb_args | |
| class ShTestLldb(ShTest): | |
| def __init__(self, extra_substitutions=[], preamble_commands=[]): | |
| super().__init__( | |
| extra_substitutions=extra_substitutions, preamble_commands=preamble_commands | |
| ) | |
| def execute(self, test, litConfig): | |
| # Run each Shell test in a separate directory (on remote). | |
| # Find directory change command in %lldb substitution. | |
| for i, t in enumerate(test.config.substitutions): | |
| if re.match(t[0], "%lldb"): | |
| cmd = t[1] | |
| if '-O "platform settings -w ' in cmd: | |
| # If command is present, it is added by get_lldb_args. | |
| # Replace the path with the tests' path in suite. | |
| # Example: | |
| # bin/lldb | |
| # -O "platform shell mkdir -p /home/user/shell" | |
| # -O "platform settings -w /home/user/shell" ... | |
| # => | |
| # bin/lldb | |
| # -O "platform shell mkdir -p /home/user/shell/SymbolFile/Breakpad/inline-record.test" | |
| # -O "platform settings -w /home/user/shell/SymbolFile/Breakpad/inline-record.test" ... | |
| args_def = " ".join(get_lldb_args(test.config)) | |
| args_unique = " ".join( | |
| get_lldb_args( | |
| test.config, | |
| posixpath.join(*test.path_in_suite), | |
| ) | |
| ) | |
| test.config.substitutions[i] = ( | |
| t[0], | |
| cmd.replace(args_def, args_unique), | |
| ) | |
| break | |
| return lldbflakes.execute_with_reruns( | |
| lambda: ShTest.execute(self, test, litConfig) | |
| ) | |
| def use_lldb_substitutions(config): | |
| # Set up substitutions for primary tools. These tools must come from config.lldb_tools_dir | |
| # which is basically the build output directory. We do not want to find these in path or | |
| # anywhere else, since they are specifically the programs which are actually being tested. | |
| dsname = "debugserver" if platform.system() in ["Darwin"] else "lldb-server" | |
| dsargs = [] if platform.system() in ["Darwin"] else ["gdbserver"] | |
| build_script = os.path.dirname(__file__) | |
| build_script = os.path.join(build_script, "build.py") | |
| build_script_args = [ | |
| build_script, | |
| ( | |
| "--compiler=clang" if config.enable_remote else "--compiler=any" | |
| ), # Default to best compiler | |
| "--arch=" + str(config.lldb_bitness), | |
| ] | |
| if config.lldb_lit_tools_dir: | |
| build_script_args.append("--tools-dir={0}".format(config.lldb_lit_tools_dir)) | |
| if config.lldb_tools_dir: | |
| build_script_args.append("--tools-dir={0}".format(config.lldb_tools_dir)) | |
| if config.llvm_libs_dir: | |
| build_script_args.append("--libs-dir={0}".format(config.llvm_libs_dir)) | |
| if config.objc_gnustep_dir: | |
| build_script_args.append( | |
| '--objc-gnustep-dir="{0}"'.format(config.objc_gnustep_dir) | |
| ) | |
| if config.cmake_sysroot: | |
| build_script_args.append("--sysroot={0}".format(config.cmake_sysroot)) | |
| lldb_init = _get_lldb_init_path(config) | |
| launcher = getattr(config, "lldb_launcher", None) | |
| primary_tools = [ | |
| ToolSubst( | |
| "%lldb", | |
| command=FindTool("lldb"), | |
| extra_args=get_lldb_args(config), | |
| launcher=launcher, | |
| unresolved="fatal", | |
| ), | |
| ToolSubst( | |
| "%lldb-init", | |
| command=FindTool("lldb"), | |
| extra_args=["-S", lldb_init], | |
| launcher=launcher, | |
| unresolved="fatal", | |
| ), | |
| ToolSubst( | |
| "%lldb-noinit", | |
| command=FindTool("lldb"), | |
| extra_args=["--no-lldbinit"], | |
| launcher=launcher, | |
| unresolved="fatal", | |
| ), | |
| ToolSubst( | |
| "%lldb-server", | |
| command=FindTool("lldb-server"), | |
| extra_args=[], | |
| unresolved="ignore", | |
| ), | |
| ToolSubst( | |
| "%debugserver", | |
| command=FindTool(dsname), | |
| extra_args=dsargs, | |
| unresolved="ignore", | |
| ), | |
| ToolSubst( | |
| "%platformserver", | |
| command=FindTool("lldb-server"), | |
| extra_args=["platform"], | |
| unresolved="ignore", | |
| ), | |
| "lldb-test", | |
| "lldb-dap", | |
| "lldb-mcp", | |
| ToolSubst( | |
| "%build", command="'" + sys.executable + "'", extra_args=build_script_args | |
| ), | |
| ] | |
| _disallow(config, "lldb") | |
| _disallow(config, "lldb-server") | |
| _disallow(config, "debugserver") | |
| _disallow(config, "platformserver") | |
| llvm_config.add_tool_substitutions(primary_tools, [config.lldb_tools_dir]) | |
| def _use_msvc_substitutions(config): | |
| # If running from a Visual Studio Command prompt (e.g. vcvars), this will | |
| # detect the include and lib paths, and find cl.exe and link.exe and create | |
| # substitutions for each of them that explicitly specify /I and /L paths | |
| cl = lit.util.which("cl") | |
| if not cl: | |
| return | |
| # Don't use lit.util.which() for link.exe: In `git bash`, it will pick | |
| # up /usr/bin/link (another name for ln). | |
| link = os.path.join(os.path.dirname(cl), "link.exe") | |
| cl = '"' + cl + '"' | |
| link = '"' + link + '"' | |
| includes = os.getenv("INCLUDE", "").split(";") | |
| libs = os.getenv("LIB", "").split(";") | |
| config.available_features.add("msvc") | |
| compiler_flags = ['"/I{}"'.format(x) for x in includes if os.path.exists(x)] | |
| linker_flags = ['"/LIBPATH:{}"'.format(x) for x in libs if os.path.exists(x)] | |
| tools = [ | |
| ToolSubst("%msvc_cl", command=cl, extra_args=compiler_flags), | |
| ToolSubst("%msvc_link", command=link, extra_args=linker_flags), | |
| ] | |
| llvm_config.add_tool_substitutions(tools) | |
| return | |
| def use_support_substitutions(config): | |
| # Set up substitutions for support tools. These tools can be overridden at the CMake | |
| # level (by specifying -DLLDB_LIT_TOOLS_DIR), installed, or as a last resort, we can use | |
| # the just-built version. | |
| if config.enable_remote: | |
| host_flags = ["--target=" + config.target_triple] | |
| else: | |
| host_flags = ["--target=" + config.host_triple] | |
| if platform.system() in ["Darwin"]: | |
| try: | |
| out = subprocess.check_output(["xcrun", "--show-sdk-path"]).strip() | |
| res = 0 | |
| except OSError: | |
| res = -1 | |
| if res == 0 and out: | |
| sdk_path = out.decode("utf-8") | |
| llvm_config.lit_config.note("using SDKROOT: %r" % sdk_path) | |
| host_flags += ["-isysroot", sdk_path] | |
| elif sys.platform != "win32": | |
| host_flags += ["-pthread"] | |
| if sys.platform.startswith("netbsd"): | |
| # needed e.g. to use freshly built libc++ | |
| host_flags += [ | |
| "-L" + config.llvm_libs_dir, | |
| "-Wl,-rpath," + config.llvm_libs_dir, | |
| ] | |
| # The clang module cache is used for building inferiors. | |
| host_flags += ["-fmodules-cache-path={}".format(config.clang_module_cache)] | |
| # Our files use x86 AT&T assembly throughout. | |
| # Enable it explicitly so any local Clang preference for Intel syntax gets overriden. | |
| if "x86-registered-target" in config.available_features: | |
| host_flags += ["-mllvm", "-x86-asm-syntax=att"] | |
| if config.cmake_sysroot: | |
| host_flags += ["--sysroot={}".format(config.cmake_sysroot)] | |
| if config.enable_remote and config.has_libcxx: | |
| host_flags += [ | |
| "-L{}".format(config.libcxx_libs_dir), | |
| "-lc++", | |
| ] | |
| # By default, macOS doesn't allow injecting the ASAN runtime into system processes. | |
| if platform.system() in ["Darwin"] and config.llvm_use_sanitizer: | |
| system_clang = ( | |
| subprocess.check_output(["xcrun", "-find", "clang"]).strip().decode("utf-8") | |
| ) | |
| system_liblto = os.path.join( | |
| os.path.dirname(os.path.dirname(system_clang)), "lib", "libLTO.dylib" | |
| ) | |
| host_flags += ["-Wl,-lto_library", "-Wl," + system_liblto] | |
| host_flags = " ".join(host_flags) | |
| config.substitutions.append(("%clang_host", "%clang " + host_flags)) | |
| config.substitutions.append(("%clangxx_host", "%clangxx " + host_flags)) | |
| config.substitutions.append( | |
| ("%clang_cl_host", "%clang_cl --target=" + config.host_triple) | |
| ) | |
| additional_tool_dirs = [] | |
| if config.lldb_lit_tools_dir: | |
| additional_tool_dirs.append(config.lldb_lit_tools_dir) | |
| llvm_config.use_clang( | |
| additional_flags=["--target=specify-a-target-or-use-a-_host-substitution"], | |
| additional_tool_dirs=additional_tool_dirs, | |
| required=True, | |
| use_installed=True, | |
| ) | |
| if llvm_config.clang_has_bounds_safety(): | |
| llvm_config.lit_config.note("clang has -fbounds-safety support") | |
| config.available_features.add("clang-bounds-safety") | |
| if sys.platform == "win32": | |
| _use_msvc_substitutions(config) | |
| have_lld = llvm_config.use_lld( | |
| additional_tool_dirs=additional_tool_dirs, required=False, use_installed=True | |
| ) | |
| if have_lld: | |
| config.available_features.add("lld") | |
| support_tools = [ | |
| "yaml2obj", | |
| "obj2yaml", | |
| "llvm-dwp", | |
| "llvm-pdbutil", | |
| "llvm-mc", | |
| "llvm-readobj", | |
| "llvm-objdump", | |
| "llvm-objcopy", | |
| "lli", | |
| ] | |
| additional_tool_dirs += [config.lldb_tools_dir, config.llvm_tools_dir] | |
| llvm_config.add_tool_substitutions(support_tools, additional_tool_dirs) | |
| _disallow(config, "clang") |