Skip to content

Commit 7f81869

Browse files
authored
[libc++] Split features.py into multiple files (#167353)
The features.py file that performs detection of Lit features had grown to be massive, so this patch splits it into smaller chunks which makes it easier to keep things organized.
1 parent 45bb926 commit 7f81869

File tree

10 files changed

+1002
-921
lines changed

10 files changed

+1002
-921
lines changed

libcxx/utils/libcxx/test/features.py

Lines changed: 0 additions & 920 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# ===----------------------------------------------------------------------===##
2+
#
3+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
# See https://llvm.org/LICENSE.txt for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
# ===----------------------------------------------------------------------===##
8+
9+
from . import availability, compiler, gdb, libcxx_macros, localization, misc, platform
10+
11+
# Lit features are evaluated in order. Some features depend on other features, so
12+
# we are careful to define them in the correct order. For example, several features
13+
# require the compiler detection to have been performed.
14+
DEFAULT_FEATURES = []
15+
DEFAULT_FEATURES += compiler.features
16+
DEFAULT_FEATURES += libcxx_macros.features
17+
DEFAULT_FEATURES += platform.features
18+
DEFAULT_FEATURES += localization.features
19+
DEFAULT_FEATURES += gdb.features
20+
DEFAULT_FEATURES += misc.features
21+
DEFAULT_FEATURES += availability.features
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# ===----------------------------------------------------------------------===##
2+
#
3+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
# See https://llvm.org/LICENSE.txt for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
# ===----------------------------------------------------------------------===##
8+
9+
from libcxx.test.dsl import Feature
10+
from lit.BooleanExpression import BooleanExpression
11+
12+
# Helpers to define correspondances between LLVM versions and vendor system versions.
13+
# Those are used for backdeployment features below, do not use directly in tests.
14+
features = [
15+
Feature(
16+
name="_target-has-llvm-22",
17+
when=lambda cfg: BooleanExpression.evaluate(
18+
"TBD",
19+
cfg.available_features,
20+
),
21+
),
22+
Feature(
23+
name="_target-has-llvm-21",
24+
when=lambda cfg: BooleanExpression.evaluate(
25+
"TBD",
26+
cfg.available_features,
27+
),
28+
),
29+
Feature(
30+
name="_target-has-llvm-20",
31+
when=lambda cfg: BooleanExpression.evaluate(
32+
"_target-has-llvm-21 || target={{.+}}-apple-macosx{{26.[0-9](.\d+)?}}",
33+
cfg.available_features,
34+
),
35+
),
36+
Feature(
37+
name="_target-has-llvm-19",
38+
when=lambda cfg: BooleanExpression.evaluate(
39+
"_target-has-llvm-20 || target={{.+}}-apple-macosx{{15.[4-9](.\d+)?}}",
40+
cfg.available_features,
41+
),
42+
),
43+
Feature(
44+
name="_target-has-llvm-18",
45+
when=lambda cfg: BooleanExpression.evaluate(
46+
"_target-has-llvm-19 || target={{.+}}-apple-macosx{{15.[0-3](.\d+)?}}",
47+
cfg.available_features,
48+
),
49+
),
50+
Feature(
51+
name="_target-has-llvm-17",
52+
when=lambda cfg: BooleanExpression.evaluate(
53+
"_target-has-llvm-18 || target={{.+}}-apple-macosx{{14.[4-9](.\d+)?}}",
54+
cfg.available_features,
55+
),
56+
),
57+
Feature(
58+
name="_target-has-llvm-16",
59+
when=lambda cfg: BooleanExpression.evaluate(
60+
"_target-has-llvm-17 || target={{.+}}-apple-macosx{{14.[0-3](.[0-9]+)?}}",
61+
cfg.available_features,
62+
),
63+
),
64+
Feature(
65+
name="_target-has-llvm-15",
66+
when=lambda cfg: BooleanExpression.evaluate(
67+
"_target-has-llvm-16 || target={{.+}}-apple-macosx{{13.[4-9](.[0-9]+)?}}",
68+
cfg.available_features,
69+
),
70+
),
71+
Feature(
72+
name="_target-has-llvm-14",
73+
when=lambda cfg: BooleanExpression.evaluate(
74+
"_target-has-llvm-15",
75+
cfg.available_features,
76+
),
77+
),
78+
Feature(
79+
name="_target-has-llvm-13",
80+
when=lambda cfg: BooleanExpression.evaluate(
81+
"_target-has-llvm-14 || target={{.+}}-apple-macosx{{13.[0-3](.[0-9]+)?}}",
82+
cfg.available_features,
83+
),
84+
),
85+
Feature(
86+
name="_target-has-llvm-12",
87+
when=lambda cfg: BooleanExpression.evaluate(
88+
"_target-has-llvm-13 || target={{.+}}-apple-macosx{{12.[3-9](.[0-9]+)?}}",
89+
cfg.available_features,
90+
),
91+
),
92+
]
93+
94+
# Define features for back-deployment testing.
95+
#
96+
# These features can be used to XFAIL tests that fail when deployed on (or compiled
97+
# for) an older system. For example, if a test exhibits a bug in the libc++ on a
98+
# particular system version, or if it uses a symbol that is not available on an
99+
# older version of the dylib, it can be marked as XFAIL with these features.
100+
#
101+
# We have two families of Lit features:
102+
#
103+
# The first one is `using-built-library-before-llvm-XYZ`. These features encode the
104+
# fact that the test suite is being *run* against a version of the shared/static library
105+
# that predates LLVM version XYZ. This is useful to represent the use case of compiling
106+
# a program against the latest libc++ but then deploying it and running it on an older
107+
# system with an older version of the (usually shared) library.
108+
#
109+
# This feature is built up using the target triple passed to the compiler and the
110+
# `stdlib=system` Lit feature, which encodes that we're running against the same library
111+
# as described by the target triple.
112+
#
113+
# The second set of features is `availability-<FEATURE>-missing`. This family of Lit
114+
# features encodes the presence of availability markup in the libc++ headers. This is
115+
# useful to check that a test fails specifically when compiled for a given deployment
116+
# target, such as when testing availability markup where we want to make sure that
117+
# using the annotated facility on a deployment target that doesn't support it will fail
118+
# at compile time. This can be achieved by creating a `.verify.cpp` test that checks for
119+
# the right errors and marking the test as `REQUIRES: availability-<FEATURE>-missing`.
120+
#
121+
# This feature is built up using the presence of availability markup detected inside
122+
# __config, the flavor of the library being tested and the target triple passed to the
123+
# compiler.
124+
#
125+
# Note that both families of Lit features are similar but different in important ways.
126+
# For example, tests for availability markup should be expected to produce diagnostics
127+
# regardless of whether we're running against a system library, as long as we're using
128+
# a libc++ flavor that enables availability markup. Similarly, a test could fail when
129+
# run against the system library of an older version of FreeBSD, even though FreeBSD
130+
# doesn't provide availability markup at the time of writing this.
131+
for version in ("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22"):
132+
features.append(
133+
Feature(
134+
name="using-built-library-before-llvm-{}".format(version),
135+
when=lambda cfg, v=version: BooleanExpression.evaluate(
136+
"stdlib=system && !_target-has-llvm-{}".format(v),
137+
cfg.available_features,
138+
),
139+
)
140+
)
141+
142+
features += [
143+
# Tests that require https://wg21.link/P0482 support in the built library
144+
Feature(
145+
name="availability-char8_t_support-missing",
146+
when=lambda cfg: BooleanExpression.evaluate(
147+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-12)",
148+
cfg.available_features,
149+
),
150+
),
151+
# Tests that require std::to_chars(floating-point) in the built library
152+
Feature(
153+
name="availability-fp_to_chars-missing",
154+
when=lambda cfg: BooleanExpression.evaluate(
155+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-14)",
156+
cfg.available_features,
157+
),
158+
),
159+
# Tests that require __libcpp_verbose_abort support in the built library
160+
Feature(
161+
name="availability-verbose_abort-missing",
162+
when=lambda cfg: BooleanExpression.evaluate(
163+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-15)",
164+
cfg.available_features,
165+
),
166+
),
167+
# Tests that require std::pmr support in the built library
168+
Feature(
169+
name="availability-pmr-missing",
170+
when=lambda cfg: BooleanExpression.evaluate(
171+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-16)",
172+
cfg.available_features,
173+
),
174+
),
175+
# Tests that require support for <print> and std::print in <ostream> in the built library.
176+
Feature(
177+
name="availability-print-missing",
178+
when=lambda cfg: BooleanExpression.evaluate(
179+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-18)",
180+
cfg.available_features,
181+
),
182+
),
183+
# Tests that require time zone database support in the built library
184+
Feature(
185+
name="availability-tzdb-missing",
186+
when=lambda cfg: BooleanExpression.evaluate(
187+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-19)",
188+
cfg.available_features,
189+
),
190+
),
191+
# Tests that require std::from_chars(floating-point) in the built library
192+
Feature(
193+
name="availability-fp_from_chars-missing",
194+
when=lambda cfg: BooleanExpression.evaluate(
195+
"!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-20)",
196+
cfg.available_features,
197+
),
198+
),
199+
]
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# ===----------------------------------------------------------------------===##
2+
#
3+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
# See https://llvm.org/LICENSE.txt for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
# ===----------------------------------------------------------------------===##
8+
9+
from libcxx.test.dsl import compilerMacros, Feature, AddCompileFlag, AddFeature
10+
11+
_isAnyClang = lambda cfg: "__clang__" in compilerMacros(cfg)
12+
_isAppleClang = lambda cfg: "__apple_build_version__" in compilerMacros(cfg)
13+
_isAnyGCC = lambda cfg: "__GNUC__" in compilerMacros(cfg)
14+
_isClang = lambda cfg: _isAnyClang(cfg) and not _isAppleClang(cfg)
15+
_isGCC = lambda cfg: _isAnyGCC(cfg) and not _isAnyClang(cfg)
16+
_isAnyClangOrGCC = lambda cfg: _isAnyClang(cfg) or _isAnyGCC(cfg)
17+
_isClExe = lambda cfg: not _isAnyClangOrGCC(cfg)
18+
_isMSVC = lambda cfg: "_MSC_VER" in compilerMacros(cfg)
19+
_msvcVersion = lambda cfg: (int(compilerMacros(cfg)["_MSC_VER"]) // 100, int(compilerMacros(cfg)["_MSC_VER"]) % 100)
20+
21+
features = [
22+
# gcc-style-warnings detects compilers that understand -Wno-meow flags, unlike MSVC's compiler driver cl.exe.
23+
Feature(name="gcc-style-warnings", when=_isAnyClangOrGCC),
24+
Feature(name="cl-style-warnings", when=_isClExe),
25+
26+
Feature(name="apple-clang", when=_isAppleClang),
27+
Feature(
28+
name=lambda cfg: "apple-clang-{__clang_major__}".format(**compilerMacros(cfg)),
29+
when=_isAppleClang,
30+
),
31+
Feature(
32+
name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}".format(**compilerMacros(cfg)),
33+
when=_isAppleClang,
34+
),
35+
Feature(
36+
name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(**compilerMacros(cfg)),
37+
when=_isAppleClang,
38+
),
39+
Feature(name="clang", when=_isClang),
40+
Feature(
41+
name=lambda cfg: "clang-{__clang_major__}".format(**compilerMacros(cfg)),
42+
when=_isClang,
43+
),
44+
Feature(
45+
name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}".format(**compilerMacros(cfg)),
46+
when=_isClang,
47+
),
48+
Feature(
49+
name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(**compilerMacros(cfg)),
50+
when=_isClang,
51+
),
52+
# Note: Due to a GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760), we must disable deprecation warnings
53+
# on GCC or spurious diagnostics are issued.
54+
#
55+
# TODO:
56+
# - Enable -Wplacement-new with GCC.
57+
# - Enable -Wclass-memaccess with GCC.
58+
Feature(
59+
name="gcc",
60+
when=_isGCC,
61+
actions=[
62+
AddCompileFlag("-D_LIBCPP_DISABLE_DEPRECATION_WARNINGS"),
63+
AddCompileFlag("-Wno-placement-new"),
64+
AddCompileFlag("-Wno-class-memaccess"),
65+
AddFeature("GCC-ALWAYS_INLINE-FIXME"),
66+
],
67+
),
68+
Feature(
69+
name=lambda cfg: "gcc-{__GNUC__}".format(**compilerMacros(cfg)), when=_isGCC
70+
),
71+
Feature(
72+
name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}".format(**compilerMacros(cfg)),
73+
when=_isGCC,
74+
),
75+
Feature(
76+
name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}".format(**compilerMacros(cfg)),
77+
when=_isGCC,
78+
),
79+
Feature(name="msvc", when=_isMSVC),
80+
Feature(name=lambda cfg: "msvc-{}".format(*_msvcVersion(cfg)), when=_isMSVC),
81+
Feature(name=lambda cfg: "msvc-{}.{}".format(*_msvcVersion(cfg)), when=_isMSVC),
82+
]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# ===----------------------------------------------------------------------===##
2+
#
3+
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
# See https://llvm.org/LICENSE.txt for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
# ===----------------------------------------------------------------------===##
8+
9+
from libcxx.test.dsl import Feature, AddSubstitution
10+
import shutil
11+
import subprocess
12+
13+
# Detect whether GDB is on the system, has Python scripting and supports
14+
# adding breakpoint commands. If so add a substitution to access it.
15+
def check_gdb(cfg):
16+
gdb_path = shutil.which("gdb")
17+
if gdb_path is None:
18+
return False
19+
20+
# Check that we can set breakpoint commands, which was added in 8.3.
21+
# Using the quit command here means that gdb itself exits, not just
22+
# the "python <...>" command.
23+
test_src = """\
24+
try:
25+
gdb.Breakpoint(\"main\").commands=\"foo\"
26+
except AttributeError:
27+
gdb.execute(\"quit 1\")
28+
gdb.execute(\"quit\")"""
29+
30+
try:
31+
stdout = subprocess.check_output(
32+
[gdb_path, "-ex", "python " + test_src, "--batch"],
33+
stderr=subprocess.DEVNULL,
34+
universal_newlines=True,
35+
)
36+
except subprocess.CalledProcessError:
37+
# We can't set breakpoint commands
38+
return False
39+
40+
# Check we actually ran the Python
41+
return not "Python scripting is not supported" in stdout
42+
43+
44+
features = [
45+
Feature(
46+
name="host-has-gdb-with-python",
47+
when=check_gdb,
48+
actions=[AddSubstitution("%{gdb}", lambda cfg: shutil.which("gdb"))],
49+
)
50+
]

0 commit comments

Comments
 (0)