* [RFC PATCH v3 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs
@ 2026-11-05 18:09 Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Ian Rogers @ 2026-11-05 18:09 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter,
Quentin Monnet, Miguel Ojeda, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Nick Desaulniers, Bill Wendling, Justin Stitt, linux-perf-users,
bpf, rust-for-linux, linux-kbuild, llvm, linux-kernel
The zlib-rs project (https://github.com/trifectatechfoundation/zlib-rs)
provides a memory-safe, high-performance Rust implementation of the zlib
compression specification along with a C ABI layer (libz-rs-sys) that is a
drop-in replacement for the standard C zlib library. Transitioning
decompression of kernel configuration files (/proc/config.gz), compressed
ELF/BTF sections, and perf data from C zlib to zlib-rs improves both memory
safety and decompression performance.
On many Linux distributions (such as Debian, Ubuntu, and Fedora), Rust
crates like zlib-rs and libz-rs-sys are packaged as Cargo registry sources
under /usr/share/cargo/registry/ (e.g. librust-libz-rs-sys-dev or
rust-libz-rs-sys-devel) rather than as prebuilt C shared libraries, while
other environments may install prebuilt libz_rs libraries via pkg-config or
a custom prefix (LIBZ_RS_DIR).
This RFC series lays the groundwork for building and linking Rust crate
libraries in tools/ offline from the system Cargo registry and integrates
zlib-rs support into perf and bpftool, preferring zlib-rs over C zlib when
available:
1. **tools build: Add Rust library build infrastructure and zlib-rs feature test**:
- Adds `tools/build/Makefile.rust` with helpers to resolve C compiler and
linker flags for Rust libraries via `%-cflags` and `%-libs` targets.
- Resolves `zlib-rs` compiler and linker flags via `LIBZ_RS_DIR`,
`pkg-config` (`libz-rs-sys-cdylib`, `zlib-rs`, `z_rs`), or building
`libz_rs.a` (with the `export-symbols`, `c-allocator`, `std`, and `gz`
features) into `$(OUTPUT)libz_rs/` from `/usr/share/cargo/registry`
using offline Cargo (`cargo metadata --offline` and
`cargo build --offline`).
- Passes `-Wl,--exclude-libs,libz_rs.a` when linking `libz_rs.a` so
symbols pulled into the executable are marked `HIDDEN` and not exported
into `.dynsym`, preventing shared libraries linked against system
`libz.so.1` (`libelf.so`, `libdw.so`, `libcurl.so`, etc.) from
partially binding some `zlib` calls to the executable's `libz_rs.a` and
others to `libz.so.1`.
- Adds `tools/build/feature/test-zlib-rs.c` checking
`ZLIB_VER_SUBREVISION == 15` (`0xf`, which distinguishes
`libz-rs-sys`'s `zlib.h` from standard C `zlib.h`) and linking against
`inflateInit()`.
- Extends `tools/scripts/Makefile.include` with cross-compilation target
triples (`RUST_TARGET_FLAGS_<arch>`) and the `feature_rust_lib` macro.
2. **perf build: Prefer zlib-rs over zlib when available**:
- Moves Rust detection ahead of zlib detection in
`tools/perf/Makefile.config` and prefers `zlib-rs` over C `zlib` unless
`NO_ZLIB_RS=1` (or `NO_ZLIB=1` / `NO_RUST=1`) is set.
- Replaces `-lz` with `$(or $(ZLIB_LIBS),-lz)` in `DWARFLIBS`,
`libbfd-liberty-z`, and `llvm-config --system-libs` so static
`libdw`/`libelf`, `libbfd`, and `libLLVM` builds use the selected
`zlib` implementation while falling back to `-lz` if `NO_ZLIB=1`
disables `perf`'s direct zlib support.
- Defines both `HAVE_ZLIB_SUPPORT` and `HAVE_ZLIB_RS_SUPPORT` when
`zlib-rs` is used so existing zlib call sites in `perf` work unchanged
while `perf version --build-options` and `perf check feature zlib-rs`
report whether `zlib-rs` is active.
- Shares `$(OUTPUT)libz_rs/` with the host bootstrap `bpftool` build in
`tools/perf/bpf_skel.mak` and adds `NO_ZLIB` / `NO_ZLIB_RS` tests to
`tools/perf/tests/make`.
3. **bpftool: Prefer zlib-rs over zlib when available**:
- Adds `zlib-rs` and `zlib` to `FEATURE_TESTS` and `FEATURE_DISPLAY` in
`tools/bpf/bpftool/Makefile`, configures `ZLIB_CFLAGS` and
`ZLIB_LIBS` via `feature_rust_lib` when `zlib-rs` is detected, and
replaces `-lz` with `$(ZLIB_LIBS)` in static `llvm-config --system-libs`.
Changes in v3:
- Pass `-Wl,--exclude-libs,libz_rs.a` in `FEATURE_LIBS-zlib-rs` so symbols
pulled into the executable from `libz_rs.a` are given `HIDDEN` visibility
and excluded from `.dynsym`, preventing shared libraries linked against
system `libz.so.1` from partially binding some `zlib` symbols to the
executable's `libz_rs.a` and others to `libz.so.1` (Quentin Monnet).
- Replace `-lz` with `$(or $(ZLIB_LIBS),-lz)` / `$(ZLIB_LIBS)` in
`DWARFLIBS`, `libbfd-liberty-z`, and `$(LLVM_CONFIG) --system-libs` in
`tools/perf/Makefile.config` and `tools/bpf/bpftool/Makefile` so static
`libLLVM` and `libdw`/`libelf`/`libbfd` builds do not link `-lz` alongside
`zlib-rs` while preserving `-lz` for dependent libraries under `NO_ZLIB=1`
(Quentin Monnet, Sashiko).
- Expand comments in `tools/build/Makefile.rust` explaining why
`CARGO_REGISTRY_DIR` (`source.crates-io.replace-with`) and removing stale
`Cargo.lock` before `cargo metadata --offline` are required.
- Rebase onto `perf-tools-next` (`v7.4-rc1`).
Changes in v2:
- Use offline Cargo (`cargo metadata --offline` and `cargo build --offline`
configured against `CARGO_REGISTRY_DIR` = `/usr/share/cargo/registry` and
isolated from `~/.cargo`) to resolve crate versions, dependency graphs,
features, and build scripts instead of manually globbing crate directory
names and invoking `rustc` on hardcoded `.rlib` edges (Miguel Ojeda).
- Avoid including `../../scripts/Makefile.arch` in `tools/bpf/bpftool/Makefile`
(to keep the standalone bpftool mirror self-contained) by placing
`RUST_TARGET_FLAGS_<arch>` in `tools/scripts/Makefile.include`, and expand
the bpftool commit message on the security and performance motivation for
preferring `zlib-rs` (Quentin Monnet).
- Drop unused `.rlib` pattern rules and helpers from `tools/build/Build.include`
and `tools/build/Makefile.build` (Sashiko).
- Address Sashiko review feedback on `PKG_CONFIG` handling when unset or with
`-static`, `test-all.bin` re-checking `zlib-rs` and `rust`, preserving
`EXTRA_CFLAGS` optimization defaults when building `libbpf.a`, and
honoring `NO_ZLIB_RS=1` in `bpftool` when `FEATURES_DUMP` is used.
AI Assistance Disclosure (per Documentation/process/coding-assistants.rst
and Documentation/process/generated-content.rst):
- Tools used: Antigravity coding assistant and Sashiko automated patch
review using Gemini 4 LLMs.
- Summary of prompts and assistance: Interactive pair-programming session to
identify distro packaging for zlib-rs/libz-rs-sys, implement the zlib-rs
feature test and offline Cargo build rules in Makefile.rust, integrate
zlib-rs detection into perf and bpftool, isolate `libz_rs.a` symbols with
`-Wl,--exclude-libs,libz_rs.a` and ensure static library flag consistency,
and address reviewer and automated Sashiko feedback.
- Testing performed: Built and tested perf and bpftool with zlib-rs
(default), NO_ZLIB_RS=1 (fallback to C zlib), NO_ZLIB=1, and MINIMAL=1;
verified with `readelf --dyn-syms` and `LD_BIND_NOW=1 LD_DEBUG=bindings`
that `libz_rs.a` symbols are not exported in `.dynsym`; verified
`perf version --build-options`, `perf check feature`, and the
`make_no_zlib` / `make_no_zlib_rs` tests in `tools/perf/tests/make`; and
checked all commits with `scripts/checkpatch.pl`.
Ian Rogers (3):
tools build: Add Rust library build infrastructure and zlib-rs feature
test
perf build: Prefer zlib-rs over zlib when available
bpftool: Prefer zlib-rs over zlib when available
tools/bpf/bpftool/.gitignore | 1 +
tools/bpf/bpftool/Makefile | 59 +++++++-
tools/build/Makefile.feature | 12 +-
tools/build/Makefile.rust | 166 +++++++++++++++++++++++
tools/build/feature/.gitignore | 1 +
tools/build/feature/Makefile | 11 +-
tools/build/feature/test-zlib-rs.c | 19 +++
tools/perf/.gitignore | 1 +
tools/perf/Documentation/perf-check.txt | 1 +
tools/perf/Makefile.config | 92 +++++++------
tools/perf/Makefile.perf | 32 ++++-
tools/perf/bpf_skel.mak | 8 +-
tools/perf/builtin-check.c | 1 +
tools/perf/scripts/install-build-deps.sh | 6 +
tools/perf/tests/make | 9 ++
tools/scripts/Makefile.include | 25 ++++
16 files changed, 391 insertions(+), 53 deletions(-)
create mode 100644 tools/build/Makefile.rust
create mode 100644 tools/build/feature/test-zlib-rs.c
--
2.56.0.455.g6c5a503b38-goog
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test
2026-11-05 18:09 [RFC PATCH v3 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
@ 2026-11-05 18:09 ` Ian Rogers
2026-11-05 18:30 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
2026-11-05 18:09 ` [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 3/3] bpftool: " Ian Rogers
2 siblings, 2 replies; 10+ messages in thread
From: Ian Rogers @ 2026-11-05 18:09 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter,
Quentin Monnet, Miguel Ojeda, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Nick Desaulniers, Bill Wendling, Justin Stitt, linux-perf-users,
bpf, rust-for-linux, linux-kbuild, llvm, linux-kernel
Add shared Rust library build and feature detection support across tools/
and implement the zlib-rs feature check:
- Add tools/build/Makefile.rust with rules to resolve Rust library C
compiler and linker flags via %-cflags and %-libs targets.
- Support resolving zlib-rs via LIBZ_RS_DIR, pkg-config
(libz-rs-sys-cdylib, zlib-rs, z_rs), or building libz_rs.a into
$(OUTPUT)libz_rs/ from the system Cargo registry
(/usr/share/cargo/registry) using offline Cargo (cargo metadata and
cargo build --offline).
- Pass -Wl,--exclude-libs,libz_rs.a when linking libz_rs.a so symbols
pulled into the executable are marked HIDDEN and not exported into
.dynsym, preventing shared libraries linked against system libz.so.1
(such as libelf.so, libdw.so, and libcurl.so) from partially binding
some zlib calls to the executable's libz_rs.a and others to libz.so.1.
- Add tools/build/feature/test-zlib-rs.c verifying ZLIB_VER_SUBREVISION
== 15 (0xf) and linking against inflateInit().
- Add RUST_TARGET_FLAGS_<arch> cross-compilation triples and the
feature_rust_lib helper macro to tools/scripts/Makefile.include.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/build/Makefile.feature | 12 ++-
tools/build/Makefile.rust | 166 +++++++++++++++++++++++++++++
tools/build/feature/.gitignore | 1 +
tools/build/feature/Makefile | 11 +-
tools/build/feature/test-zlib-rs.c | 19 ++++
tools/scripts/Makefile.include | 25 +++++
6 files changed, 231 insertions(+), 3 deletions(-)
create mode 100644 tools/build/Makefile.rust
create mode 100644 tools/build/feature/test-zlib-rs.c
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 4d37d11f674c..ecf27626d493 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -5,10 +5,11 @@ ifneq ($(OUTPUT),)
OUTPUT_FEATURES = $(OUTPUT)feature/
$(shell mkdir -p $(OUTPUT_FEATURES))
endif
+RUST_OUTPUT ?= $(abspath $(or $(OUTPUT),$(CURDIR)))/
feature_check = $(eval $(feature_check_code))
define feature_check_code
- feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
+ feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) RUST_OUTPUT="$(RUST_OUTPUT)" CC="$(CC)" CXX="$(CXX)" CARGO="$(CARGO)" RUSTC="$(RUSTC)" $(if $(PKG_CONFIG),PKG_CONFIG="$(PKG_CONFIG)") CFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" RUST_FLAGS="$(RUST_FLAGS)" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
endef
feature_set = $(eval $(feature_set_code))
@@ -128,6 +129,8 @@ FEATURE_TESTS_EXTRA := \
libdebuginfod \
clang-bpf-co-re \
bpftool-skeletons \
+ zlib-rs \
+ rust \
libunwind \
libunwind-debug-frame \
$(foreach arch,$(LIBUNWIND_ARCHS),libunwind-$(arch) libunwind-debug-frame-$(arch))
@@ -149,6 +152,7 @@ FEATURE_DISPLAY ?= \
libcapstone \
llvm-perf \
zlib \
+ zlib-rs \
lzma \
bpf \
libaio \
@@ -216,6 +220,12 @@ ifeq ($(feature-all), 1)
$(call feature_check,compile-x32)
$(call feature_check,bionic)
$(call feature_check,babeltrace2-ctf-writer)
+ ifneq ($(filter zlib-rs,$(FEATURE_TESTS)),)
+ $(call feature_check,zlib-rs)
+ endif
+ ifneq ($(filter rust,$(FEATURE_TESTS)),)
+ $(call feature_check,rust)
+ endif
$(call feature_check,libunwind)
$(call feature_check,libunwind-debug-frame)
$(foreach arch,$(LIBUNWIND_ARCHS),$(call feature_check,libunwind-$(arch)))
diff --git a/tools/build/Makefile.rust b/tools/build/Makefile.rust
new file mode 100644
index 000000000000..952aac9fc4bf
--- /dev/null
+++ b/tools/build/Makefile.rust
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Shared rules and helpers for discovering and building Rust libraries
+# (either from pre-installed packages/pkg-config or from distro Cargo
+# registry sources via offline Cargo) for tools/ builds and feature detection.
+
+ifeq ($(pound),)
+include $(dir $(lastword $(MAKEFILE_LIST)))../scripts/Makefile.include
+endif
+
+ifneq ($(CROSS_COMPILE),)
+ ifeq ($(filter --target=%,$(RUST_FLAGS)),)
+ ifneq ($(RUST_TARGET_FLAGS_$(ARCH)),)
+ override RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH))
+ endif
+ endif
+endif
+
+ifeq ($(PKG_CONFIG),)
+ ifneq (, $(shell which $(CROSS_COMPILE)pkg-config 2>/dev/null))
+ PKG_CONFIG := $(CROSS_COMPILE)pkg-config
+ else
+ PKG_CONFIG := pkg-config
+
+ ifdef CROSS_COMPILE
+ ifeq ($(PKG_CONFIG_LIBDIR)$(PKG_CONFIG_PATH)$(PKG_CONFIG_SYSROOT_DIR),)
+ CROSS_ARCH = $(notdir $(CROSS_COMPILE:%-=%))
+ PKG_CONFIG_LIBDIR := /usr/local/$(CROSS_ARCH)/lib/pkgconfig/
+ PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/lib/$(CROSS_ARCH)/pkgconfig/
+ PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/lib/$(CROSS_ARCH)/pkgconfig/
+ PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/local/share/pkgconfig/
+ PKG_CONFIG_LIBDIR := $(PKG_CONFIG_LIBDIR):/usr/share/pkgconfig/
+ export PKG_CONFIG_LIBDIR
+ endif
+ endif
+ endif
+endif
+
+ifeq ($(findstring -static,${LDFLAGS}),-static)
+ ifeq ($(findstring --static,$(PKG_CONFIG)),)
+ override PKG_CONFIG += --static
+ endif
+endif
+
+# Helper targets invoked by $(call feature_rust_lib,<name>) to query the
+# resolved compiler and linker flags for a Rust library feature.
+%-cflags:
+ @echo $(FEATURE_CFLAGS-$*)
+
+%-libs:
+ @echo $(FEATURE_LIBS-$*)
+
+# Place compiled Rust library artifacts in their own subdirectory under the
+# build output root (e.g. $(OUTPUT)libz_rs/, alongside libapi/, libbpf/, etc.)
+# rather than inside $(OUTPUT)feature/.
+RUST_OUTPUT ?= $(OUTPUT)
+LIBZ_RS_OUTPUT ?= $(RUST_OUTPUT)libz_rs/
+
+$(LIBZ_RS_OUTPUT):
+ $(Q)mkdir -p $@
+
+# Use the system Cargo registry (e.g. /usr/share/cargo/registry from
+# Debian/Ubuntu librust-*-dev or Fedora rust-*-devel packages) offline via
+# Cargo so Cargo resolves compatible crate versions, dependency graphs,
+# features, and build scripts without touching ~/.cargo or the network.
+#
+# Upstream /usr/bin/cargo only searches crates.io by default; distros do not
+# point /usr/bin/cargo at /usr/share/cargo/registry globally because Cargo's
+# directory source mechanism replaces crates.io entirely, which would break
+# normal user builds. Instead, distro package builders (such as Debian's
+# /usr/share/cargo/bin/cargo wrapper and Fedora's %cargo_prep macro) configure
+# source.crates-io.replace-with to point at /usr/share/cargo/registry. We pass
+# the same source replacement via --config and set CARGO_HOME to a temporary
+# directory so ~/.cargo is neither read nor modified.
+CARGO_REGISTRY_DIR ?= /usr/share/cargo/registry
+CARGO_OFFLINE_FLAGS = --offline \
+ --config 'source.crates-io.replace-with="system-registry"' \
+ --config 'source.system-registry.directory="$(CARGO_REGISTRY_DIR)"'
+
+# cargo build takes --target=<triple> as a CLI flag (which also places the
+# output in target/<triple>/release/) and compiler flags via RUSTFLAGS.
+# Build with -C relocation-model=pic so libz_rs.a can be linked into PIE
+# binaries.
+CARGO_TARGET := $(patsubst --target=%,%,$(firstword $(filter --target=%,$(RUST_FLAGS))))
+CARGO_RUSTFLAGS := $(filter-out --target=%,$(RUST_FLAGS)) -C relocation-model=pic
+
+# Build libz_rs.a and stage its headers into $(LIBZ_RS_OUTPUT)include/:
+# - Cargo writes Cargo.lock next to Cargo.toml, so the synthetic manifest and
+# lib.rs are generated inside the writable $(LIBZ_RS_OUTPUT) directory rather
+# than in $(srctree), and removed once the build finishes (any stale
+# Cargo.lock from an interrupted build is also removed upfront so a distro
+# package upgrade in $(CARGO_REGISTRY_DIR) is not blocked by an old lockfile).
+# - Enable export-symbols (unprefixed zlib C ABI symbols), c-allocator, std,
+# and gz (gzopen/gzopen64/gzread/etc.) on libz-rs-sys.
+# - Query cargo metadata for the resolved libz-rs-sys crate path so we copy
+# the matching zlib.h and zconf.h headers that Cargo selected.
+$(LIBZ_RS_OUTPUT)libz_rs.a: $(wildcard $(CARGO_REGISTRY_DIR)) | $(LIBZ_RS_OUTPUT)
+ $(Q){ \
+ rm -f $(LIBZ_RS_OUTPUT)Cargo.lock && \
+ printf '[package]\nname = "z_rs"\nversion = "0.1.0"\nedition = "2021"\n\n[lib]\nname = "z_rs"\npath = "lib.rs"\ncrate-type = ["staticlib"]\n\n[dependencies]\nlibz-rs-sys = { version = "*", default-features = false, features = ["export-symbols", "c-allocator", "std", "gz"] }\n' > $(LIBZ_RS_OUTPUT)Cargo.toml && \
+ printf 'pub use libz_rs_sys::*;\n' > $(LIBZ_RS_OUTPUT)lib.rs && \
+ inc_dir=$$(CARGO_HOME="$(LIBZ_RS_OUTPUT)cargo_home" $(CARGO) metadata $(CARGO_OFFLINE_FLAGS) --format-version 1 --manifest-path $(LIBZ_RS_OUTPUT)Cargo.toml | sed -n 's/.*"name":"libz_rs_sys","src_path":"\([^"]*\)\/src\/lib\.rs".*/\1/p') && \
+ test -n "$$inc_dir" && test -d "$$inc_dir/include" && \
+ mkdir -p $(LIBZ_RS_OUTPUT)include && \
+ cp -f "$$inc_dir"/include/*.h $(LIBZ_RS_OUTPUT)include/ && \
+ CARGO_HOME="$(LIBZ_RS_OUTPUT)cargo_home" RUSTC="$(RUSTC)" RUSTFLAGS="$(CARGO_RUSTFLAGS)" \
+ $(CARGO) build $(CARGO_OFFLINE_FLAGS) --release \
+ --manifest-path $(LIBZ_RS_OUTPUT)Cargo.toml \
+ --target-dir $(LIBZ_RS_OUTPUT)target \
+ $(if $(CARGO_TARGET),--target=$(CARGO_TARGET)) && \
+ mv -f $(LIBZ_RS_OUTPUT)target/$(if $(CARGO_TARGET),$(CARGO_TARGET)/)release/libz_rs.a $@ && \
+ rm -rf $(LIBZ_RS_OUTPUT)Cargo.toml $(LIBZ_RS_OUTPUT)Cargo.lock \
+ $(LIBZ_RS_OUTPUT)lib.rs $(LIBZ_RS_OUTPUT)target \
+ $(LIBZ_RS_OUTPUT)cargo_home; \
+ } > $(@:.a=.make.output) 2>&1 || { \
+ rm -rf $(LIBZ_RS_OUTPUT)Cargo.toml $(LIBZ_RS_OUTPUT)Cargo.lock \
+ $(LIBZ_RS_OUTPUT)lib.rs $(LIBZ_RS_OUTPUT)include \
+ $(LIBZ_RS_OUTPUT)target $(LIBZ_RS_OUTPUT)cargo_home $@; \
+ false; \
+ }
+
+# Only evaluate zlib-rs pkg-config / Cargo flags when building a zlib-rs target
+# (or 'all'), avoiding unnecessary shell calls during 'clean' or unrelated
+# feature tests in tools/build/feature/Makefile.
+# Note: GNU Make's $(filter ...) only supports a single '%' wildcard per
+# pattern, so $(findstring zlib-rs,...) is used to match targets like
+# $(OUTPUT)test-zlib-rs.bin, zlib-rs-cflags, and zlib-rs-libs.
+ifneq ($(if $(MAKECMDGOALS),$(or $(findstring zlib-rs,$(MAKECMDGOALS)),$(filter all %libz_rs.a,$(MAKECMDGOALS))),all),)
+ # Resolve zlib-rs flags and libraries in priority order:
+ # 1. Explicit LIBZ_RS_DIR=/path/to/prefix override
+ # 2. pkg-config (libz-rs-sys-cdylib when not linking -static since it only
+ # provides a shared library, zlib-rs, or z_rs)
+ # 3. System Cargo registry built via Cargo into $(LIBZ_RS_OUTPUT)libz_rs.a
+ # (linked with -lpthread -ldl -lm required by the embedded Rust libstd)
+ ifdef LIBZ_RS_DIR
+ FEATURE_CFLAGS-zlib-rs := -I$(LIBZ_RS_DIR)/include
+ FEATURE_LIBS-zlib-rs := -L$(LIBZ_RS_DIR)/lib -lz_rs
+ endif
+
+ ifeq ($(FEATURE_LIBS-zlib-rs),)
+ ZLIB_RS_PC := $(shell ($(if $(findstring -static,${LDFLAGS}),false,$(PKG_CONFIG) --exists libz-rs-sys-cdylib 2>/dev/null && echo libz-rs-sys-cdylib)) || \
+ ($(PKG_CONFIG) --exists zlib-rs 2>/dev/null && echo zlib-rs) || \
+ ($(PKG_CONFIG) --exists z_rs 2>/dev/null && echo z_rs))
+ ifneq ($(ZLIB_RS_PC),)
+ FEATURE_CFLAGS-zlib-rs := $(shell $(PKG_CONFIG) --cflags $(ZLIB_RS_PC) 2>/dev/null)
+ FEATURE_LIBS-zlib-rs := $(shell $(PKG_CONFIG) --libs $(ZLIB_RS_PC) 2>/dev/null)
+ endif
+ endif
+
+ ifeq ($(FEATURE_LIBS-zlib-rs),)
+ ifneq ($(wildcard $(CARGO_REGISTRY_DIR)),)
+ FEATURE_CFLAGS-zlib-rs := -I$(LIBZ_RS_OUTPUT)include
+ FEATURE_STATIC-zlib-rs := $(LIBZ_RS_OUTPUT)libz_rs.a
+ # Pass -Wl,--exclude-libs,libz_rs.a so symbols pulled into the executable
+ # from libz_rs.a are marked HIDDEN and not exported into .dynsym. That
+ # prevents shared libraries linked against system libz.so.1 (e.g.
+ # libelf.so, libdw.so, libcurl.so) from partially binding some zlib
+ # calls to the executable's libz_rs.a and others to libz.so.1.
+ FEATURE_LIBS-zlib-rs := $(FEATURE_STATIC-zlib-rs) \
+ -Wl,--exclude-libs,libz_rs.a -lpthread -ldl -lm
+ endif
+ endif
+endif
+
+zlib-rs-cflags: $(FEATURE_STATIC-zlib-rs)
+zlib-rs-libs: $(FEATURE_STATIC-zlib-rs)
diff --git a/tools/build/feature/.gitignore b/tools/build/feature/.gitignore
index 15fcd34acdb9..2fb933f84bd0 100644
--- a/tools/build/feature/.gitignore
+++ b/tools/build/feature/.gitignore
@@ -2,3 +2,4 @@
*.d
*.bin
*.output
+libz_rs/
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 10340a537224..0c728531fcdc 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -50,6 +50,7 @@ FILES= \
test-compile-32.bin \
test-compile-x32.bin \
test-zlib.bin \
+ test-zlib-rs.bin \
test-lzma.bin \
test-bpf.bin \
test-libbpf.bin \
@@ -100,7 +101,7 @@ else
endif
ifeq ($(findstring -static,${LDFLAGS}),-static)
- PKG_CONFIG += --static
+ override PKG_CONFIG += --static
endif
all: $(FILES)
@@ -301,6 +302,11 @@ $(OUTPUT)test-compile-x32.bin:
$(OUTPUT)test-zlib.bin:
$(BUILD) -lz
+include ../Makefile.rust
+
+$(OUTPUT)test-zlib-rs.bin: $(FEATURE_STATIC-zlib-rs)
+ $(BUILD) $(FEATURE_CFLAGS-zlib-rs) $(FEATURE_LIBS-zlib-rs)
+
$(OUTPUT)test-lzma.bin:
$(BUILD) -llzma
@@ -374,4 +380,5 @@ $(OUTPUT)test-rust.bin:
###############################
clean:
- rm -f $(FILES) $(OUTPUT)*.d $(FILES:.bin=.make.output)
+ rm -f $(FILES) $(OUTPUT)*.d $(OUTPUT)*.make.output
+ rm -rf $(LIBZ_RS_OUTPUT)
diff --git a/tools/build/feature/test-zlib-rs.c b/tools/build/feature/test-zlib-rs.c
new file mode 100644
index 000000000000..b8729c5135bb
--- /dev/null
+++ b/tools/build/feature/test-zlib-rs.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <zlib.h>
+
+/*
+ * libz-rs-sys's bundled zlib.h defines ZLIB_VER_SUBREVISION to 15 (0xf) to
+ * distinguish itself from standard C zlib (which defines it to 0). Verify
+ * we are including the zlib-rs header and can link against its zlib C ABI.
+ */
+#if !defined(ZLIB_VER_SUBREVISION) || ZLIB_VER_SUBREVISION != 15
+#error "Not zlib-rs header"
+#endif
+
+int main(void)
+{
+ z_stream zs;
+
+ inflateInit(&zs);
+ return 0;
+}
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 378387f62960..7089e9ce64c7 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -109,8 +109,33 @@ CC_NO_CLANG := $(shell if command -v $(firstword $(CC)) >/dev/null 2>&1; then $(
# Some tools require bpftool
SYSTEM_BPFTOOL ?= bpftool
+CARGO ?= cargo
RUSTC ?= rustc
+# Map kernel ARCH to rustc --target triples when cross-compiling tools/.
+ifneq ($(CROSS_COMPILE),)
+ RUST_TARGET_FLAGS_arm := arm-unknown-linux-gnueabi
+ RUST_TARGET_FLAGS_arm64 := aarch64-unknown-linux-gnu
+ RUST_TARGET_FLAGS_loongarch := loongarch64-unknown-linux-gnu
+ RUST_TARGET_FLAGS_m68k := m68k-unknown-linux-gnu
+ RUST_TARGET_FLAGS_mips := mipsel-unknown-linux-gnu
+ RUST_TARGET_FLAGS_powerpc := powerpc64le-unknown-linux-gnu
+ RUST_TARGET_FLAGS_riscv := riscv64gc-unknown-linux-gnu
+ RUST_TARGET_FLAGS_s390 := s390x-unknown-linux-gnu
+ RUST_TARGET_FLAGS_x86 := x86_64-unknown-linux-gnu
+ RUST_TARGET_FLAGS_x86_64 := x86_64-unknown-linux-gnu
+endif
+
+# Query tools/build/Makefile.rust for a Rust library feature's CFLAGS and LIBS
+# (building any required staticlib such as libz_rs.a under $(RUST_OUTPUT)), and
+# populate FEATURE_CFLAGS-<feat> and FEATURE_LIBS-<feat>.
+define feature_rust_lib_code
+ RUST_OUTPUT ?= $$(abspath $$(or $$(OUTPUT),$$(CURDIR)))/
+ FEATURE_CFLAGS-$(1) := $$(shell $$(MAKE) -s --no-print-directory -f $$(srctree)/tools/build/Makefile.rust RUST_OUTPUT="$$(RUST_OUTPUT)" $$(if $$(PKG_CONFIG),PKG_CONFIG="$$(PKG_CONFIG)") CARGO="$$(CARGO)" RUSTC="$$(RUSTC)" RUST_FLAGS="$$(RUST_FLAGS)" LDFLAGS="$$(LDFLAGS)" $(1)-cflags)
+ FEATURE_LIBS-$(1) := $$(shell $$(MAKE) -s --no-print-directory -f $$(srctree)/tools/build/Makefile.rust RUST_OUTPUT="$$(RUST_OUTPUT)" $$(if $$(PKG_CONFIG),PKG_CONFIG="$$(PKG_CONFIG)") CARGO="$$(CARGO)" RUSTC="$$(RUSTC)" RUST_FLAGS="$$(RUST_FLAGS)" LDFLAGS="$$(LDFLAGS)" $(1)-libs)
+endef
+feature_rust_lib = $(eval $(feature_rust_lib_code))
+
ifeq ($(CC_NO_CLANG), 1)
EXTRA_WARNINGS += -Wstrict-aliasing=3
--
2.56.0.455.g6c5a503b38-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available
2026-11-05 18:09 [RFC PATCH v3 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
@ 2026-11-05 18:09 ` Ian Rogers
2026-11-05 18:26 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
2026-11-05 18:09 ` [RFC PATCH v3 3/3] bpftool: " Ian Rogers
2 siblings, 2 replies; 10+ messages in thread
From: Ian Rogers @ 2026-11-05 18:09 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter,
Quentin Monnet, Miguel Ojeda, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Nick Desaulniers, Bill Wendling, Justin Stitt, linux-perf-users,
bpf, rust-for-linux, linux-kbuild, llvm, linux-kernel
Detect and prefer zlib-rs over C zlib in the perf build unless disabled
with NO_ZLIB_RS=1 (or NO_ZLIB=1 / NO_RUST=1):
- Move Rust compiler detection ahead of zlib detection in
tools/perf/Makefile.config and use feature_check + feature_rust_lib for
zlib-rs, setting both HAVE_ZLIB_SUPPORT and HAVE_ZLIB_RS_SUPPORT when
zlib-rs is used and falling back to C zlib (-lz) otherwise.
- Replace -lz with $(ZLIB_LIBS) in DWARFLIBS and llvm-config
--system-libs so static libdw/libelf and libLLVM configurations use
the selected zlib implementation.
- Build and clean libz_rs.a in $(OUTPUT)libz_rs/, pass ZLIB_CFLAGS when
building static libbpf, and share RUST_OUTPUT with the host bootstrap
bpftool build in tools/perf/bpf_skel.mak.
- Expose 'zlib-rs' in 'perf check feature' / 'perf version --build-options'
and document it in perf-check.txt.
- Add zlib-rs package mappings to tools/perf/scripts/install-build-deps.sh
and NO_ZLIB / NO_ZLIB_RS build tests to tools/perf/tests/make.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/.gitignore | 1 +
tools/perf/Documentation/perf-check.txt | 1 +
tools/perf/Makefile.config | 92 ++++++++++++++----------
tools/perf/Makefile.perf | 32 +++++++--
tools/perf/bpf_skel.mak | 8 ++-
tools/perf/builtin-check.c | 1 +
tools/perf/scripts/install-build-deps.sh | 6 ++
tools/perf/tests/make | 9 +++
8 files changed, 107 insertions(+), 43 deletions(-)
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 3b968c5158b8..8a5df9c9e8ae 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -55,6 +55,7 @@ libbpf/
libperf/
libsubcmd/
libsymbol/
+libz_rs/
fixdep
Documentation/doc.dep
python_ext_build/
diff --git a/tools/perf/Documentation/perf-check.txt b/tools/perf/Documentation/perf-check.txt
index 1406a41c5d09..dda75b1d9cbd 100644
--- a/tools/perf/Documentation/perf-check.txt
+++ b/tools/perf/Documentation/perf-check.txt
@@ -66,6 +66,7 @@ feature::
numa_num_possible_cpus / HAVE_LIBNUMA_SUPPORT
python-module / HAVE_PYTHON_MODULE_SUPPORT
zlib / HAVE_ZLIB_SUPPORT
+ zlib-rs / HAVE_ZLIB_RS_SUPPORT
zstd / HAVE_ZSTD_SUPPORT
OPTIONS
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index b4764f69f47f..81b56cbc8658 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -69,6 +69,12 @@ endif
include $(srctree)/tools/scripts/Makefile.arch
+ifneq ($(CROSS_COMPILE),)
+ ifneq ($(RUST_TARGET_FLAGS_$(ARCH)),)
+ RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH))
+ endif
+endif
+
$(call detected_var,SRCARCH)
CFLAGS += -I$(OUTPUT)arch/$(SRCARCH)/include/generated
@@ -532,13 +538,54 @@ ifdef CORESIGHT
endif
endif
+ifndef NO_RUST
+ $(call feature_check,rust)
+ ifneq ($(feature-rust), 1)
+ $(warning Rust is not found. Test workloads with rust are disabled.)
+ NO_RUST := 1
+ else
+ NO_RUST := 0
+ CFLAGS += -DHAVE_RUST_SUPPORT
+ $(call detected,CONFIG_RUST_SUPPORT)
+ endif
+
+ ifneq ($(CROSS_COMPILE),)
+ ifeq ($(RUST_TARGET_FLAGS_$(ARCH)),)
+ $(error Unknown rust cross compilation architecture $(ARCH))
+ endif
+ endif
+endif
+
+# Building zlib-rs from Cargo crate sources requires a working rustc.
+ifneq ($(NO_RUST), 0)
+ NO_ZLIB_RS := 1
+endif
+
+# Prefer zlib-rs over C zlib when available, unless disabled via NO_ZLIB=1 or
+# NO_ZLIB_RS=1. Both provide the standard zlib C API (HAVE_ZLIB_SUPPORT), while
+# HAVE_ZLIB_RS_SUPPORT records that zlib-rs is the implementation in use.
ifndef NO_ZLIB
- ifeq ($(feature-zlib), 1)
+ ifndef NO_ZLIB_RS
+ $(call feature_check,zlib-rs)
+ ifeq ($(feature-zlib-rs), 1)
+ $(call feature_rust_lib,zlib-rs)
+ ZLIB_CFLAGS := $(FEATURE_CFLAGS-zlib-rs)
+ ZLIB_LIBS := $(FEATURE_LIBS-zlib-rs)
+ CFLAGS += -DHAVE_ZLIB_RS_SUPPORT $(ZLIB_CFLAGS)
+ $(call detected,CONFIG_ZLIB_RS)
+ endif
+ endif
+ ifeq ($(ZLIB_LIBS),)
+ ifeq ($(feature-zlib), 1)
+ ZLIB_LIBS := -lz
+ else
+ NO_ZLIB := 1
+ endif
+ endif
+ ifneq ($(ZLIB_LIBS),)
CFLAGS += -DHAVE_ZLIB_SUPPORT
- EXTLIBS += -lz
+ EXTLIBS += $(ZLIB_LIBS)
$(call detected,CONFIG_ZLIB)
- else
- NO_ZLIB := 1
endif
endif
@@ -580,7 +627,7 @@ ifndef NO_LIBELF
ifndef NO_LIBDW
CFLAGS += -DHAVE_LIBDW_SUPPORT $(LIBDW_CFLAGS)
LDFLAGS += $(LIBDW_LDFLAGS)
- EXTLIBS += ${DWARFLIBS}
+ EXTLIBS += $(patsubst -lz,$(or $(ZLIB_LIBS),-lz),${DWARFLIBS})
$(call detected,CONFIG_LIBDW)
endif # NO_LIBDW
@@ -908,7 +955,7 @@ ifdef BUILD_NONDISTRO
else ifeq ($(feature-libbfd-liberty), 1)
EXTLIBS += -lbfd -lopcodes -liberty
else ifeq ($(feature-libbfd-liberty-z), 1)
- EXTLIBS += -lbfd -lopcodes -liberty -lz
+ EXTLIBS += -lbfd -lopcodes -liberty $(or $(ZLIB_LIBS),-lz)
endif
CFLAGS += -DHAVE_LIBBFD_SUPPORT
@@ -930,7 +977,7 @@ ifndef NO_LIBLLVM
CFLAGS += -DHAVE_LIBLLVM_SUPPORT
LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags 2>/dev/null)
LLVM_CXXFLAGS := $(shell $(LLVM_CONFIG) --cxxflags 2>/dev/null)
- LLVM_LIBLLVM := $(shell $(LLVM_CONFIG) --libs all 2>/dev/null) $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null)
+ LLVM_LIBLLVM := $(shell $(LLVM_CONFIG) --libs all 2>/dev/null) $(patsubst -lz,$(or $(ZLIB_LIBS),-lz),$(shell $(LLVM_CONFIG) --system-libs 2>/dev/null))
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
CFLAGS += $(LLVM_CFLAGS)
CXXFLAGS += -DHAVE_LIBLLVM_SUPPORT $(LLVM_CXXFLAGS)
@@ -1132,37 +1179,6 @@ ifneq ($(NO_LIBTRACEEVENT),1)
endif
endif
-ifndef NO_RUST
- $(call feature_check,rust)
- ifneq ($(feature-rust), 1)
- $(warning Rust is not found. Test workloads with rust are disabled.)
- NO_RUST := 1
- else
- NO_RUST := 0
- CFLAGS += -DHAVE_RUST_SUPPORT
- $(call detected,CONFIG_RUST_SUPPORT)
- endif
-
- ifneq ($(CROSS_COMPILE),)
- RUST_TARGET_FLAGS_arm := arm-unknown-linux-gnueabi
- RUST_TARGET_FLAGS_arm64 := aarch64-unknown-linux-gnu
- RUST_TARGET_FLAGS_loongarch := loongarch64-unknown-linux-gnu
- RUST_TARGET_FLAGS_m68k := m68k-unknown-linux-gnu
- RUST_TARGET_FLAGS_mips := mipsel-unknown-linux-gnu
- RUST_TARGET_FLAGS_powerpc := powerpc64le-unknown-linux-gnu
- RUST_TARGET_FLAGS_riscv := riscv64gc-unknown-linux-gnu
- RUST_TARGET_FLAGS_s390 := s390x-unknown-linux-gnu
- RUST_TARGET_FLAGS_x86 := x86_64-unknown-linux-gnu
- RUST_TARGET_FLAGS_x86_64 := x86_64-unknown-linux-gnu
-
- ifeq ($(RUST_TARGET_FLAGS_$(ARCH)),)
- $(error Unknown rust cross compilation architecture $(ARCH))
- endif
-
- RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH))
- endif
-endif
-
# Among the variables below, these:
# perfexecdir
# libbpf_include_dir
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index b74b534e1153..0c24b13e9e0c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -75,6 +75,8 @@ include ../scripts/utilities.mak
#
# Define NO_ZLIB if you do not want to support compressed kernel modules
#
+# Define NO_ZLIB_RS if you do not want to use zlib-rs for zlib support
+#
# Define NO_BABELTRACE2 if you do not want babeltrace2-ctf-writer support
# for CTF data format.
#
@@ -417,6 +419,13 @@ ifdef LIBBPF_STATIC
CFLAGS += -I$(LIBBPF_OUTPUT)/include
endif
+ifneq ($(OUTPUT),)
+ LIBZ_RS_OUTPUT = $(abspath $(OUTPUT))/libz_rs
+else
+ LIBZ_RS_OUTPUT = $(CURDIR)/libz_rs
+endif
+LIBZ_RS = $(filter %/libz_rs.a,$(ZLIB_LIBS))
+
ifneq ($(OUTPUT),)
LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd
else
@@ -741,6 +750,11 @@ ifdef LIBBPF_STATIC
prepare: $(LIBBPF)
endif
+ifneq ($(LIBZ_RS),)
+prepare: $(LIBZ_RS)
+bpf-skel-prepare: $(LIBZ_RS)
+endif
+
$(OUTPUT)%.o: %.c prepare FORCE
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -805,15 +819,25 @@ $(LIBAPI)-clean:
$(call QUIET_CLEAN, libapi)
$(Q)$(RM) -r -- $(LIBAPI_OUTPUT)
-$(LIBBPF): FORCE | $(LIBBPF_OUTPUT)
+$(LIBBPF): FORCE $(LIBZ_RS) | $(LIBBPF_OUTPUT)
$(Q)$(MAKE) -C $(LIBBPF_DIR) FEATURES_DUMP=$(FEATURE_DUMP_EXPORT) \
O= OUTPUT=$(LIBBPF_OUTPUT)/ DESTDIR=$(LIBBPF_DESTDIR) prefix= subdir= \
- EXTRA_CFLAGS="-fPIC" $@ install_headers
+ EXTRA_CFLAGS="-fPIC $(ZLIB_CFLAGS)" $@ install_headers
$(LIBBPF)-clean:
$(call QUIET_CLEAN, libbpf)
$(Q)$(RM) -r -- $(LIBBPF_OUTPUT)
+ifneq ($(LIBZ_RS),)
+$(LIBZ_RS): | $(LIBZ_RS_OUTPUT)
+ $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.rust LIBZ_RS_OUTPUT=$(LIBZ_RS_OUTPUT)/ \
+ CARGO="$(CARGO)" RUSTC="$(RUSTC)" RUST_FLAGS="$(RUST_FLAGS)" $@
+endif
+
+libz-rs-clean:
+ $(call QUIET_CLEAN, libz_rs)
+ $(Q)$(RM) -r -- $(LIBZ_RS_OUTPUT)
+
$(LIBPERF): FORCE | $(LIBPERF_OUTPUT)
$(Q)$(MAKE) -C $(LIBPERF_DIR) O=$(LIBPERF_OUTPUT) \
DESTDIR=$(LIBPERF_DESTDIR) prefix= subdir= \
@@ -1026,7 +1050,7 @@ python-clean:
$(RM) $(OUTPUT)python/perf.pyi; \
fi
-$(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT):
+$(LIBAPI_OUTPUT) $(LIBBPF_OUTPUT) $(LIBPERF_OUTPUT) $(LIBSUBCMD_OUTPUT) $(LIBSYMBOL_OUTPUT) $(LIBZ_RS_OUTPUT):
$(Q)$(MKDIR) -p $@
bpf-skel-clean:
@@ -1050,7 +1074,7 @@ else # When an OUTPUT directory is present, clean up the copied pmu-events/arch
endif
clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(LIBPERF)-clean \
- arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean \
+ libz-rs-clean arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean \
pmu-events-clean
$(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive \
$(OUTPUT)perf-iostat $(LANG_BINDINGS)
diff --git a/tools/perf/bpf_skel.mak b/tools/perf/bpf_skel.mak
index f2559de39f96..d2ac4c4a7402 100644
--- a/tools/perf/bpf_skel.mak
+++ b/tools/perf/bpf_skel.mak
@@ -39,9 +39,15 @@ ifneq ($(WERROR),0)
CLANG_OPTIONS += -Werror
endif
+# When not cross-compiling, share the top-level $(OUTPUT)libz_rs/ directory
+# with the host bootstrap bpftool build so libz_rs.a is not compiled twice.
+ifeq ($(CROSS_COMPILE),)
+BPFTOOL_RUST_OUTPUT := RUST_OUTPUT=$(abspath $(or $(OUTPUT),.))/
+endif
+
$(BPFTOOL):
$(Q)mkdir -p $(SKEL_TOOL_TMP_OUT)
- $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool OUTPUT=$(SKEL_TOOL_TMP_OUT)/ bootstrap
+ $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool OUTPUT=$(SKEL_TOOL_TMP_OUT)/ $(BPFTOOL_RUST_OUTPUT) bootstrap
# Paths to search for a kernel to generate vmlinux.h from.
VMLINUX_BTF_ELF_PATHS ?= $(if $(O),$(O)/vmlinux) \
diff --git a/tools/perf/builtin-check.c b/tools/perf/builtin-check.c
index 1e43e097e7a7..fe1fc40561a9 100644
--- a/tools/perf/builtin-check.c
+++ b/tools/perf/builtin-check.c
@@ -59,6 +59,7 @@ struct feature_status supported_features[] = {
FEATURE_STATUS("lzma", HAVE_LZMA_SUPPORT),
FEATURE_STATUS("numa_num_possible_cpus", HAVE_LIBNUMA_SUPPORT),
FEATURE_STATUS("zlib", HAVE_ZLIB_SUPPORT),
+ FEATURE_STATUS("zlib-rs", HAVE_ZLIB_RS_SUPPORT),
FEATURE_STATUS("zstd", HAVE_ZSTD_SUPPORT),
FEATURE_STATUS("rust", HAVE_RUST_SUPPORT),
diff --git a/tools/perf/scripts/install-build-deps.sh b/tools/perf/scripts/install-build-deps.sh
index 3e53c7bf0f85..7c405f1a4c83 100755
--- a/tools/perf/scripts/install-build-deps.sh
+++ b/tools/perf/scripts/install-build-deps.sh
@@ -146,6 +146,9 @@ fedora_pkg_for() {
zlib)
echo "zlib-devel"
;;
+ zlib-rs)
+ echo "cargo rust-libz-rs-sys-devel"
+ ;;
lzma)
echo "xz-devel"
;;
@@ -305,6 +308,9 @@ debian_pkg_for() {
zlib)
echo "zlib1g-dev"
;;
+ zlib-rs)
+ echo "cargo librust-libz-rs-sys-dev"
+ ;;
lzma)
echo "liblzma-dev"
;;
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 7524de522802..96567d9ea2a4 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -99,6 +99,8 @@ make_no_babeltrace2 := NO_BABELTRACE2=1
make_with_coresight := CORESIGHT=1
make_no_sdt := NO_SDT=1
make_no_libpfm4 := NO_LIBPFM4=1
+make_no_zlib := NO_ZLIB=1
+make_no_zlib_rs := NO_ZLIB_RS=1
make_with_gtk4 := GTK4=1
make_refcnt_check := EXTRA_CFLAGS="-DREFCNT_CHECKING=1"
make_tags := tags
@@ -193,6 +195,8 @@ run += make_no_sdt
run += make_no_babeltrace2
run += make_with_coresight
run += make_no_libpfm4
+run += make_no_zlib
+run += make_no_zlib_rs
run += make_refcnt_check
run += make_help
run += make_doc
@@ -302,6 +306,11 @@ 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
+test_make_no_zlib := test -x $(PERF_O)/perf && ! $(PERF_O)/perf check -q feature zlib && ! $(PERF_O)/perf check -q feature zlib-rs
+test_make_no_zlib_O := test -x $$TMP_O/perf && ! $$TMP_O/perf check -q feature zlib && ! $$TMP_O/perf check -q feature zlib-rs
+test_make_no_zlib_rs := test -x $(PERF_O)/perf && ! $(PERF_O)/perf check -q feature zlib-rs
+test_make_no_zlib_rs_O := test -x $$TMP_O/perf && ! $$TMP_O/perf check -q feature zlib-rs
+
# 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
--
2.56.0.455.g6c5a503b38-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC PATCH v3 3/3] bpftool: Prefer zlib-rs over zlib when available
2026-11-05 18:09 [RFC PATCH v3 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
@ 2026-11-05 18:09 ` Ian Rogers
2026-11-05 18:15 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
2 siblings, 2 replies; 10+ messages in thread
From: Ian Rogers @ 2026-11-05 18:09 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Ian Rogers, Adrian Hunter,
Quentin Monnet, Miguel Ojeda, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Nick Desaulniers, Bill Wendling, Justin Stitt, linux-perf-users,
bpf, rust-for-linux, linux-kbuild, llvm, linux-kernel
Add zlib-rs and zlib to FEATURE_TESTS and FEATURE_DISPLAY in
tools/bpf/bpftool/Makefile and use feature_rust_lib to configure
ZLIB_CFLAGS and ZLIB_LIBS when zlib-rs is detected (unless disabled with
NO_ZLIB_RS=1), falling back to -lz. Also replace -lz with $(ZLIB_LIBS)
in static llvm-config --system-libs.
Decompression of kernel configuration (/proc/config.gz) and compressed
ELF/BTF sections (via libbpf, and via libelf/libbfd/libLLVM in static
builds) processes data that benefits from a memory-safe implementation.
Preferring zlib-rs over C zlib provides memory safety and improved
decompression performance while keeping bpftool aligned with tools/perf
(including sharing libz_rs.a when building bootstrap bpftool for perf
BPF skeletons).
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/bpf/bpftool/.gitignore | 1 +
tools/bpf/bpftool/Makefile | 59 +++++++++++++++++++++++++++++++-----
2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/tools/bpf/bpftool/.gitignore b/tools/bpf/bpftool/.gitignore
index a736f64dc5dc..ea2222373634 100644
--- a/tools/bpf/bpftool/.gitignore
+++ b/tools/bpf/bpftool/.gitignore
@@ -6,5 +6,6 @@ bpftool*.8
FEATURE-DUMP.bpftool
feature
libbpf
+libz_rs
/*.skel.h
/vmlinux.h
diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
index b0f7168e7943..0b5f3967465f 100644
--- a/tools/bpf/bpftool/Makefile
+++ b/tools/bpf/bpftool/Makefile
@@ -16,6 +16,8 @@ else
endif
BOOTSTRAP_OUTPUT := $(_OUTPUT)bootstrap/
+LIBZ_RS_OUTPUT := $(_OUTPUT)libz_rs/
+
LIBBPF_OUTPUT := $(_OUTPUT)libbpf/
LIBBPF_DESTDIR := $(LIBBPF_OUTPUT)
LIBBPF_INCLUDE := $(LIBBPF_DESTDIR)include
@@ -38,7 +40,9 @@ $(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBBPF_BOOTSTRAP_OUTPUT) $(LIBBPF_HDRS_DI
$(LIBBPF): $(wildcard $(BPF_DIR)/*.[ch] $(BPF_DIR)/Makefile) | $(LIBBPF_OUTPUT)
$(Q)$(MAKE) -C $(BPF_DIR) OUTPUT=$(LIBBPF_OUTPUT) \
- DESTDIR=$(LIBBPF_DESTDIR:/=) prefix= $(LIBBPF) install_headers
+ DESTDIR=$(LIBBPF_DESTDIR:/=) prefix= \
+ $(if $(ZLIB_CFLAGS),EXTRA_CFLAGS="$(or $(EXTRA_CFLAGS),-g -O2) $(ZLIB_CFLAGS)") \
+ $(LIBBPF) install_headers
$(LIBBPF_INTERNAL_HDRS): $(LIBBPF_HDRS_DIR)/%.h: $(BPF_DIR)/%.h | $(LIBBPF_HDRS_DIR)
$(call QUIET_INSTALL, $@)
@@ -115,8 +119,20 @@ ifneq ($(SKIP_CRYPTO),1)
CRYPTO_LIBS := -lcrypto
endif
+ifneq ($(CROSS_COMPILE),)
+ ifneq ($(MAKECMDGOALS),bootstrap)
+ ifneq ($(RUST_TARGET_FLAGS_$(ARCH)),)
+ RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH))
+ else
+ NO_ZLIB_RS := 1
+ endif
+ else
+ NO_ZLIB_RS := 1
+ endif
+endif
+
ifeq ($(MAKECMDGOALS),bootstrap)
-FEATURE_TESTS := libelf-zstd
+FEATURE_TESTS := libelf-zstd $(if $(NO_ZLIB_RS),,zlib-rs) zlib
FEATURE_DISPLAY :=
else
FEATURE_TESTS := clang-bpf-co-re
@@ -128,6 +144,10 @@ FEATURE_TESTS += libbfd-liberty-z
FEATURE_TESTS += disassembler-four-args
FEATURE_TESTS += disassembler-init-styled
FEATURE_TESTS += libelf-zstd
+ifeq ($(NO_ZLIB_RS),)
+FEATURE_TESTS += zlib-rs
+endif
+FEATURE_TESTS += zlib
FEATURE_DISPLAY := clang-bpf-co-re
FEATURE_DISPLAY += llvm
@@ -135,6 +155,10 @@ FEATURE_DISPLAY += libcap
FEATURE_DISPLAY += libbfd
FEATURE_DISPLAY += libbfd-liberty
FEATURE_DISPLAY += libbfd-liberty-z
+ifeq ($(NO_ZLIB_RS),)
+FEATURE_DISPLAY += zlib-rs
+endif
+FEATURE_DISPLAY += zlib
endif
check_feat := 1
@@ -153,8 +177,29 @@ include $(FEATURES_DUMP)
endif
endif
-LIBS = $(LIBBPF) -lelf $(CRYPTO_LIBS) -lz
-LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf $(CRYPTO_LIBS) -lz
+# Prefer zlib-rs over C zlib when detected (libz_rs.a exports the full zlib C
+# ABI including both gzopen and gzopen64, so it is also compatible with a
+# pre-built libbpf.a compiled against system <zlib.h> with _FILE_OFFSET_BITS=64).
+# When cross-compiling, the host bootstrap bpftool still links against the
+# host's -lz.
+ZLIB_LIBS := -lz
+ZLIB_BOOTSTRAP_LIBS := -lz
+ifeq ($(feature-zlib-rs),1)
+ ifeq ($(NO_ZLIB_RS),)
+ $(call feature_rust_lib,zlib-rs)
+ ZLIB_CFLAGS := $(FEATURE_CFLAGS-zlib-rs)
+ ZLIB_LIBS := $(FEATURE_LIBS-zlib-rs)
+ CFLAGS += $(ZLIB_CFLAGS)
+ ifeq ($(CROSS_COMPILE),)
+ HOST_CFLAGS += $(ZLIB_CFLAGS)
+ LIBBPF_BOOTSTRAP_CFLAGS += $(ZLIB_CFLAGS)
+ ZLIB_BOOTSTRAP_LIBS := $(ZLIB_LIBS)
+ endif
+ endif
+endif
+
+LIBS = $(LIBBPF) -lelf $(CRYPTO_LIBS) $(ZLIB_LIBS)
+LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf $(CRYPTO_LIBS) $(ZLIB_BOOTSTRAP_LIBS)
ifeq ($(feature-libelf-zstd),1)
LIBS += -lzstd
@@ -188,7 +233,7 @@ ifeq ($(HAS_LLVM),1)
CFLAGS += $(filter-out -D_GNU_SOURCE,$(shell $(LLVM_CONFIG) --cflags))
LIBS += $(shell $(LLVM_CONFIG) --libs $(LLVM_CONFIG_LIB_COMPONENTS))
ifeq ($(shell $(LLVM_CONFIG) --shared-mode),static)
- LIBS += $(shell $(LLVM_CONFIG) --system-libs $(LLVM_CONFIG_LIB_COMPONENTS))
+ LIBS += $(patsubst -lz,$(ZLIB_LIBS),$(shell $(LLVM_CONFIG) --system-libs $(LLVM_CONFIG_LIB_COMPONENTS)))
LIBS += -lstdc++
endif
LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags)
@@ -200,7 +245,7 @@ else
else ifeq ($(feature-libbfd-liberty),1)
LIBS += -lbfd -ldl -lopcodes -liberty
else ifeq ($(feature-libbfd-liberty-z),1)
- LIBS += -lbfd -ldl -lopcodes -liberty -lz
+ LIBS += -lbfd -ldl -lopcodes -liberty $(ZLIB_LIBS)
endif
# If one of the above feature combinations is set, we support libbfd
@@ -304,7 +349,7 @@ clean: $(LIBBPF)-clean $(LIBBPF_BOOTSTRAP)-clean feature-detect-clean
$(call QUIET_CLEAN, bpftool)
$(Q)$(RM) -- $(OUTPUT)bpftool $(OUTPUT)*.o $(OUTPUT)*.d
$(Q)$(RM) -- $(OUTPUT)*.skel.h $(OUTPUT)vmlinux.h
- $(Q)$(RM) -r -- $(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT)
+ $(Q)$(RM) -r -- $(LIBBPF_OUTPUT) $(BOOTSTRAP_OUTPUT) $(LIBZ_RS_OUTPUT)
$(call QUIET_CLEAN, core-gen)
$(Q)$(RM) -- $(OUTPUT)FEATURE-DUMP.bpftool
$(Q)$(RM) -r -- $(OUTPUT)feature/
--
2.56.0.455.g6c5a503b38-goog
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 3/3] bpftool: Prefer zlib-rs over zlib when available
2026-11-05 18:09 ` [RFC PATCH v3 3/3] bpftool: " Ian Rogers
@ 2026-11-05 18:15 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-05 18:15 UTC (permalink / raw)
To: Ian Rogers; +Cc: linux-perf-users
> Add zlib-rs and zlib to FEATURE_TESTS and FEATURE_DISPLAY in
> tools/bpf/bpftool/Makefile and use feature_rust_lib to configure
> ZLIB_CFLAGS and ZLIB_LIBS when zlib-rs is detected (unless disabled with
> NO_ZLIB_RS=1), falling back to -lz. Also replace -lz with $(ZLIB_LIBS)
> in static llvm-config --system-libs.
>
> Decompression of kernel configuration (/proc/config.gz) and compressed
> ELF/BTF sections (via libbpf, and via libelf/libbfd/libLLVM in static
> builds) processes data that benefits from a memory-safe implementation.
> Preferring zlib-rs over C zlib provides memory safety and improved
> decompression performance while keeping bpftool aligned with tools/perf
> (including sharing libz_rs.a when building bootstrap bpftool for perf
> BPF skeletons).
>
> Signed-off-by: Ian Rogers <irogers@google.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105180923.3441359-1-irogers@google.com?part=3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available
2026-11-05 18:09 ` [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
@ 2026-11-05 18:26 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-05 18:26 UTC (permalink / raw)
To: Ian Rogers; +Cc: linux-perf-users
> Detect and prefer zlib-rs over C zlib in the perf build unless disabled
> with NO_ZLIB_RS=1 (or NO_ZLIB=1 / NO_RUST=1):
>
> - Move Rust compiler detection ahead of zlib detection in
> tools/perf/Makefile.config and use feature_check + feature_rust_lib for
> zlib-rs, setting both HAVE_ZLIB_SUPPORT and HAVE_ZLIB_RS_SUPPORT when
> zlib-rs is used and falling back to C zlib (-lz) otherwise.
> - Replace -lz with $(ZLIB_LIBS) in DWARFLIBS and llvm-config
> --system-libs so static libdw/libelf and libLLVM configurations use
> the selected zlib implementation.
> - Build and clean libz_rs.a in $(OUTPUT)libz_rs/, pass ZLIB_CFLAGS when
> building static libbpf, and share RUST_OUTPUT with the host bootstrap
> bpftool build in tools/perf/bpf_skel.mak.
> - Expose 'zlib-rs' in 'perf check feature' / 'perf version --build-options'
> and document it in perf-check.txt.
> - Add zlib-rs package mappings to tools/perf/scripts/install-build-deps.sh
> and NO_ZLIB / NO_ZLIB_RS build tests to tools/perf/tests/make.
>
> Signed-off-by: Ian Rogers <irogers@google.com>
Sashiko has reviewed this patch and found no issues.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105180923.3441359-1-irogers@google.com?part=2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
@ 2026-11-05 18:30 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-11-05 18:30 UTC (permalink / raw)
To: Ian Rogers, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Jiri Olsa, Adrian Hunter, Quentin Monnet,
Miguel Ojeda, Nathan Chancellor, Nicolas Schier
Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
Nick Desaulniers, Bill Wendling, Justin Stitt, linux-perf-users,
bpf, linux-kbuild
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] tools build: feature_check_code passes CLANG_CROSS_FLAGS to g++ in CXXFLAGS
--
commit b53b88b2adbac2b7788068d159976b5144e79923
Author: Ian Rogers <irogers@google.com>
tools build: Add Rust library build infrastructure and zlib-rs feature test
This commit adds shared Rust library build and feature detection rules under
tools/build/Makefile.rust, along with cross-compilation target mappings and a
feature test for zlib-rs.
> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
> index 4d37d11f674c5..ecf27626d493e 100644
> --- a/tools/build/Makefile.feature
> +++ b/tools/build/Makefile.feature
> @@ -5,10 +5,11 @@ ifneq ($(OUTPUT),)
> OUTPUT_FEATURES = $(OUTPUT)feature/
> $(shell mkdir -p $(OUTPUT_FEATURES))
> endif
> +RUST_OUTPUT ?= $(abspath $(or $(OUTPUT),$(CURDIR)))/
>
> feature_check = $(eval $(feature_check_code))
> define feature_check_code
> - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
> + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) RUST_OUTPUT="$(RUST_OUTPUT)" CC="$(CC)" CXX="$(CXX)" CARGO="$(CARGO)" RUSTC="$(RUSTC)" $(if $(PKG_CONFIG),PKG_CONFIG="$(PKG_CONFIG)") CFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" RUST_FLAGS="$(RUST_FLAGS)" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
> endef
[Severity: Medium]
Does prepending $(CLANG_CROSS_FLAGS) to CXXFLAGS in feature_check_code break
C++ feature detection (such as cxa-demangle, llvm, and llvm-perf) when
cross-compiling with CC=clang and the default CXX=$(CROSS_COMPILE)g++?
In tools/scripts/Makefile.include, CLANG_CROSS_FLAGS is populated whenever
CC_NO_CLANG is 0 and CROSS_COMPILE is set, and is only appended to CFLAGS and
AFLAGS while CXX defaults to $(CROSS_COMPILE)g++ (unless LLVM is set or CXX is
explicitly overridden):
tools/scripts/Makefile.include:
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
...
$(call allow-override,CXX,$(CROSS_COMPILE)g++)
...
CLANG_CROSS_FLAGS := --target=$(CLANG_TARGET)
GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc 2>/dev/null))
ifneq ($(GCC_TOOLCHAIN_DIR),)
CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
CLANG_CROSS_FLAGS += --sysroot=$(shell $(CROSS_COMPILE)gcc -print-sysroot)
CLANG_CROSS_FLAGS += --gcc-toolchain=$(realpath $(GCC_TOOLCHAIN_DIR)/..)
endif # GCC_TOOLCHAIN_DIR
endif # CLANG_CROSS_FLAGS
CFLAGS += $(CLANG_CROSS_FLAGS)
AFLAGS += $(CLANG_CROSS_FLAGS)
As noted in tools/perf/Makefile.config (commit c8592f8da838 ("perf build: Fix
CXX clang flag injection when only CC=clang is set")), CC being clang does not
imply CXX is clang++. When $(CROSS_COMPILE)g++ is invoked for a C++ feature
check via $(BUILDXX), it rejects Clang-only flags in CLANG_CROSS_FLAGS such as
--target=... and --gcc-toolchain=..., causing the feature check to fail.
Also, this change to CFLAGS and CXXFLAGS in tools/build/Makefile.feature is
not mentioned in the commit message. Should CLANG_CROSS_FLAGS only be passed
in CXXFLAGS when CXX is actually clang++, or is this change intended for a
separate patch?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105180923.3441359-1-irogers@google.com?part=1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available
2026-11-05 18:09 ` [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
2026-11-05 18:26 ` sashiko-bot
@ 2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: bot+bpf-ci @ 2026-11-05 18:53 UTC (permalink / raw)
To: irogers, peterz, mingo, acme, namhyung, jolsa, irogers,
adrian.hunter, qmo, ojeda, nathan, nsc
Cc: boqun, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl, tmgross,
dakr, ndesaulniers, morbo, justinstitt, linux-perf-users, bpf,
rust-for-linux, linux-kbuild, llvm, linux-kernel, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2006 bytes --]
> perf build: Prefer zlib-rs over zlib when available
TL;DR: install-build-deps.sh may fail entirely on Debian 13 (and possibly
Fedora) because the new zlib-rs package mapping names packages that may not
exist, with no availability check, so apt-get could install nothing.
> diff --git a/tools/perf/scripts/install-build-deps.sh b/tools/perf/scripts/install-build-deps.sh
> --- a/tools/perf/scripts/install-build-deps.sh
> +++ b/tools/perf/scripts/install-build-deps.sh
[ ... ]
> @@ -305,6 +308,9 @@ debian_pkg_for() {
> zlib)
> echo "zlib1g-dev"
> ;;
> + zlib-rs)
> + echo "cargo librust-libz-rs-sys-dev"
> + ;;
> lzma)
> echo "liblzma-dev"
> ;;
Will this break install-build-deps.sh on Debian 13 (trixie), which the
script header lists as validated?
trixie does not appear to ship librust-libz-rs-sys-dev, and unlike the RHEL
branch, the Debian/Ubuntu path in package_set() has no availability check
(pkg_available() is only used for RHEL). The name goes straight into the
install command:
echo "DEBIAN_FRONTEND=noninteractive apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y $*"
apt-get then fails with "E: Unable to locate package
librust-libz-rs-sys-dev" (exit 100) and installs nothing, including the
packages that are available. main() prints "error: the install command
failed" and exits 1.
Before this patch zlib-rs had no case, so it was skipped via
[ -n "$pkg" ] || continue and the install worked.
The fedora_pkg_for() name rust-libz-rs-sys-devel is also added without a
check, so Fedora would fail the same way if it lacks that package.
Should debian_pkg_for() probe availability the way pkg_available() does for
dnf, or leave zlib-rs unmapped on distros that do not package the crate?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/42083491750
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
2026-11-05 18:30 ` sashiko-bot
@ 2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: bot+bpf-ci @ 2026-11-05 18:53 UTC (permalink / raw)
To: irogers, peterz, mingo, acme, namhyung, jolsa, irogers,
adrian.hunter, qmo, ojeda, nathan, nsc
Cc: boqun, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl, tmgross,
dakr, ndesaulniers, morbo, justinstitt, linux-perf-users, bpf,
rust-for-linux, linux-kbuild, llvm, linux-kernel, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3342 bytes --]
> tools build: Add Rust library build infrastructure and zlib-rs feature test
TL;DR: Prepending CLANG_CROSS_FLAGS to CXXFLAGS in the feature tests may break
C++ checks (cxa-demangle, llvm) when cross-building with CC=clang but a g++
CXX, silently dropping perf features.
> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
> index 4d37d11f674c..ecf27626d493 100644
> --- a/tools/build/Makefile.feature
> +++ b/tools/build/Makefile.feature
> @@ -5,10 +5,11 @@ ifneq ($(OUTPUT),)
> OUTPUT_FEATURES = $(OUTPUT)feature/
> $(shell mkdir -p $(OUTPUT_FEATURES))
> endif
> +RUST_OUTPUT ?= $(abspath $(or $(OUTPUT),$(CURDIR)))/
>
> feature_check = $(eval $(feature_check_code))
> define feature_check_code
> - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
> + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) RUST_OUTPUT="$(RUST_OUTPUT)" CC="$(CC)" CXX="$(CXX)" CARGO="$(CARGO)" RUSTC="$(RUSTC)" $(if $(PKG_CONFIG),PKG_CONFIG="$(PKG_CONFIG)") CFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(CLANG_CROSS_FLAGS) $(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" RUST_FLAGS="$(RUST_FLAGS)" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
> endef
Is it correct to prepend $(CLANG_CROSS_FLAGS) to CXXFLAGS here?
CLANG_CROSS_FLAGS is computed in tools/scripts/Makefile.include from a
probe of CC alone (CC_NO_CLANG == 0 && CROSS_COMPILE set), and holds
clang-only options such as --target=<triple>, --prefix=, --sysroot= and
--gcc-toolchain=. Nothing checks that CXX is clang.
With 'make CC=clang CROSS_COMPILE=aarch64-linux-gnu-' (no LLVM=1),
Makefile.include leaves CXX as $(CROSS_COMPILE)g++, so each C++ feature
test would run as something like:
aarch64-linux-gnu-g++ --target=aarch64-linux-gnu ... --gcc-toolchain=/usr
-MD -Wall -Werror -o test-cxa-demangle.bin test-cxa-demangle.cpp
and g++ rejects the unrecognized --target option. The probe is silent
(output goes to /dev/null), so feature_check for cxa-demangle, llvm and
llvm-perf would return 0 and perf would drop HAVE_CXA_DEMANGLE_SUPPORT
and libllvm support without any error.
Before this patch CXXFLAGS in the feature sub-make did not contain
CLANG_CROSS_FLAGS, and Makefile.include only appends it to CFLAGS and
AFLAGS, so those tests passed. The same kind of failure was already fixed
for native perf builds in c8592f8da838 ("perf build: Only pass clang flags
to CXX when CXX is clang"), where tools/perf/Makefile.config probes
CXX_NO_CLANG separately.
Could CLANG_CROSS_FLAGS be added to CXXFLAGS only when CXX is clang, or
left on CFLAGS only? The commit message also does not mention that
CLANG_CROSS_FLAGS is now passed to every tool's feature tests.
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/42083491750
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC PATCH v3 3/3] bpftool: Prefer zlib-rs over zlib when available
2026-11-05 18:09 ` [RFC PATCH v3 3/3] bpftool: " Ian Rogers
2026-11-05 18:15 ` sashiko-bot
@ 2026-11-05 18:53 ` bot+bpf-ci
1 sibling, 0 replies; 10+ messages in thread
From: bot+bpf-ci @ 2026-11-05 18:53 UTC (permalink / raw)
To: irogers, peterz, mingo, acme, namhyung, jolsa, irogers,
adrian.hunter, qmo, ojeda, nathan, nsc
Cc: boqun, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl, tmgross,
dakr, ndesaulniers, morbo, justinstitt, linux-perf-users, bpf,
rust-for-linux, linux-kbuild, llvm, linux-kernel, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2116 bytes --]
> bpftool: Prefer zlib-rs over zlib when available
TL;DR: Possible behaviour issue: bpftool ignores perf's NO_RUST/NO_ZLIB_RS, so
"make -C tools/perf NO_RUST=1" may still build and link the bootstrap bpftool
against zlib-rs via cargo.
> diff --git a/tools/bpf/bpftool/Makefile b/tools/bpf/bpftool/Makefile
> --- a/tools/bpf/bpftool/Makefile
> +++ b/tools/bpf/bpftool/Makefile
[ ... ]
> @@ -115,8 +119,20 @@ ifneq ($(SKIP_CRYPTO),1)
> CRYPTO_LIBS := -lcrypto
> endif
>
> +ifneq ($(CROSS_COMPILE),)
> + ifneq ($(MAKECMDGOALS),bootstrap)
> + ifneq ($(RUST_TARGET_FLAGS_$(ARCH)),)
> + RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH))
> + else
> + NO_ZLIB_RS := 1
> + endif
> + else
> + NO_ZLIB_RS := 1
> + endif
> +endif
> +
> ifeq ($(MAKECMDGOALS),bootstrap)
> -FEATURE_TESTS := libelf-zstd
> +FEATURE_TESTS := libelf-zstd $(if $(NO_ZLIB_RS),,zlib-rs) zlib
> FEATURE_DISPLAY :=
> else
The commit message says bpftool stays aligned with tools/perf, and that
zlib-rs is shared with the bootstrap bpftool built for perf BPF skeletons.
In perf, zlib-rs is turned off when NO_RUST is set or rustc is not found:
tools/perf/Makefile.config:
ifneq ($(NO_RUST), 0)
NO_ZLIB_RS := 1
That NO_ZLIB_RS is a plain makefile variable in perf, so it does not reach
the sub-make that tools/perf/bpf_skel.mak runs:
$(MAKE) -C ../bpf/bpftool OUTPUT=$(SKEL_TOOL_TMP_OUT)/ \
$(BPFTOOL_RUST_OUTPUT) bootstrap
bpftool only looks at NO_ZLIB_RS and CROSS_COMPILE and never at NO_RUST.
Can "make -C tools/perf NO_RUST=1" on a host that has cargo and the cargo
registry installed still list zlib-rs in the bootstrap FEATURE_TESTS here,
run cargo to build libz_rs.a, and link the bootstrap bpftool against it?
Would it make sense to pass NO_ZLIB_RS=1 from bpf_skel.mak when perf has
disabled zlib-rs, or to have bpftool honour NO_RUST=1?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/42083491750
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-05 18:53 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-05 18:09 [RFC PATCH v3 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-11-05 18:09 ` [RFC PATCH v3 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
2026-11-05 18:30 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
2026-11-05 18:09 ` [RFC PATCH v3 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
2026-11-05 18:26 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
2026-11-05 18:09 ` [RFC PATCH v3 3/3] bpftool: " Ian Rogers
2026-11-05 18:15 ` sashiko-bot
2026-11-05 18:53 ` bot+bpf-ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox