Files
TheRock/math-libs/libhipcxx/.upstream-tests/utils/libcudacxx/test/config.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

1878 lines
84 KiB
Python

# ===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ===----------------------------------------------------------------------===##
# Modifications Copyright (c) 2024-2026 Advanced Micro Devices, Inc.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import ctypes
import os
import platform
import re
import shlex
import shutil
import sys
import libcudacxx.util
from libcudacxx.compiler import CXXCompiler
# The wildcard import is to support `eval(exec_str)` in
# `Configuration.configure_executor()` below.
from libcudacxx.test.executor import * # noqa: F403
from libcudacxx.test.executor import LocalExecutor, NoopExecutor
from libcudacxx.test.target_info import make_target_info
def loadSiteConfig(lit_config, config, param_name, env_name):
# We haven't loaded the site specific configuration (the user is
# probably trying to run on a test file directly, and either the site
# configuration hasn't been created by the build system, or we are in an
# out-of-tree build situation).
site_cfg = lit_config.params.get(param_name, os.environ.get(env_name))
if not site_cfg:
lit_config.warning(
"No site specific configuration file found!"
" Running the tests in the default configuration."
)
elif not os.path.isfile(site_cfg):
lit_config.fatal(
"Specified site configuration file does not exist: '%s'" % site_cfg
)
else:
lit_config.note("using site specific configuration at %s" % site_cfg)
ld_fn = lit_config.load_config
# Null out the load_config function so that lit.site.cfg doesn't
# recursively load a config even if it tries.
# TODO: This is one hell of a hack. Fix it.
def prevent_reload_fn(*args, **kwargs):
pass
lit_config.load_config = prevent_reload_fn
ld_fn(config, site_cfg)
lit_config.load_config = ld_fn
# Extract the value of a numeric macro such as __cplusplus or a feature-test
# macro.
def intMacroValue(token):
return int(token.rstrip("LlUu"))
class Configuration(object):
# pylint: disable=redefined-outer-name
def __init__(self, lit_config, config):
self.lit_config = lit_config
self.config = config
self.is_windows = platform.system() == "Windows"
self.cxx = None
self.cxx_is_clang_cl = None
self.cxx_stdlib_under_test = None
self.project_obj_root = None
self.libcudacxx_src_root = None
self.libcudacxx_obj_root = None
self.cxx_library_root = None
self.cxx_runtime_root = None
self.abi_library_root = None
self.link_shared = self.get_lit_bool("enable_shared", default=True)
self.debug_build = self.get_lit_bool("debug_build", default=False)
self.exec_env = dict(os.environ)
self.exec_env["CUDA_MODULE_LOADING"] = "EAGER"
self.use_target = False
self.use_system_cxx_lib = False
self.use_clang_verify = False
self.long_tests = None
self.execute_external = False
def get_lit_conf(self, name, default=None):
val = self.lit_config.params.get(name, None)
if val is None:
val = getattr(self.config, name, None)
if val is None:
val = default
return val
def get_lit_bool(self, name, default=None, env_var=None):
def check_value(value, var_name):
if value is None:
return default
if isinstance(value, bool):
return value
if not isinstance(value, str):
raise TypeError("expected bool or string")
if value.lower() in ("1", "true"):
return True
if value.lower() in ("", "0", "false"):
return False
self.lit_config.fatal(
"parameter '{}' should be true or false".format(var_name)
)
conf_val = self.get_lit_conf(name)
if (
env_var is not None
and env_var in os.environ
and os.environ[env_var] is not None
):
val = os.environ[env_var]
if conf_val is not None:
self.lit_config.warning(
"Environment variable %s=%s is overriding explicit "
"--param=%s=%s" % (env_var, val, name, conf_val)
)
return check_value(val, env_var)
return check_value(conf_val, name)
def get_compute_capabilities(self):
deduced_compute_archs = []
libnames = ("libcuda.so", "libcuda.dylib", "nvcuda.dll", "cuda.dll")
for libname in libnames:
try:
cuda = ctypes.CDLL(libname)
except OSError:
continue
else:
break
else:
raise OSError("could not load any of: " + " ".join(libnames))
self.lit_config.note('compute_archs set to "native", computing available archs')
CUDA_SUCCESS = 0
nGpus = ctypes.c_int()
cc_major = ctypes.c_int()
cc_minor = ctypes.c_int()
result = ctypes.c_int()
device = ctypes.c_int()
error_str = ctypes.c_char_p()
result = cuda.cuInit(0)
if result != CUDA_SUCCESS:
cuda.cuGetErrorString(result, ctypes.byref(error_str))
self.lit_config.note(
"cuInit failed with error code %d: %s"
% (result, error_str.value.decode())
)
return "native"
result = cuda.cuDeviceGetCount(ctypes.byref(nGpus))
if result != CUDA_SUCCESS:
cuda.cuGetErrorString(result, ctypes.byref(error_str))
self.lit_config.note(
"cuDeviceGetCount failed with error code %d: %s"
% (result, error_str.value.decode())
)
return "native"
self.lit_config.note("Found %d device(s)." % nGpus.value)
for i in range(nGpus.value):
result = cuda.cuDeviceGet(ctypes.byref(device), i)
if result != CUDA_SUCCESS:
cuda.cuGetErrorString(result, ctypes.byref(error_str))
self.lit_config.note(
"cuDeviceGet failed with error code %d: %s"
% (result, error_str.value.decode())
)
return "native"
if (
cuda.cuDeviceComputeCapability(
ctypes.byref(cc_major), ctypes.byref(cc_minor), device
)
== CUDA_SUCCESS
):
self.lit_config.note(
"Deduced compute capability of device %d to: %d%d"
% (i + 1, cc_major.value, cc_minor.value)
)
deduced_compute_archs.append(cc_major.value * 10 + cc_minor.value)
self.lit_config.note(
"Deduced compute capabilities are: %s" % deduced_compute_archs
)
deduced_comput_archs_str = ", ".join(
[str(element) for element in deduced_compute_archs]
)
return deduced_comput_archs_str
def get_modules_enabled(self):
return self.get_lit_bool(
"enable_modules", default=False, env_var="LIBCUDACXX_ENABLE_MODULES"
)
def make_static_lib_name(self, name):
"""Return the full filename for the specified library name"""
if self.is_windows:
# Only allow libc++ to use this function for now.
assert name == "c++"
return "lib" + name + ".lib"
else:
return "lib" + name + ".a"
def configure(self):
self.configure_executor()
self.configure_use_system_cxx_lib()
self.configure_target_info()
self.configure_cxx()
self.configure_triple()
self.configure_deployment()
self.configure_src_root()
self.configure_obj_root()
self.configure_cxx_stdlib_under_test()
self.configure_cxx_library_root()
self.configure_use_clang_verify()
self.configure_use_thread_safety()
self.configure_no_execute()
self.configure_execute_external()
self.configure_ccache()
self.configure_compile_flags()
self.configure_filesystem_compile_flags()
self.configure_link_flags()
self.configure_env()
self.configure_color_diagnostics()
if (self.cxx.type != 'nvrtcc' and self.cxx.type != 'hiprtcc'):
self.configure_debug_mode()
self.configure_warnings()
self.configure_sanitizer()
self.configure_coverage()
self.configure_modules()
self.configure_coroutines()
self.configure_substitutions()
self.configure_features()
def print_config_info(self):
# Print the final compile and link flags.
self.lit_config.note(
"Using compiler: %s %s" % (self.cxx.path, self.cxx.first_arg)
)
self.lit_config.note("Using flags: %s" % self.cxx.flags)
if self.cxx.use_modules:
self.lit_config.note("Using modules flags: %s" % self.cxx.modules_flags)
self.lit_config.note("Using compile flags: %s" % self.cxx.compile_flags)
if len(self.cxx.warning_flags):
self.lit_config.note("Using warnings: %s" % self.cxx.warning_flags)
self.lit_config.note("Using link flags: %s" % self.cxx.link_flags)
# Print as list to prevent "set([...])" from being printed.
self.lit_config.note(
"Using available_features: %s" % list(self.config.available_features)
)
show_env_vars = {}
for k, v in self.exec_env.items():
if k not in os.environ or os.environ[k] != v:
show_env_vars[k] = v
self.lit_config.note("Adding environment variables: %r" % show_env_vars)
sys.stderr.flush() # Force flushing to avoid broken output on Windows
def get_test_format(self):
from libcudacxx.test.format import LibcxxTestFormat
return LibcxxTestFormat(
self.cxx,
self.use_clang_verify,
self.execute_external,
self.executor,
exec_env=self.exec_env,
)
def configure_executor(self):
exec_str = self.get_lit_conf("executor", "None")
exec_timeout = self.get_lit_conf("maxIndividualTestTime", "None")
# Security note: eval() is used here for intentional code execution to instantiate
# executor objects from configuration. This is a known limitation of the lit config
# system. Only use trusted configuration files.
te = eval(exec_str) # nosec B307 - Intentional executor instantiation from config
if te:
self.lit_config.note("Using executor: %r" % exec_str)
if self.lit_config.useValgrind:
# We have no way of knowing where in the chain the
# ValgrindExecutor is supposed to go. It is likely
# that the user wants it at the end, but we have no
# way of getting at that easily.
self.lit_config.fatal(
"Cannot infer how to create a Valgrind " " executor."
)
else:
te = LocalExecutor()
te.timeout = 0
if exec_timeout:
te.timeout = exec_timeout
if self.lit_config.useValgrind:
# te = ValgrindExecutor(self.lit_config.valgrindArgs, te)
self.lit_config.fatal("ValgrindExecutor never existed in CCCL.")
self.executor = te
def configure_target_info(self):
self.target_info = make_target_info(self)
def get_rocm_version(self):
rocm_version = os.getenv('ROCM_VERSION', None)
if rocm_version is not None:
parts = rocm_version.split(".")
if len(parts) == 3:
try:
rocm_version_major, rocm_version_minor, rocm_version_patch = map(int, parts)
return rocm_version_major, rocm_version_minor, rocm_version_patch
except ValueError:
pass
print(f"Could not read ROCM version from ROCM_VERSION='{rocm_version}' environment variable! Expected format: MAJOR.MINOR.PATCH (e.g., 7.0.1).")
print("Falling back to file-based lookup.")
# If format is incorrect, fall through to file-based detection
# 1. Find rocm_version.h
out, err, code = libcudacxx.util.executeCommand(
["hipconfig", "--path"] # find HIP base path
)
if code != 0:
return None
hip_path = out.strip()
out, err, code = libcudacxx.util.executeCommand(
["find", hip_path, "-name", "rocm_version.h"]
)
if code != 0:
return None
rocm_version_h = out.strip()
# 2. Extract major, minor, patch using grep
with open(rocm_version_h, "r") as f:
content = f.read()
major_match = re.search(r"ROCM_VERSION_MAJOR\s+(\d+)", content)
minor_match = re.search(r"ROCM_VERSION_MINOR\s+(\d+)", content)
patch_match = re.search(r"ROCM_VERSION_PATCH\s+(\d+)", content)
if not (major_match and minor_match and patch_match):
return None
rocm_version_major = int(major_match.group(1))
rocm_version_minor = int(minor_match.group(1))
rocm_version_patch = int(patch_match.group(1))
return rocm_version_major, rocm_version_minor, rocm_version_patch
def configure_cxx(self):
# Gather various compiler parameters.
cxx = self.get_lit_conf("cxx_under_test")
cxx_first_arg = self.get_lit_conf("cxx_first_arg")
nvrtc = self.get_lit_bool("is_nvrtc", False)
hiprtc = self.get_lit_bool('is_hiprtc', False)
self.cxx_is_clang_cl = (
cxx is not None and os.path.basename(cxx) == "clang-cl.exe"
)
if platform.system() == "Windows":
self.config.available_features.add("windows_amd")
# Build CXXCompiler manually for NVRTCC
if nvrtc is True:
cxx_type = "nvrtcc"
self.cxx = CXXCompiler(
path=cxx,
first_arg=cxx_first_arg,
cxx_type=cxx_type,
cxx_version=("1", "1", "1"),
)
self.cxx.default_dialect = "c++11"
self.cxx.source_lang = "cu"
maj_v, min_v, patch_v = self.cxx.version
self.config.available_features.add("nvrtc")
self.config.available_features.add("%s-%s" % (self.cxx.type, maj_v))
self.config.available_features.add(
"%s-%s.%s" % (self.cxx.type, maj_v, min_v)
)
self.config.available_features.add(
"%s-%s.%s.%s" % (self.cxx.type, maj_v, min_v, patch_v)
)
self.lit_config.note("detected cxx.type as: {}".format(self.cxx.type))
self.lit_config.note("detected cxx.version as: {}".format(self.cxx.version))
self.lit_config.note(
"detected cxx.default_dialect as: {}".format(self.cxx.default_dialect)
)
self.cxx.compile_env = dict(os.environ)
# If compiler is *not* NVRTCC
## Build CXXCompiler manually for HIPRTCC
elif hiprtc is True:
cxx_type = "hiprtcc"
self.cxx = CXXCompiler(
path=cxx,
first_arg=cxx_first_arg,
cxx_type=cxx_type,
cxx_version=('1', '1', '1'))
self.cxx.default_dialect = "c++11"
self.cxx.source_lang = 'hip'
maj_v, min_v, patch_v = self.cxx.version
self.config.available_features.add("hiprtc")
self.config.available_features.add('%s-%s' % (self.cxx.type, maj_v))
self.config.available_features.add('%s-%s.%s' % (
self.cxx.type, maj_v, min_v))
self.config.available_features.add('%s-%s.%s.%s' % (
self.cxx.type, maj_v, min_v, patch_v))
self.lit_config.note("detected cxx.type as: {}".format(
self.cxx.type))
self.lit_config.note("detected cxx.version as: {}".format(
self.cxx.version))
self.lit_config.note("detected cxx.default_dialect as: {}".format(
self.cxx.default_dialect))
self.cxx.compile_env = dict(os.environ)
# NOTE(AMD/HIP): Get rocm version and define attributes to unsupport tests based on ROCm version.
rocm_version = self.get_rocm_version() # (major, minor, patch) as ints
if rocm_version is None:
print("Warning: rocm_version could not be identified, some tests may fail\
(e.g., std/algorithms/alg.modifying/alg.unique/unique_pred.pass.cpp)!")
elif rocm_version < (7, 0, 3):
self.config.available_features.add("rocm_lt_7.0.2")
# If compiler is *not* HIPRTCC
else:
# If no specific cxx_under_test was given, attempt to infer it as
# clang++.
if cxx is None or self.cxx_is_clang_cl:
search_paths = self.config.environment["PATH"]
if cxx is not None and os.path.isabs(cxx):
search_paths = os.path.dirname(cxx)
clangxx = libcudacxx.util.which("clang++", search_paths)
if clangxx:
cxx = clangxx
self.lit_config.note("inferred cxx_under_test as: %r" % cxx)
elif self.cxx_is_clang_cl:
self.lit_config.fatal(
"Failed to find clang++ substitution for" " clang-cl"
)
if not cxx:
self.lit_config.fatal(
"must specify user parameter cxx_under_test "
"(e.g., --param=cxx_under_test=clang++)"
)
if self.cxx_is_clang_cl:
self.cxx = self._configure_clang_cl(cxx)
else:
self.cxx = CXXCompiler(
cxx,
cxx_first_arg,
compile_flags=self.get_lit_conf("cmake_cxx_flags"),
cuda_path=self.get_lit_conf("cuda_path"),
)
cxx_type = self.cxx.type
if cxx_type is not None:
assert self.cxx.version is not None
maj_v, min_v, patch_v = self.cxx.version
self.config.available_features.add(cxx_type)
self.config.available_features.add("%s-%s" % (cxx_type, maj_v))
self.config.available_features.add(
"%s-%s.%s" % (cxx_type, maj_v, min_v)
)
self.config.available_features.add(
"%s-%s.%s.%s" % (cxx_type, maj_v, min_v, patch_v)
)
self.lit_config.note("detected cxx.type as: {}".format(self.cxx.type))
self.lit_config.note("detected cxx.version as: {}".format(self.cxx.version))
self.lit_config.note(
"detected cxx.default_dialect as: {}".format(self.cxx.default_dialect)
)
self.cxx.compile_env = dict(os.environ)
# 'CCACHE_CPP2' prevents ccache from stripping comments while
# preprocessing. This is required to prevent stripping of '-verify'
# comments.
self.cxx.compile_env["CCACHE_CPP2"] = "1"
if self.cxx.type == "nvcc":
nvcc_host_compiler = self.get_lit_conf("nvcc_host_compiler")
if len(nvcc_host_compiler.strip()) == 0:
if platform.system() == "Darwin":
nvcc_host_compiler = "clang"
elif platform.system() == "Windows":
nvcc_host_compiler = "cl.exe"
else:
nvcc_host_compiler = "gcc"
self.host_cxx = CXXCompiler(nvcc_host_compiler, None)
self.host_cxx_type = self.host_cxx.type
if self.host_cxx_type is not None:
assert self.host_cxx.version is not None
maj_v, min_v, _ = self.host_cxx.version
self.config.available_features.add(self.host_cxx_type)
self.config.available_features.add(
"%s-%s" % (self.host_cxx_type, maj_v)
)
self.config.available_features.add(
"%s-%s.%s" % (self.host_cxx_type, maj_v, min_v)
)
self.lit_config.note(
"detected host_cxx.type as: {}".format(self.host_cxx.type)
)
self.lit_config.note(
"detected host_cxx.version as: {}".format(self.host_cxx.version)
)
self.lit_config.note(
"detected host_cxx.default_dialect as: {}".format(
self.host_cxx.default_dialect
)
)
def _configure_clang_cl(self, clang_path):
def _split_env_var(var):
return [p.strip() for p in os.environ.get(var, "").split(";") if p.strip()]
def _prefixed_env_list(var, prefix):
from itertools import chain
return list(
chain.from_iterable((prefix, path) for path in _split_env_var(var))
)
assert self.cxx_is_clang_cl
flags = []
compile_flags = _prefixed_env_list("INCLUDE", "-isystem")
link_flags = _prefixed_env_list("LIB", "-L")
for path in _split_env_var("LIB"):
self.add_path(self.exec_env, path)
return CXXCompiler(
clang_path, flags=flags, compile_flags=compile_flags, link_flags=link_flags
)
def _dump_macros_verbose(self, *args, **kwargs):
if (self.cxx.type == 'nvrtcc' or self.cxx.type == 'hiprtcc'):
return None
macros_or_error = self.cxx.dumpMacros(*args, **kwargs)
if isinstance(macros_or_error, tuple):
cmd, out, err, rc = macros_or_error
report = libcudacxx.util.makeReport(cmd, out, err, rc)
report += "Compiler failed unexpectedly when dumping macros!"
self.lit_config.fatal(report)
return None
assert isinstance(macros_or_error, dict)
return macros_or_error
def configure_src_root(self):
self.libcudacxx_src_root = self.get_lit_conf(
"libcudacxx_src_root", os.path.dirname(self.config.test_source_root)
)
def configure_obj_root(self):
self.project_obj_root = self.get_lit_conf("project_obj_root")
self.libcudacxx_obj_root = self.get_lit_conf("libcudacxx_obj_root")
if not self.libcudacxx_obj_root and self.project_obj_root is not None:
possible_roots = [
os.path.join(self.project_obj_root, "libcudacxx"),
os.path.join(self.project_obj_root, "projects", "libcudacxx"),
os.path.join(self.project_obj_root, "runtimes", "libcudacxx"),
]
for possible_root in possible_roots:
if os.path.isdir(possible_root):
self.libcudacxx_obj_root = possible_root
break
else:
self.libcudacxx_obj_root = self.project_obj_root
def configure_cxx_library_root(self):
self.cxx_library_root = self.get_lit_conf(
"cxx_library_root", self.libcudacxx_obj_root
)
self.cxx_runtime_root = self.get_lit_conf(
"cxx_runtime_root", self.cxx_library_root
)
def configure_use_system_cxx_lib(self):
# This test suite supports testing against either the system library or
# the locally built one; the former mode is useful for testing ABI
# compatibility between the current headers and a shipping dynamic
# library.
# Default to testing against the locally built libc++ library.
self.use_system_cxx_lib = self.get_lit_conf("use_system_cxx_lib")
if self.use_system_cxx_lib == "true":
self.use_system_cxx_lib = True
elif self.use_system_cxx_lib == "false":
self.use_system_cxx_lib = False
elif self.use_system_cxx_lib:
assert os.path.isdir(self.use_system_cxx_lib), (
"the specified use_system_cxx_lib parameter (%s) is not a valid directory"
% self.use_system_cxx_lib
)
self.use_system_cxx_lib = os.path.abspath(self.use_system_cxx_lib)
self.lit_config.note(
"inferred use_system_cxx_lib as: %r" % self.use_system_cxx_lib
)
def configure_cxx_stdlib_under_test(self):
default_stdlib_under_test = 'libstdc++' if self.cxx.type=='hipcc' else 'libc++'
self.cxx_stdlib_under_test = self.get_lit_conf(
"cxx_stdlib_under_test", default_stdlib_under_test
)
if self.cxx_stdlib_under_test not in [
"libc++",
"libstdc++",
"msvc",
"cxx_default",
]:
self.lit_config.fatal(
'unsupported value for "cxx_stdlib_under_test": %s'
% self.cxx_stdlib_under_test
)
self.config.available_features.add(self.cxx_stdlib_under_test)
if self.cxx_stdlib_under_test == "libstdc++":
self.config.available_features.add("libstdc++")
# Manually enable the experimental and filesystem tests for libstdc++
# if the options aren't present.
# FIXME this is a hack.
if self.get_lit_conf("enable_experimental") is None:
self.config.enable_experimental = "true"
def configure_use_clang_verify(self):
if (self.cxx.type == 'nvrtcc' or self.cxx.type == 'hiprtcc'):
return
"""If set, run clang with -verify on failing tests."""
self.use_clang_verify = self.get_lit_bool("use_clang_verify")
if self.use_clang_verify is None:
# NOTE: We do not test for the -verify flag directly because
# -verify will always exit with non-zero on an empty file.
self.use_clang_verify = self.cxx.isVerifySupported()
self.lit_config.note(
"inferred use_clang_verify as: %r" % self.use_clang_verify
)
if self.use_clang_verify:
self.config.available_features.add("verify-support")
def configure_use_thread_safety(self):
"""If set, run clang with -verify on failing tests."""
has_thread_safety = self.cxx.hasCompileFlag("-Werror=thread-safety")
if has_thread_safety:
self.cxx.compile_flags += ["-Werror=thread-safety"]
self.config.available_features.add("thread-safety")
self.lit_config.note("enabling thread-safety annotations")
def configure_execute_external(self):
# Choose between lit's internal shell pipeline runner and a real shell.
# If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the
# default value. Otherwise we ask the target_info.
use_lit_shell_default = os.environ.get("LIT_USE_INTERNAL_SHELL")
if use_lit_shell_default is not None:
use_lit_shell_default = use_lit_shell_default != "0"
else:
use_lit_shell_default = self.target_info.use_lit_shell_default()
# Check for the command line parameter using the default value if it is
# not present.
use_lit_shell = self.get_lit_bool("use_lit_shell", use_lit_shell_default)
self.execute_external = not use_lit_shell
def configure_no_execute(self):
if isinstance(self.executor, NoopExecutor):
self.config.available_features.add("no_execute")
def configure_ccache(self):
use_ccache_default = os.environ.get("CMAKE_CUDA_COMPILER_LAUNCHER") is not None
use_ccache = self.get_lit_bool("use_ccache", use_ccache_default)
if use_ccache and not self.cxx.type == 'nvrtcc' and not self.cxx.type == 'hiprtcc':
self.cxx.use_ccache = True
self.lit_config.note("enabling ccache")
def add_deployment_feature(self, feature):
(arch, name, version) = self.config.deployment
self.config.available_features.add("%s=%s-%s" % (feature, arch, name))
self.config.available_features.add("%s=%s" % (feature, name))
self.config.available_features.add("%s=%s%s" % (feature, name, version))
def configure_features(self):
additional_features = self.get_lit_conf("additional_features")
if additional_features:
for f in additional_features.split(","):
self.config.available_features.add(f.strip())
self.target_info.add_locale_features(self.config.available_features)
target_platform = self.target_info.platform()
# Write an "available feature" that combines the triple when
# use_system_cxx_lib is enabled. This is so that we can easily write
# XFAIL markers for tests that are known to fail with versions of
# libc++ as were shipped with a particular triple.
if self.use_system_cxx_lib:
self.config.available_features.add("with_system_cxx_lib")
self.config.available_features.add(
"with_system_cxx_lib=%s" % self.config.target_triple
)
# Add subcomponents individually.
target_components = self.config.target_triple.split("-")
for component in target_components:
self.config.available_features.add("with_system_cxx_lib=%s" % component)
# Add available features for more generic versions of the target
# triple attached to with_system_cxx_lib.
if self.use_deployment:
self.add_deployment_feature("with_system_cxx_lib")
# Configure the availability feature. Availability is only enabled
# with libc++, because other standard libraries do not provide
# availability markup.
if self.use_deployment and self.cxx_stdlib_under_test == "libc++":
self.config.available_features.add("availability")
self.add_deployment_feature("availability")
if platform.system() == "Darwin":
self.config.available_features.add("apple-darwin")
# Insert the platform name into the available features as a lower case.
self.config.available_features.add(target_platform)
# Simulator testing can take a really long time for some of these tests
# so add a feature check so we can REQUIRES: long_tests in them
self.long_tests = self.get_lit_bool("long_tests")
if self.long_tests is None:
# Default to running long tests.
self.long_tests = True
self.lit_config.note("inferred long_tests as: %r" % self.long_tests)
if self.long_tests:
self.config.available_features.add("long_tests")
if not self.get_lit_bool("enable_filesystem", default=True):
self.config.available_features.add("c++filesystem-disabled")
self.config.available_features.add("dylib-has-no-filesystem")
# Run a compile test for the -fsized-deallocation flag. This is needed
# in test/std/language.support/support.dynamic/new.delete
if self.cxx.hasCompileFlag("-fsized-deallocation"):
self.config.available_features.add("-fsized-deallocation")
if self.cxx.hasCompileFlag("-faligned-allocation"):
self.config.available_features.add("-faligned-allocation")
else:
# FIXME remove this once more than just clang-4.0 support
# C++17 aligned allocation.
self.config.available_features.add("no-aligned-allocation")
if self.cxx.hasCompileFlag("-fdelayed-template-parsing"):
self.config.available_features.add("fdelayed-template-parsing")
if self.get_lit_bool("has_libatomic", False):
self.config.available_features.add("libatomic")
if "msvc" not in self.config.available_features:
macros = self._dump_macros_verbose()
if "__cpp_if_constexpr" not in macros:
self.config.available_features.add("libcpp-no-if-constexpr")
if "__cpp_structured_bindings" not in macros:
self.config.available_features.add("libcpp-no-structured-bindings")
if (
"__cpp_deduction_guides" not in macros
or intMacroValue(macros["__cpp_deduction_guides"]) < 201611
):
self.config.available_features.add("libcpp-no-deduction-guides")
if self.is_windows:
self.config.available_features.add("windows")
if self.cxx_stdlib_under_test == "libc++":
# LIBCXX-WINDOWS-FIXME is the feature name used to XFAIL the
# initial Windows failures until they can be properly diagnosed
# and fixed. This allows easier detection of new test failures
# and regressions. Note: New failures should not be suppressed
# using this feature. (Also see llvm.org/PR32730)
self.config.available_features.add("LIBCUDACXX-WINDOWS-FIXME")
if "msvc" not in self.config.available_features and not self.is_windows:
# Attempt to detect the glibc version by querying for __GLIBC__
# in 'features.h'. This is only available on Linux systems.
macros = self.cxx.dumpMacros(flags=["-include", "features.h"])
if isinstance(macros, dict) and "__GLIBC__" in macros:
maj_v, min_v = (macros["__GLIBC__"], macros["__GLIBC_MINOR__"])
self.config.available_features.add("glibc")
self.config.available_features.add("glibc-%s" % maj_v)
self.config.available_features.add("glibc-%s.%s" % (maj_v, min_v))
libcudacxx_gdb = self.get_lit_conf("libcudacxx_gdb")
if libcudacxx_gdb and "NOTFOUND" not in libcudacxx_gdb:
self.config.available_features.add("libcudacxx_gdb")
self.cxx.libcudacxx_gdb = libcudacxx_gdb
def configure_compile_flags(self):
self.configure_default_compile_flags()
# Configure extra flags
compile_flags_str = self.get_lit_conf("compile_flags", "")
self.cxx.compile_flags += shlex.split(compile_flags_str)
self.cxx.compile_flags += ["-D_CCCL_NO_SYSTEM_HEADER"]
if self.is_windows:
# FIXME: Can we remove this?
self.cxx.compile_flags += ["-D_CRT_SECURE_NO_WARNINGS"]
# --use-local-env is only supported by nvcc on Windows, not by hipcc or clang
if self.cxx.type == "nvcc":
self.cxx.compile_flags += ["--use-local-env"]
# Required so that tests using min/max don't fail on Windows,
# and so that those tests don't have to be changed to tolerate
# this insanity.
self.cxx.compile_flags += ["-DNOMINMAX"]
if "msvc" in self.config.available_features:
if self.cxx.type == "nvcc":
self.cxx.compile_flags += ["-Xcompiler"]
self.cxx.compile_flags += ["/bigobj"]
additional_flags = self.get_lit_conf("test_compiler_flags")
if additional_flags:
self.cxx.compile_flags += shlex.split(additional_flags)
compute_archs = self.get_lit_conf("compute_archs")
if self.cxx.type == "nvrtcc":
self.config.available_features.add("nvrtc")
if self.cxx.type == 'hiprtcc':
self.config.available_features.add("hiprtc")
if self.cxx.type == "nvcc":
self.cxx.compile_flags += ["--extended-lambda"]
real_arch_format = "-gencode=arch=compute_{0},code=sm_{0}"
virt_arch_format = "-gencode=arch=compute_{0},code=compute_{0}"
if self.cxx.type == "clang":
real_arch_format = "--cuda-gpu-arch=sm_{0}"
virt_arch_format = "--cuda-gpu-arch=compute_{0}"
self.cxx.compile_flags += ["-O1"]
pre_sm_32 = True
pre_sm_60 = True
pre_sm_70 = True
pre_sm_80 = True
pre_sm_90 = True
pre_sm_90a = True
pre_gfx90a = True
pre_gfx942 = True
pre_gfx908 = True
pre_gfx1030 = True
pre_gfx1100 = True
pre_gfx1101 = True
pre_gfx1200 = True
pre_gfx1201 = True
# TODO(HIP/AMD): does it make sense to add variants for gfx941 and gfx942?
if compute_archs and (self.cxx.type == 'nvcc' or self.cxx.type == 'clang' or self.cxx.type == 'nvrtcc'):
pre_gfx90a = False
pre_gfx942 = False
pre_gfx908 = False
pre_gfx1030 = False
pre_gfx1100 = False
pre_gfx1101 = False
pre_gfx1200 = False
pre_gfx1201 = False
pre_sm_32 = False
pre_sm_60 = False
pre_sm_70 = False
pre_sm_80 = False
pre_sm_90 = False
pre_sm_90a = False
self.lit_config.note("Compute Archs: %s" % compute_archs)
if compute_archs == "native":
compute_archs = self.get_compute_capabilities()
compute_archs = set(sorted(re.split("\\s|;|,", compute_archs)))
for s in compute_archs:
# Split arch and mode i.e. 80-virtual -> 80, virtual
arch, *mode = re.split("-", s)
# With Hopper there are new subarchitectures like 90a we need to handle those
subarchitecture = ""
if not arch.isnumeric():
subarchitecture = arch[-1]
arch = arch[:-1]
arch = int(arch)
if arch < 32:
pre_sm_32 = True
if arch < 60:
pre_sm_60 = True
if arch < 70:
pre_sm_70 = True
if arch < 80:
pre_sm_80 = True
if arch < 90:
pre_sm_90 = True
if arch < 90 or (arch == 90 and subarchitecture < "a"):
pre_sm_90a = True
arch_flag = real_arch_format.format(str(arch) + subarchitecture)
if mode.count("virtual"):
arch_flag = virt_arch_format.format(str(arch) + subarchitecture)
self.cxx.compile_flags += [arch_flag]
elif compute_archs and (self.cxx.type == 'hipcc' or self.cxx.type == 'hiprtcc'):
pre_gfx90a = False
pre_gfx908 = False
pre_gfx942 = False
pre_gfx1030 = False
pre_gfx1100 = False
pre_gfx1101 = False
pre_gfx1200 = False
pre_gfx1201 = False
pre_sm_32 = False
pre_sm_60 = False
pre_sm_70 = False
pre_sm_80 = False
pre_sm_90 = False
compute_archs = set(sorted(re.split('\s|;|,', compute_archs)))
for arch in compute_archs:
if arch == "gfx908":
pre_gfx90a = True
pre_gfx942 = True
pre_gfx1200 = True
pre_gfx1201 = True
elif arch == "gfx90a":
pre_gfx942 = True
pre_gfx1200 = True
pre_gfx1201 = True
elif arch == "gfx1030": # RDNA2
pre_gfx1100 = True
pre_gfx1101 = True
pre_gfx1200 = True
pre_gfx1201 = True
elif arch == "gfx1100" or arch == "gfx1101": # RDNA3
pre_gfx1200 = True
pre_gfx1201 = True
# Add --offload-arch for all valid gfx architectures
if arch.startswith("gfx"):
arch_flag = '--offload-arch={0}'.format(arch)
self.cxx.compile_flags += [arch_flag]
if pre_gfx908:
self.config.available_features.add("pre-gfx908")
if pre_gfx90a:
self.config.available_features.add("pre-gfx90a")
if pre_gfx942:
self.config.available_features.add("pre-gfx942")
if pre_gfx1030:
self.config.available_features.add("pre-gfx1030")
if pre_gfx1100:
self.config.available_features.add("pre-gfx1100")
if pre_gfx1101:
self.config.available_features.add("pre-gfx1101")
if pre_gfx1200:
self.config.available_features.add("pre-gfx1200")
if pre_gfx1201:
self.config.available_features.add("pre-gfx1201")
if pre_sm_32:
self.config.available_features.add("pre-sm-32")
if pre_sm_60:
self.config.available_features.add("pre-sm-60")
if pre_sm_70:
self.config.available_features.add("pre-sm-70")
if pre_sm_80:
self.config.available_features.add("pre-sm-80")
if pre_sm_90:
self.config.available_features.add("pre-sm-90")
if pre_sm_90a:
self.config.available_features.add("pre-sm-90a")
def configure_default_compile_flags(self):
nvcc_host_compiler = self.get_lit_conf("nvcc_host_compiler")
if nvcc_host_compiler and self.cxx.type == "nvcc":
self.cxx.compile_flags += ["-ccbin={0}".format(nvcc_host_compiler)]
# Try and get the std version from the command line. Fall back to
# default given in lit.site.cfg is not present. If default is not
# present then force c++11.
std = self.get_lit_conf("std")
if not std:
# Choose the newest possible language dialect if none is given.
possible_stds = [
"c++20",
"c++2a",
"c++17",
"c++1z",
"c++14",
"c++11",
"c++03",
]
if self.cxx.type == "gcc":
maj_v, _, _ = self.cxx.version
maj_v = int(maj_v)
if maj_v < 6:
possible_stds.remove("c++1z")
possible_stds.remove("c++17")
# FIXME: How many C++14 tests actually fail under GCC 5 and 6?
# Should we XFAIL them individually instead?
if maj_v < 6:
possible_stds.remove('c++14')
elif self.cxx.type == 'hipcc':
# FIXME(HIP): hipcc does not support new with --std=c++20, --std=cc+2a in device code
# see https://github.com/AMD-AI/libhipcxx/issues/25
possible_stds.remove('c++20')
possible_stds.remove('c++2a')
for s in possible_stds:
cxx = self.cxx
success = True
if self.cxx.type == "nvcc":
# NVCC warns, but doesn't error, if the host compiler
# doesn't support the dialect. It's also possible that the
# host compiler supports the dialect, but NVCC doesn't.
# So, first we need to check if NVCC supports the dialect...
if not self.cxx.hasCompileFlag("-std=%s" % s):
# If it doesn't, give up on this dialect.
success = False
# ... then we need to check if host compiler supports the
# dialect.
cxx = self.host_cxx
if cxx.type == "msvc":
if not cxx.hasCompileFlag("/std:%s" % s):
success = False
else:
if not cxx.hasCompileFlag("-std=%s" % s):
success = False
if success:
std = s
self.lit_config.note("inferred language dialect as: %s" % std)
break
if std:
# We found a dialect flag.
stdflag = "-std={0}".format(std)
if self.cxx.type == "msvc":
stdflag = "/std:{0}".format(std)
extraflags = []
if self.cxx.type == "clang":
extraflags = ["-Wno-unknown-cuda-version", "--no-cuda-version-check"]
# Do a check with the user/config flag to ensure that the flag is supported.
if not self.cxx.hasCompileFlag([stdflag] + extraflags):
raise OSError(
"Configured compiler does not support flag {0}".format(stdflag)
)
self.cxx.flags += [stdflag]
if not std:
# There is no dialect flag. This happens with older MSVC.
if self.cxx.type == "nvcc":
std = self.host_cxx.default_dialect
else:
std = self.cxx.default_dialect
self.lit_config.note("using default language dialect: %s" % std)
std_feature = std.replace("gnu++", "c++")
std_feature = std.replace("1z", "17")
std_feature = std.replace("2a", "20")
self.config.available_features.add(std_feature)
# Configure include paths
self.configure_compile_flags_header_includes()
self.target_info.add_cxx_compile_flags(self.cxx.compile_flags)
# Configure feature flags.
self.configure_compile_flags_exceptions()
self.configure_compile_flags_rtti()
self.configure_compile_flags_abi_version()
enable_32bit = self.get_lit_bool("enable_32bit", False)
if enable_32bit:
self.cxx.flags += ["-m32"]
# Use verbose output for better errors
if not self.cxx.use_ccache or self.cxx.type == "msvc":
self.cxx.flags += ["-v"]
sysroot = self.get_lit_conf("sysroot")
if sysroot:
self.cxx.flags += ["--sysroot=" + sysroot]
gcc_toolchain = self.get_lit_conf("gcc_toolchain")
if gcc_toolchain:
self.cxx.flags += ["--gcc-toolchain=" + gcc_toolchain]
# NOTE: the _DEBUG definition must precede the triple check because for
# the Windows build of libc++, the forced inclusion of a header requires
# that _DEBUG is defined. Incorrect ordering will result in -target
# being elided.
if self.is_windows and self.debug_build:
self.cxx.compile_flags += ["-D_DEBUG"]
if self.use_target:
if not self.cxx.addFlagIfSupported(
["--target=" + self.config.target_triple]
):
self.lit_config.warning(
"use_target is true but --target is "
"not supported by the compiler"
)
if self.use_deployment:
arch, name, version = self.config.deployment
self.cxx.flags += ["-arch", arch]
self.cxx.flags += ["-m" + name + "-version-min=" + version]
# Add includes for support headers used in the tests.
support_path = os.path.join(self.libcudacxx_src_root, "test", "support")
self.cxx.compile_flags += ["-I" + support_path]
# Add includes for the PSTL headers
pstl_src_root = self.get_lit_conf("pstl_src_root")
pstl_obj_root = self.get_lit_conf("pstl_obj_root")
if pstl_src_root is not None and pstl_obj_root is not None:
self.cxx.compile_flags += ["-I" + os.path.join(pstl_src_root, "include")]
self.cxx.compile_flags += [
"-I" + os.path.join(pstl_obj_root, "generated_headers")
]
self.cxx.compile_flags += ["-I" + os.path.join(pstl_src_root, "test")]
self.config.available_features.add("parallel-algorithms")
# FIXME(EricWF): variant_size.pass.cpp requires a slightly larger
# template depth with older Clang versions.
self.cxx.addFlagIfSupported("-ftemplate-depth=270")
# If running without execution we need to mark tests that only fail at runtime as unsupported
if self.lit_config.noExecute:
self.config.available_features.add("no_execute")
def configure_compile_flags_header_includes(self):
support_path = os.path.join(self.libcudacxx_src_root, "test", "support")
self.configure_config_site_header()
if self.cxx_stdlib_under_test != "libstdc++" and not self.is_windows:
self.cxx.compile_flags += [
"-include",
os.path.join(support_path, "nasty_macros.h"),
]
if self.cxx_stdlib_under_test == "msvc":
self.cxx.compile_flags += [
"-include",
os.path.join(support_path, "msvc_stdlib_force_include.h"),
]
pass
if (
self.is_windows
and self.debug_build
and self.cxx_stdlib_under_test != "msvc"
):
self.cxx.compile_flags += [
"-include",
os.path.join(support_path, "set_windows_crt_report_mode.h"),
]
cxx_headers = self.get_lit_conf("cxx_headers")
if cxx_headers == "" or (
cxx_headers is None and self.cxx_stdlib_under_test != "libc++"
):
self.lit_config.note("using the system cxx headers")
return
# I don't think this is required, since removing it helps clang-cuda compile and libcudacxx only supports building in CUDA modes?
# if self.cxx.type != 'nvcc' and self.cxx.type != 'pgi' and self.cxx.type != 'hipcc':
# self.cxx.compile_flags += ['-nostdinc++']
if cxx_headers is None:
cxx_headers = os.path.join(self.libcudacxx_src_root, "include")
if not os.path.isdir(cxx_headers):
self.lit_config.fatal("cxx_headers='%s' is not a directory." % cxx_headers)
self.cxx.compile_flags += ["-I" + cxx_headers]
if self.libcudacxx_obj_root is not None:
cxxabi_headers = os.path.join(
self.libcudacxx_obj_root, "include", "c++build"
)
if os.path.isdir(cxxabi_headers):
self.cxx.compile_flags += ["-I" + cxxabi_headers]
def configure_config_site_header(self):
# Check for a possible __config_site in the build directory. We
# use this if it exists.
if self.libcudacxx_obj_root is None:
return
config_site_header = os.path.join(self.libcudacxx_obj_root, "__config_site")
if not os.path.isfile(config_site_header):
return
contained_macros = self.parse_config_site_and_add_features(config_site_header)
self.lit_config.note(
"Using __config_site header %s with macros: %r"
% (config_site_header, contained_macros)
)
# FIXME: This must come after the call to
# 'parse_config_site_and_add_features(...)' in order for it to work.
self.cxx.compile_flags += ["-include", config_site_header]
def parse_config_site_and_add_features(self, header):
"""parse_config_site_and_add_features - Deduce and add the test
features that that are implied by the #define's in the __config_site
header. Return a dictionary containing the macros found in the
'__config_site' header.
"""
# MSVC can't dump macros, so we just give up.
if "msvc" in self.config.available_features:
return {}
# Parse the macro contents of __config_site by dumping the macros
# using 'c++ -dM -E' and filtering the predefines.
predefines = self._dump_macros_verbose()
macros = self._dump_macros_verbose(header)
feature_macros_keys = set(macros.keys()) - set(predefines.keys())
feature_macros = {}
for k in feature_macros_keys:
feature_macros[k] = macros[k]
# We expect the header guard to be one of the definitions
assert "_LIBCUDACXX_CONFIG_SITE" in feature_macros
del feature_macros["_LIBCUDACXX_CONFIG_SITE"]
# The __config_site header should be non-empty. Otherwise it should
# have never been emitted by CMake.
assert len(feature_macros) > 0
# FIXME: This is a hack that should be fixed using module maps.
# If modules are enabled then we have to lift all of the definitions
# in __config_site onto the command line.
for m in feature_macros:
define = "-D%s" % m
if feature_macros[m]:
define += "=%s" % (feature_macros[m])
self.cxx.modules_flags += [define]
if self.cxx.hasCompileFlag("-Wno-macro-redefined"):
self.cxx.compile_flags += ["-Wno-macro-redefined"]
# Transform each macro name into the feature name used in the tests.
# Ex. _LIBCUDACXX_HAS_NO_THREADS -> libcpp-has-no-threads
for m in feature_macros:
assert m.startswith("_LIBCUDACXX_HAS_") or m.startswith("_LIBCUDACXX_ABI_")
m = m.lower()[1:].replace("_", "-")
self.config.available_features.add(m)
return feature_macros
def configure_compile_flags_exceptions(self):
enable_exceptions = self.get_lit_bool("enable_exceptions", True)
nvrtc = self.get_lit_bool("is_nvrtc", False)
hiprtc = self.get_lit_bool('is_hiprtc', False)
if not enable_exceptions:
self.config.available_features.add("libcpp-no-exceptions")
if "nvhpc" in self.config.available_features:
# NVHPC reports all expressions as `noexcept(true)` with its
# "no exceptions" mode. Override the setting from CMake as
# a temporary workaround for that.
pass
# TODO: I don't know how to shut off exceptions with MSVC.
elif "msvc" not in self.config.available_features:
if self.cxx.type == "nvcc":
self.cxx.compile_flags += ["-Xcompiler"]
self.cxx.compile_flags += ["-fno-exceptions"]
elif nvrtc:
self.config.available_features.add("libcpp-no-exceptions")
elif hiprtc:
self.config.available_features.add('libcpp-no-exceptions')
def configure_compile_flags_rtti(self):
enable_rtti = self.get_lit_bool("enable_rtti", True)
if not enable_rtti:
self.config.available_features.add("libcpp-no-rtti")
if self.cxx.type == "nvcc":
self.cxx.compile_flags += ["-Xcompiler"]
if "nvhpc" in self.config.available_features:
self.cxx.compile_flags += ["--no_rtti"]
elif "msvc" in self.config.available_features:
self.cxx.compile_flags += ["/GR-"]
self.cxx.compile_flags += ["-D_SILENCE_CXX20_CISO646_REMOVED_WARNING"]
else:
self.cxx.compile_flags += ["-fno-rtti"]
def configure_compile_flags_abi_version(self):
abi_unstable = self.get_lit_bool("abi_unstable")
if abi_unstable:
self.config.available_features.add("libcpp-abi-unstable")
self.cxx.compile_flags += ["-D_LIBCUDACXX_ABI_UNSTABLE"]
def configure_filesystem_compile_flags(self):
if not self.get_lit_bool("enable_filesystem", default=True):
return
static_env = os.path.join(
self.libcudacxx_src_root,
"test",
"libcudacxx",
"std",
"input.output",
"filesystems",
"Inputs",
"static_test_env",
)
static_env = os.path.realpath(static_env)
assert os.path.isdir(static_env)
self.cxx.compile_flags += [
'-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env
]
dynamic_env = os.path.join(
self.config.test_exec_root, "filesystem", "Output", "dynamic_env"
)
dynamic_env = os.path.realpath(dynamic_env)
if not os.path.isdir(dynamic_env):
os.makedirs(dynamic_env)
self.cxx.compile_flags += [
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env
]
self.exec_env["LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT"] = "%s" % dynamic_env
dynamic_helper = os.path.join(
self.libcudacxx_src_root,
"test",
"support",
"filesystem_dynamic_test_helper.py",
)
assert os.path.isfile(dynamic_helper)
self.cxx.compile_flags += [
'-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER="%s %s"'
% (sys.executable, dynamic_helper)
]
def configure_link_flags(self):
nvcc_host_compiler = self.get_lit_conf("nvcc_host_compiler")
if nvcc_host_compiler and self.cxx.type == "nvcc":
self.cxx.link_flags += ["-ccbin={0}".format(nvcc_host_compiler)]
if self.is_windows:
# --use-local-env is only supported by nvcc on Windows, not by hipcc or clang
if self.cxx.type == "nvcc":
self.cxx.link_flags += ["--use-local-env"]
# Configure library path
self.configure_link_flags_cxx_library_path()
self.configure_link_flags_abi_library_path()
# Configure libraries
if self.cxx_stdlib_under_test == "libc++":
if self.get_lit_conf("name") != "libcu++":
if (
"nvhpc" not in self.config.available_features
or not self.cxx.is_nvrtc
):
if self.cxx.type == "nvcc":
self.cxx.link_flags += ["-Xcompiler"]
self.cxx.link_flags += ["-nodefaultlibs"]
# FIXME: Handle MSVCRT as part of the ABI library handling.
if self.is_windows and "msvc" not in self.config.available_features:
if self.cxx.type == "nvcc":
self.cxx.link_flags += ["-Xcompiler"]
self.cxx.link_flags += ["-nostdlib"]
self.configure_link_flags_cxx_library()
self.configure_link_flags_abi_library()
self.configure_extra_library_flags()
elif self.cxx_stdlib_under_test == "libstdc++":
self.config.available_features.add("c++experimental")
# These libraries don't exist on Windows
if not self.is_windows:
self.cxx.link_flags += ["-lm", "-pthread"]
elif self.cxx_stdlib_under_test == "msvc":
# FIXME: Correctly setup debug/release flags here.
pass
elif self.cxx_stdlib_under_test == "cxx_default":
self.cxx.link_flags += ["-pthread"]
else:
self.lit_config.fatal("invalid stdlib under test")
link_flags_str = self.get_lit_conf("link_flags", "")
self.cxx.link_flags += shlex.split(link_flags_str)
def configure_link_flags_cxx_library_path(self):
if not self.use_system_cxx_lib:
if self.cxx_library_root:
self.cxx.link_flags += ["-L" + self.cxx_library_root]
if self.is_windows and self.link_shared:
self.add_path(self.cxx.compile_env, self.cxx_library_root)
if self.cxx_runtime_root:
if not self.is_windows:
if self.cxx.type == "nvcc":
self.cxx.link_flags += [
"-Xcompiler",
'"-Wl,-rpath,' + self.cxx_runtime_root + '"',
]
else:
self.cxx.link_flags += ["-Wl,-rpath," + self.cxx_runtime_root]
elif self.is_windows and self.link_shared:
self.add_path(self.exec_env, self.cxx_runtime_root)
elif os.path.isdir(str(self.use_system_cxx_lib)):
self.cxx.link_flags += ["-L" + self.use_system_cxx_lib]
if not self.is_windows:
if self.cxx.type == "nvcc":
self.cxx.link_flags += [
"-Xcompiler",
'"-Wl,-rpath,' + self.cxx_runtime_root + '"',
]
else:
self.cxx.link_flags += ["-Wl,-rpath," + self.use_system_cxx_lib]
if self.is_windows and self.link_shared:
self.add_path(self.cxx.compile_env, self.use_system_cxx_lib)
additional_flags = self.get_lit_conf("test_linker_flags")
if additional_flags:
self.cxx.link_flags += shlex.split(additional_flags)
def configure_link_flags_abi_library_path(self):
# Configure ABI library paths.
self.abi_library_root = self.get_lit_conf("abi_library_path")
if self.abi_library_root:
self.cxx.link_flags += ["-L" + self.abi_library_root]
if not self.is_windows:
if self.cxx.type == "nvcc":
self.cxx.link_flags += [
"-Xcompiler",
'"-Wl,-rpath,' + self.cxx_runtime_root + '"',
]
else:
self.cxx.link_flags += ["-Wl,-rpath," + self.abi_library_root]
else:
self.add_path(self.exec_env, self.abi_library_root)
def configure_link_flags_cxx_library(self):
libcxx_experimental = self.get_lit_bool("enable_experimental", default=False)
if libcxx_experimental:
self.config.available_features.add("c++experimental")
self.cxx.link_flags += ["-lc++experimental"]
if self.link_shared and self.cxx.type != 'hipcc':
self.cxx.link_flags += ["-lc++"]
def configure_link_flags_abi_library(self):
cxx_abi = self.get_lit_conf("cxx_abi", "libcxxabi")
if cxx_abi == "libstdc++":
self.cxx.link_flags += ["-lstdc++"]
elif cxx_abi == "libsupc++":
self.cxx.link_flags += ["-lsupc++"]
elif cxx_abi == "libcxxabi":
# If the C++ library requires explicitly linking to libc++abi, or
# if we're testing libc++abi itself (the test configs are shared),
# then link it.
testing_libcxxabi = self.get_lit_conf("name", "") == "libc++abi"
if self.target_info.allow_cxxabi_link() or testing_libcxxabi:
libcxxabi_shared = self.get_lit_bool("libcxxabi_shared", default=True)
if libcxxabi_shared:
self.cxx.link_flags += ["-lc++abi"]
else:
cxxabi_library_root = self.get_lit_conf("abi_library_path")
if cxxabi_library_root:
libname = self.make_static_lib_name("c++abi")
abs_path = os.path.join(cxxabi_library_root, libname)
self.cxx.link_flags += [abs_path]
else:
self.cxx.link_flags += ["-lc++abi"]
elif cxx_abi == "libcxxrt":
self.cxx.link_flags += ["-lcxxrt"]
elif cxx_abi == "vcruntime":
debug_suffix = "d" if self.debug_build else ""
self.cxx.link_flags += [
"-l%s%s" % (lib, debug_suffix)
for lib in ["vcruntime", "ucrt", "msvcrt"]
]
elif cxx_abi == "none" or cxx_abi == "default":
if self.is_windows:
debug_suffix = "d" if self.debug_build else ""
self.cxx.link_flags += ["-lmsvcrt%s" % debug_suffix]
else:
self.lit_config.fatal("C++ ABI setting %s unsupported for tests" % cxx_abi)
def configure_extra_library_flags(self):
if self.get_lit_bool("cxx_ext_threads", default=False):
self.cxx.link_flags += ["-lc++external_threads"]
self.target_info.add_cxx_link_flags(self.cxx.link_flags)
def configure_color_diagnostics(self):
use_color = self.get_lit_conf("color_diagnostics")
if use_color is None:
use_color = os.environ.get("LIBCXX_COLOR_DIAGNOSTICS")
if use_color is None:
return
if use_color != "":
self.lit_config.fatal(
'Invalid value for color_diagnostics "%s".' % use_color
)
color_flag = "-fdiagnostics-color=always"
# Check if the compiler supports the color diagnostics flag. Issue a
# warning if it does not since color diagnostics have been requested.
if not self.cxx.hasCompileFlag(color_flag):
self.lit_config.warning(
"color diagnostics have been requested but are not supported "
"by the compiler"
)
else:
self.cxx.flags += [color_flag]
def configure_debug_mode(self):
debug_level = self.get_lit_conf("debug_level", None)
if not debug_level:
return
if debug_level not in ["0", "1"]:
self.lit_config.fatal('Invalid value for debug_level "%s".' % debug_level)
self.cxx.compile_flags += ["-D_LIBCUDACXX_DEBUG=%s" % debug_level]
def configure_warnings(self):
default_enable_warnings = (
"clang" in self.config.available_features
or "msvc" in self.config.available_features
or "nvcc" in self.config.available_features
)
enable_warnings = self.get_lit_bool("enable_warnings", default_enable_warnings)
self.cxx.useWarnings(enable_warnings)
if "nvcc" in self.config.available_features:
self.cxx.warning_flags += ["-Xcudafe", "--display_error_number"]
self.cxx.warning_flags += ["-Werror=all-warnings"]
if "msvc" in self.config.available_features:
self.cxx.warning_flags += ["-Xcompiler", "/W4", "-Xcompiler", "/WX"]
# warning C4100: 'quack': unreferenced formal parameter
self.cxx.warning_flags += ["-Xcompiler", "-wd4100"]
# warning C4127: conditional expression is constant
self.cxx.warning_flags += ["-Xcompiler", "-wd4127"]
# warning C4180: qualifier applied to function type has no meaning; ignored
self.cxx.warning_flags += ["-Xcompiler", "-wd4180"]
# warning C4309: 'moo': truncation of constant value
self.cxx.warning_flags += ["-Xcompiler", "-wd4309"]
# warning C4996: deprecation warnings
self.cxx.warning_flags += ["-Xcompiler", "-wd4996"]
else:
# TODO: Re-enable soon.
def addIfHostSupports(flag):
if hasattr(self, "host_cxx") and self.host_cxx.hasWarningFlag(flag):
self.cxx.warning_flags += ["-Xcompiler", flag]
addIfHostSupports("-Wall")
addIfHostSupports("-Wextra")
addIfHostSupports("-Werror")
if "gcc" in self.config.available_features:
addIfHostSupports(
"-Wno-literal-suffix"
) # GCC warning about reserved UDLs
addIfHostSupports(
"-Wno-user-defined-literals"
) # Clang warning about reserved UDLs
addIfHostSupports("-Wno-unused-parameter")
addIfHostSupports(
"-Wno-unused-local-typedefs"
) # GCC warning local typdefs
addIfHostSupports("-Wno-deprecated-declarations")
addIfHostSupports("-Wno-noexcept-type")
addIfHostSupports("-Wno-unused-function")
if "gcc-4.8" in self.config.available_features:
# GCC pre-GCC5 spuriously generates these on reasonable aggregate initialization.
addIfHostSupports("-Wno-missing-field-initializers")
# TODO: port the warning disables from the non-NVCC path?
self.cxx.warning_flags += [
"-D_LIBCUDACXX_DISABLE_PRAGMA_GCC_SYSTEM_HEADER"
]
pass
else:
self.cxx.warning_flags += [
"-D_LIBCUDACXX_DISABLE_PRAGMA_GCC_SYSTEM_HEADER",
"-Wall",
"-Wextra",
"-Werror",
]
if self.cxx.hasWarningFlag("-Wuser-defined-warnings"):
self.cxx.warning_flags += ["-Wuser-defined-warnings"]
self.config.available_features.add("diagnose-if-support")
self.cxx.addWarningFlagIfSupported("-Wshadow")
self.cxx.addWarningFlagIfSupported("-Wno-unused-command-line-argument")
self.cxx.addWarningFlagIfSupported("-Wno-attributes")
self.cxx.addWarningFlagIfSupported("-Wno-pessimizing-move")
self.cxx.addWarningFlagIfSupported("-Wno-c++11-extensions")
self.cxx.addWarningFlagIfSupported("-Wno-user-defined-literals")
self.cxx.addWarningFlagIfSupported("-Wno-noexcept-type")
self.cxx.addWarningFlagIfSupported("-Wno-aligned-allocation-unavailable")
# These warnings should be enabled in order to support the MSVC
# team using the test suite; They enable the warnings below and
# expect the test suite to be clean.
self.cxx.addWarningFlagIfSupported("-Wsign-compare")
self.cxx.addWarningFlagIfSupported("-Wunused-variable")
self.cxx.addWarningFlagIfSupported("-Wunused-parameter")
self.cxx.addWarningFlagIfSupported("-Wunreachable-code")
std = self.get_lit_conf("std", None)
if std in ["c++98", "c++03"]:
if "nvcc" not in self.config.available_features:
# The '#define static_assert' provided by libc++ in C++03 mode
# causes an unused local typedef whenever it is used.
self.cxx.addWarningFlagIfSupported("-Wno-unused-local-typedef")
def configure_sanitizer(self):
san = self.get_lit_conf("use_sanitizer", "").strip()
if san:
self.target_info.add_sanitizer_features(san, self.config.available_features)
# Search for llvm-symbolizer along the compiler path first
# and then along the PATH env variable.
symbolizer_search_paths = os.environ.get("PATH", "")
cxx_path = libcudacxx.util.which(self.cxx.path)
if cxx_path is not None:
symbolizer_search_paths = (
os.path.dirname(cxx_path) + os.pathsep + symbolizer_search_paths
)
llvm_symbolizer = libcudacxx.util.which(
"llvm-symbolizer", symbolizer_search_paths
)
def add_ubsan():
self.cxx.flags += [
"-fsanitize=undefined",
"-fno-sanitize=float-divide-by-zero",
"-fno-sanitize-recover=all",
]
self.exec_env["UBSAN_OPTIONS"] = "print_stacktrace=1"
self.config.available_features.add("ubsan")
# Setup the sanitizer compile flags
self.cxx.flags += ["-g", "-fno-omit-frame-pointer"]
if (
san == "Address"
or san == "Address;Undefined"
or san == "Undefined;Address"
):
self.cxx.flags += ["-fsanitize=address"]
if llvm_symbolizer is not None:
self.exec_env["ASAN_SYMBOLIZER_PATH"] = llvm_symbolizer
# FIXME: Turn ODR violation back on after PR28391 is resolved
# https://bugs.llvm.org/show_bug.cgi?id=28391
self.exec_env["ASAN_OPTIONS"] = "detect_odr_violation=0"
self.config.available_features.add("asan")
self.config.available_features.add("sanitizer-new-delete")
self.cxx.compile_flags += ["-O1"]
if san == "Address;Undefined" or san == "Undefined;Address":
add_ubsan()
elif san == "Memory" or san == "MemoryWithOrigins":
self.cxx.flags += ["-fsanitize=memory"]
if san == "MemoryWithOrigins":
self.cxx.compile_flags += ["-fsanitize-memory-track-origins"]
if llvm_symbolizer is not None:
self.exec_env["MSAN_SYMBOLIZER_PATH"] = llvm_symbolizer
self.config.available_features.add("msan")
self.config.available_features.add("sanitizer-new-delete")
self.cxx.compile_flags += ["-O1"]
elif san == "Undefined":
add_ubsan()
self.cxx.compile_flags += ["-O2"]
elif san == "Thread":
self.cxx.flags += ["-fsanitize=thread"]
self.config.available_features.add("tsan")
self.config.available_features.add("sanitizer-new-delete")
else:
self.lit_config.fatal(
"unsupported value for " "use_sanitizer: {0}".format(san)
)
san_lib = self.get_lit_conf("sanitizer_library")
if san_lib:
if self.cxx.type == "nvcc":
self.cxx.link_flags += [
"-Xcompiler",
'"-Wl,-rpath,' + os.path.dirname(san_lib) + '"',
]
else:
self.cxx.link_flags += ["-Wl,-rpath," + os.path.dirname(san_lib)]
def configure_coverage(self):
self.generate_coverage = self.get_lit_bool("generate_coverage", False)
if self.generate_coverage:
self.cxx.flags += ["-g", "--coverage"]
self.cxx.compile_flags += ["-O0"]
def configure_coroutines(self):
if self.cxx.hasCompileFlag("-fcoroutines-ts"):
macros = self._dump_macros_verbose(flags=["-fcoroutines-ts"])
if "__cpp_coroutines" not in macros:
self.lit_config.warning(
"-fcoroutines-ts is supported but "
"__cpp_coroutines is not defined"
)
# Consider coroutines supported only when the feature test macro
# reflects a recent value.
if intMacroValue(macros["__cpp_coroutines"]) >= 201703:
self.config.available_features.add("fcoroutines-ts")
def configure_modules(self):
modules_flags = ["-fmodules"]
if platform.system() != "Darwin":
modules_flags += ["-Xclang", "-fmodules-local-submodule-visibility"]
supports_modules = self.cxx.hasCompileFlag(modules_flags)
enable_modules = self.get_modules_enabled()
if enable_modules and not supports_modules:
self.lit_config.fatal(
"-fmodules is enabled but not supported by the compiler"
)
if not supports_modules:
return
self.config.available_features.add("modules-support")
module_cache = os.path.join(self.config.test_exec_root, "modules.cache")
module_cache = os.path.realpath(module_cache)
if os.path.isdir(module_cache):
shutil.rmtree(module_cache)
os.makedirs(module_cache)
self.cxx.modules_flags += modules_flags + [
"-fmodules-cache-path=" + module_cache
]
if enable_modules:
self.config.available_features.add("-fmodules")
self.cxx.useModules()
def configure_substitutions(self):
sub = self.config.substitutions
cxx_path = shlex.quote(self.cxx.path)
# Configure compiler substitutions
sub.append(("%cxx", cxx_path))
sub.append(("%libcxx_src_root", self.libcudacxx_src_root))
# Configure flags substitutions
flags_str = " ".join([shlex.quote(f) for f in self.cxx.flags])
compile_flags_str = " ".join([shlex.quote(f) for f in self.cxx.compile_flags])
link_flags_str = " ".join([shlex.quote(f) for f in self.cxx.link_flags])
all_flags = "%s %s %s" % (flags_str, compile_flags_str, link_flags_str)
sub.append(("%flags", flags_str))
sub.append(("%compile_flags", compile_flags_str))
sub.append(("%link_flags", link_flags_str))
sub.append(("%all_flags", all_flags))
if self.cxx.isVerifySupported():
verify_str = " " + " ".join(self.cxx.verify_flags) + " "
sub.append(("%verify", verify_str))
# Add compile and link shortcuts
compile_str = cxx_path + " -o %t.o %s -c " + flags_str + " " + compile_flags_str
link_str = cxx_path + " -o %t.exe %t.o " + flags_str + " " + link_flags_str
assert type(link_str) is str
build_str = cxx_path + " -o %t.exe %s " + all_flags
if self.cxx.use_modules:
sub.append(("%compile_module", compile_str))
sub.append(("%build_module", build_str))
elif self.cxx.modules_flags is not None:
modules_str = " ".join(self.cxx.modules_flags) + " "
sub.append(("%compile_module", compile_str + " " + modules_str))
sub.append(("%build_module", build_str + " " + modules_str))
sub.append(("%compile", compile_str))
sub.append(("%link", link_str))
sub.append(("%build", build_str))
# Configure exec prefix substitutions.
# Configure run env substitution.
sub.append(("%run", "%t.exe"))
# Configure not program substitutions
not_py = os.path.join(self.libcudacxx_src_root, "test", "utils", "not.py")
not_str = "%s %s " % (shlex.quote(sys.executable), shlex.quote(not_py))
sub.append(("not ", not_str))
if self.get_lit_conf("libcudacxx_gdb"):
sub.append(("%libcxx_gdb", self.get_lit_conf("libcudacxx_gdb")))
def can_use_deployment(self):
# Check if the host is on an Apple platform using clang.
if not self.target_info.platform() == "darwin":
return False
if not self.target_info.is_host_macosx():
return False
if not self.cxx.type.endswith("clang"):
return False
return True
def configure_triple(self):
# Get or infer the target triple.
target_triple = self.get_lit_conf("target_triple")
self.use_target = self.get_lit_bool("use_target", False)
if self.use_target and target_triple:
self.lit_config.warning("use_target is true but no triple is specified")
# Use deployment if possible.
self.use_deployment = not self.use_target and self.can_use_deployment()
if self.use_deployment:
return
# Save the triple (and warn on Apple platforms).
self.config.target_triple = target_triple
if self.use_target and "apple" in target_triple:
self.lit_config.warning(
"consider using arch and platform instead"
" of target_triple on Apple platforms"
)
# If no target triple was given, try to infer it from the compiler
# under test.
if not self.config.target_triple:
target_triple = (
self.cxx if self.cxx.type != "nvcc" else self.host_cxx
).getTriple()
# Drop sub-major version components from the triple, because the
# current XFAIL handling expects exact matches for feature checks.
# Example: x86_64-apple-darwin14.0.0 -> x86_64-apple-darwin14
# The 5th group handles triples greater than 3 parts
# (ex x86_64-pc-linux-gnu).
target_triple = re.sub(
r"([^-]+)-([^-]+)-([^.]+)([^-]*)(.*)", r"\1-\2-\3\5", target_triple
)
# linux-gnu is needed in the triple to properly identify linuxes
# that use GLIBC. Handle redhat and opensuse triples as special
# cases and append the missing `-gnu` portion.
if target_triple.endswith("redhat-linux") or target_triple.endswith(
"suse-linux"
):
target_triple += "-gnu"
self.config.target_triple = target_triple
self.lit_config.note(
"inferred target_triple as: %r" % self.config.target_triple
)
def configure_deployment(self):
assert self.use_deployment is not None
assert self.use_target is not None
if not self.use_deployment:
# Warn about ignored parameters.
if self.get_lit_conf("arch"):
self.lit_config.warning("ignoring arch, using target_triple")
if self.get_lit_conf("platform"):
self.lit_config.warning("ignoring platform, using target_triple")
return
assert not self.use_target
assert self.target_info.is_host_macosx()
# Always specify deployment explicitly on Apple platforms, since
# otherwise a platform is picked up from the SDK. If the SDK version
# doesn't match the system version, tests that use the system library
# may fail spuriously.
arch = self.get_lit_conf("arch")
if not arch:
arch = (
(self.cxx if self.cxx.type != "nvcc" else self.host_cxx)
.getTriple()
.split("-", 1)[0]
)
self.lit_config.note("inferred arch as: %r" % arch)
inferred_platform, name, version = self.target_info.get_platform()
if inferred_platform:
self.lit_config.note("inferred platform as: %r" % (name + version))
self.config.deployment = (arch, name, version)
# Set the target triple for use by lit.
self.config.target_triple = arch + "-apple-" + name + version
self.lit_config.note(
"computed target_triple as: %r" % self.config.target_triple
)
# If we're testing a system libc++ as opposed to the upstream LLVM one,
# take the version of the system libc++ into account to compute which
# features are enabled/disabled. Otherwise, disable availability markup,
# which is not relevant for non-shipped flavors of libc++.
if self.use_system_cxx_lib:
# Dylib support for shared_mutex was added in macosx10.12.
if name == "macosx" and version in ("10.%s" % v for v in range(7, 12)):
self.config.available_features.add("dylib-has-no-shared_mutex")
self.lit_config.note(
"shared_mutex is not supported by the deployment target"
)
# Throwing bad_optional_access, bad_variant_access and bad_any_cast is
# supported starting in macosx10.14.
if name == "macosx" and version in ("10.%s" % v for v in range(7, 14)):
self.config.available_features.add("dylib-has-no-bad_optional_access")
self.lit_config.note(
"throwing bad_optional_access is not supported by the deployment target"
)
self.config.available_features.add("dylib-has-no-bad_variant_access")
self.lit_config.note(
"throwing bad_variant_access is not supported by the deployment target"
)
self.config.available_features.add("dylib-has-no-bad_any_cast")
self.lit_config.note(
"throwing bad_any_cast is not supported by the deployment target"
)
# Filesystem is support on Apple platforms starting with macosx10.15.
if name == "macosx" and version in ("10.%s" % v for v in range(7, 15)):
self.config.available_features.add("dylib-has-no-filesystem")
self.lit_config.note(
"the deployment target does not support <filesystem>"
)
def configure_env(self):
self.target_info.configure_env(self.exec_env)
def add_path(self, dest_env, new_path):
if "PATH" not in dest_env:
dest_env["PATH"] = new_path
else:
split_char = ";" if self.is_windows else ":"
dest_env["PATH"] = "%s%s%s" % (new_path, split_char, dest_env["PATH"])