import os
import platform
import shlex
import shutil
import subprocess
import sys
import lit.formats
config.name = "lldb-api"
config.suffixes = [".py"]
config.test_source_root = os.path.dirname(__file__)
config.test_exec_root = os.path.join(config.lldb_obj_root, "test", "API")
def mkdir_p(path):
import errno
try:
os.makedirs(path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if not os.path.isdir(path):
raise OSError(errno.ENOTDIR, "%s is not a directory" % path)
def find_sanitizer_runtime(name):
resource_dir = (
subprocess.check_output([config.cmake_cxx_compiler, "-print-resource-dir"])
.decode("utf-8")
.strip()
)
return os.path.join(resource_dir, "lib", "darwin", name)
def find_shlibpath_var():
if platform.system() in ["Linux", "FreeBSD", "NetBSD", "OpenBSD", "SunOS"]:
yield "LD_LIBRARY_PATH"
elif platform.system() == "Darwin":
yield "DYLD_LIBRARY_PATH"
elif platform.system() == "Windows":
yield "PATH"
def find_python_interpreter():
if "DYLD_INSERT_LIBRARIES" not in config.environment:
return None
if sys.prefix != sys.base_prefix:
copied_python = os.path.join(sys.prefix, "bin", "copied-python")
else:
copied_python = os.path.join(config.lldb_build_directory, "copied-python")
if os.path.isfile(copied_python):
return copied_python
real_python = (
subprocess.check_output(
[
config.python_executable,
os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"get_darwin_real_python.py",
),
]
)
.decode("utf-8")
.strip()
)
shutil.copy(real_python, copied_python)
try:
subprocess.check_call([copied_python, "-V"])
except subprocess.CalledProcessError:
os.remove(copied_python)
os.symlink(real_python, copied_python)
return copied_python
def is_configured(attr):
"""Return the configuration attribute if it exists and None otherwise.
This allows us to check if the attribute exists before trying to access it."""
return getattr(config, attr, None)
def delete_module_cache(path):
"""Clean the module caches in the test build directory.
This is necessary in an incremental build whenever clang changes underneath,
so doing it once per lit.py invocation is close enough."""
if os.path.isdir(path):
lit_config.note("Deleting module cache at %s." % path)
shutil.rmtree(path)
if is_configured("llvm_use_sanitizer"):
if "Address" in config.llvm_use_sanitizer:
config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1"
if "Darwin" in config.host_os:
config.environment["DYLD_INSERT_LIBRARIES"] = find_sanitizer_runtime(
"libclang_rt.asan_osx_dynamic.dylib"
)
config.environment["MallocNanoZone"] = "0"
if "Thread" in config.llvm_use_sanitizer:
config.environment["TSAN_OPTIONS"] = "halt_on_error=1"
if "Darwin" in config.host_os:
config.environment["DYLD_INSERT_LIBRARIES"] = find_sanitizer_runtime(
"libclang_rt.tsan_osx_dynamic.dylib"
)
if platform.system() == "Darwin":
python_executable = find_python_interpreter()
if python_executable:
lit_config.note(
"Using {} instead of {}".format(python_executable, config.python_executable)
)
config.python_executable = python_executable
if is_configured("shared_libs"):
for shlibpath_var in find_shlibpath_var():
shlibpath = os.path.pathsep.join(
(
config.llvm_shlib_dir,
config.llvm_libs_dir,
config.environment.get(shlibpath_var, ""),
)
)
config.environment[shlibpath_var] = shlibpath
else:
lit_config.warning(
"unable to inject shared library path on '{}'".format(platform.system())
)
lldb_use_simulator = lit_config.params.get("lldb-run-with-simulator", None)
if lldb_use_simulator:
if lldb_use_simulator == "ios":
lit_config.note("Running API tests on iOS simulator")
config.available_features.add("lldb-simulator-ios")
elif lldb_use_simulator == "watchos":
lit_config.note("Running API tests on watchOS simulator")
config.available_features.add("lldb-simulator-watchos")
elif lldb_use_simulator == "tvos":
lit_config.note("Running API tests on tvOS simulator")
config.available_features.add("lldb-simulator-tvos")
else:
lit_config.error("Unknown simulator id '{}'".format(lldb_use_simulator))
supported, errormsg = lit_config.maxIndividualTestTimeIsSupported
if supported:
lit_config.maxIndividualTestTime = 600
else:
lit_config.warning("Could not set a default per-test timeout. " + errormsg)
dotest_cmd = [os.path.join(config.lldb_src_root, "test", "API", "dotest.py")]
if is_configured("dotest_common_args_str"):
dotest_cmd.extend(config.dotest_common_args_str.split(";"))
if is_configured("llvm_libs_dir"):
dotest_cmd += ["--env", "LLVM_LIBS_DIR=" + config.llvm_libs_dir]
if is_configured("llvm_include_dir"):
dotest_cmd += ["--env", "LLVM_INCLUDE_DIR=" + config.llvm_include_dir]
if is_configured("llvm_tools_dir"):
dotest_cmd += ["--env", "LLVM_TOOLS_DIR=" + config.llvm_tools_dir]
if is_configured("has_libcxx") and config.has_libcxx:
if platform.system() != "Windows":
if is_configured("libcxx_include_dir") and is_configured("libcxx_libs_dir"):
dotest_cmd += ["--libcxx-include-dir", config.libcxx_include_dir]
if is_configured("libcxx_include_target_dir"):
dotest_cmd += [
"--libcxx-include-target-dir",
config.libcxx_include_target_dir,
]
dotest_cmd += ["--libcxx-library-dir", config.libcxx_libs_dir]
for env_var in ("ASAN_OPTIONS", "DYLD_INSERT_LIBRARIES"):
if env_var in config.environment:
dotest_cmd += ["--inferior-env", env_var + "=" + config.environment[env_var]]
if is_configured("test_arch"):
dotest_cmd += ["--arch", config.test_arch]
if is_configured("lldb_build_directory"):
dotest_cmd += ["--build-dir", config.lldb_build_directory]
if is_configured("lldb_module_cache"):
delete_module_cache(config.lldb_module_cache)
dotest_cmd += ["--lldb-module-cache-dir", config.lldb_module_cache]
if is_configured("clang_module_cache"):
delete_module_cache(config.clang_module_cache)
dotest_cmd += ["--clang-module-cache-dir", config.clang_module_cache]
if is_configured("lldb_executable"):
dotest_cmd += ["--executable", config.lldb_executable]
if is_configured("test_compiler"):
dotest_cmd += ["--compiler", config.test_compiler]
if is_configured("dsymutil"):
dotest_cmd += ["--dsymutil", config.dsymutil]
if is_configured("llvm_tools_dir"):
dotest_cmd += ["--llvm-tools-dir", config.llvm_tools_dir]
if is_configured("server"):
dotest_cmd += ["--server", config.server]
if is_configured("lldb_obj_root"):
dotest_cmd += ["--lldb-obj-root", config.lldb_obj_root]
if is_configured("lldb_libs_dir"):
dotest_cmd += ["--lldb-libs-dir", config.lldb_libs_dir]
if is_configured("lldb_framework_dir"):
dotest_cmd += ["--framework", config.lldb_framework_dir]
if (
"lldb-repro-capture" in config.available_features
or "lldb-repro-replay" in config.available_features
):
dotest_cmd += ["--skip-category=lldb-dap", "--skip-category=std-module"]
if "lldb-simulator-ios" in config.available_features:
dotest_cmd += ["--apple-sdk", "iphonesimulator", "--platform-name", "ios-simulator"]
elif "lldb-simulator-watchos" in config.available_features:
dotest_cmd += [
"--apple-sdk",
"watchsimulator",
"--platform-name",
"watchos-simulator",
]
elif "lldb-simulator-tvos" in config.available_features:
dotest_cmd += [
"--apple-sdk",
"appletvsimulator",
"--platform-name",
"tvos-simulator",
]
if is_configured("enabled_plugins"):
for plugin in config.enabled_plugins:
dotest_cmd += ["--enable-plugin", plugin]
if is_configured("dotest_user_args_str"):
dotest_cmd.extend(config.dotest_user_args_str.split(";"))
if is_configured("dotest_lit_args_str"):
dotest_cmd.extend(shlex.split(config.dotest_lit_args_str))
sys.path.append(os.path.join(config.lldb_src_root, "test", "API"))
import lldbtest
config.test_format = lldbtest.LLDBTest(dotest_cmd)
config.environment["TERM"] = os.getenv("TERM", default="vt100")
if "FREEBSD_LEGACY_PLUGIN" in os.environ:
config.environment["FREEBSD_LEGACY_PLUGIN"] = os.environ["FREEBSD_LEGACY_PLUGIN"]
if "XDG_CACHE_HOME" in os.environ:
config.environment["XDG_CACHE_HOME"] = os.environ["XDG_CACHE_HOME"]