[PATCH 9/9] perf test: Add build tests for clang and libbfd demangling

From: Ian Rogers

Date: Wed Sep 16 2026 - 02:19:19 EST


Three build configurations broke recently without the build test suite
noticing, as none of them were covered:

- "CC=clang" on its own. CXX is only set to clang++ by "make LLVM=1",
so CXX stays as g++ and used to be passed clang's flags.
- "CC=clang BUILD_NONDISTRO=1", where libbfd.c failed clang's
-Wthread-safety analysis.
- "BUILD_NONDISTRO=1 NO_DEMANGLE=1", the only combination that
compiles the libbfd demangling in symbol.c, which referred to
identifiers nothing declared.

Add the three. The clang ones need clang installed, and the libbfd ones
reuse the existing binutils check.

Testing that perf was built isn't enough for the first one. Feature
tests are allowed to fail, so a broken C++ compiler command line doesn't
fail the build, it silently turns off every feature needing a C++
compiler and the build still produces a working perf. Check that libLLVM
is still built in, which is the C++ dependent feature perf can report
on, so the test fails instead of quietly producing a perf with less in
it than the default build has.

Only make that check when libLLVM can be built in the first place. The
llvm-perf feature test compiles and links against the llvm-devel/llvm-dev
headers and libraries and needs version 13 or newer, so the presence of
llvm-config on its own says nothing. Probe the same way the feature test
does and fall back to only testing that perf was built when the probe
fails, rather than turning a machine without the LLVM development files
into a spurious failure.

For the same reason the clang tests must not reuse a feature dump made
with the default compiler, so exclude them from REUSE_FEATURES_DUMP.

Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
Assisted-by: Antigravity:gemini-3.1-pro
---
tools/perf/tests/make | 47 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 608470ff9c10..8e55ff1aecbd 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -71,6 +71,9 @@ make_clean_all := clean all
make_python_perf_so := $(python_perf_so)
make_debug := DEBUG=1
make_nondistro := BUILD_NONDISTRO=1
+make_nondistro_no_demangle := BUILD_NONDISTRO=1 NO_DEMANGLE=1
+make_clang := CC=clang
+make_clang_nondistro := CC=clang BUILD_NONDISTRO=1
make_extra_tests := EXTRA_TESTS=1
make_no_jevents := NO_JEVENTS=1
make_jevents_all := JEVENTS_ARCH=all
@@ -128,6 +131,18 @@ make_minimal += NO_CAPSTONE=1
# binutils 2_42 and newer have bfd_thread_init()
new_libbfd := $(shell echo '#include <bfd.h>' | $(CC) -E -x c - | grep bfd_thread_init)

+# Whether libLLVM can be built, which needs the llvm-devel/llvm-dev headers and
+# libraries of version 13 or newer, not just llvm-config. This mirrors the
+# llvm-perf feature test in tools/build/feature/test-llvm-perf.cpp so that
+# libLLVM is only asserted below when the default compiler can really build it.
+ifneq ($(call has,$(LLVM_CONFIG)),)
+have_libllvm := $(shell printf '#include <llvm/Support/ManagedStatic.h>\n#include <llvm/Support/raw_ostream.h>\n#if LLVM_VERSION_MAJOR < 13\n#error "llvm-devel/llvm-dev version 13 or greater is required"\n#endif\nint main(){llvm::errs()<<"";llvm::llvm_shutdown();return 0;}\n' | \
+ $(CXX) -x c++ -std=gnu++17 -I$(shell $(LLVM_CONFIG) --includedir 2>/dev/null) - -o /dev/null \
+ -L$(shell $(LLVM_CONFIG) --libdir 2>/dev/null) \
+ $(shell $(LLVM_CONFIG) --libs Core BPF 2>/dev/null) \
+ $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null) >/dev/null 2>&1 && echo y)
+endif
+
# $(run) contains all available tests
run := make_pure
# Targets 'clean all' can be run together only through top level
@@ -143,6 +158,17 @@ run += make_python_perf_so
run += make_debug
ifneq ($(new_libbfd),)
run += make_nondistro
+# Demangling with libbfd is only built when the C++ ABI's __cxa_demangle
+# isn't available, so it needs a build of its own to be compiled at all.
+run += make_nondistro_no_demangle
+endif
+# CXX is only set to clang++ by LLVM=1, so a CC=clang build has to cope with
+# a C compiler and a C++ compiler that don't match.
+ifneq ($(call has,clang),)
+run += make_clang
+ifneq ($(new_libbfd),)
+run += make_clang_nondistro
+endif
endif
run += make_extra_tests
run += make_no_jevents
@@ -278,6 +304,17 @@ test_make_install_pdf_O := $(test_ok)
test_make_libbpf_dynamic := ldd $(PERF_O)/perf | grep -q libbpf
test_make_libbpf_dynamic_O := ldd $$TMP_O/perf | grep -q libbpf

+# Feature tests are allowed to fail, so a broken C++ compiler command line
+# doesn't fail the build, it just quietly turns off everything that needs a
+# C++ compiler. Check a feature that does, otherwise these tests would pass
+# while producing a perf with less in it than the default build has.
+ifneq ($(have_libllvm),)
+test_make_clang := test -x $(PERF_O)/perf && $(PERF_O)/perf check -q feature libLLVM
+test_make_clang_O := test -x $$TMP_O/perf && $$TMP_O/perf check -q feature libLLVM
+test_make_clang_nondistro := $(test_make_clang)
+test_make_clang_nondistro_O := $(test_make_clang_O)
+endif
+
test_make_python_perf_so_O := test -f $$TMP_O/python/perf.so
test_make_perf_o_O := test -f $$TMP_O/perf.o
test_make_util_map_o_O := test -f $$TMP_O/util/map.o
@@ -407,8 +444,14 @@ $(FEATURES_DUMP_FILE_STATIC):
echo "- $@: $$cmd" && echo $$cmd && \
( eval $$cmd ) > /dev/null 2>&1

+# The clang tests exist to run feature detection with a compiler other than
+# the default one, so they have to do their own and are left out of both the
+# dependency and the 'FEATURES_DUMP=' append below.
+no_features_dump := make_clang make_clang_nondistro
+no_features_dump += $(addsuffix _O,$(no_features_dump))
+
# Add feature dump dependency for run/run_O targets
-$(foreach t,$(run) $(run_O),$(eval \
+$(foreach t,$(filter-out $(no_features_dump),$(run) $(run_O)),$(eval \
$(t): $(if $(findstring make_static,$(t)),\
$(FEATURES_DUMP_FILE_STATIC),\
$(FEATURES_DUMP_FILE))))
@@ -416,7 +459,7 @@ $(foreach t,$(run) $(run_O),$(eval \
# Append 'FEATURES_DUMP=' option to all test cases. For example:
# make_no_libbpf: NO_LIBBPF=1 --> NO_LIBBPF=1 FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP
# make_static: LDFLAGS=-static --> LDFLAGS=-static FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP_STATIC
-$(foreach t,$(run),$(if $(findstring make_static,$(t)),\
+$(foreach t,$(filter-out $(no_features_dump),$(run)),$(if $(findstring make_static,$(t)),\
$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE_STATIC)),\
$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE))))
endif
--
2.55.0.1032.g73a4cd73de-goog