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
1878 lines
84 KiB
Python
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"])
|