* [RFC PATCH v2 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs
@ 2026-10-30 20:27 Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Ian Rogers @ 2026-10-30 20:27 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`).
- 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.
- 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` and configures `ZLIB_CFLAGS` and
`ZLIB_LIBS` via `feature_rust_lib` when `zlib-rs` is detected.
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, separate Rust library outputs
into $(OUTPUT)libz_rs/, 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 `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 | 57 +++++++++-
tools/build/Makefile.feature | 12 +-
tools/build/Makefile.rust | 160 +++++++++++++++++++++++
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 | 88 +++++++------
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, 382 insertions(+), 50 deletions(-)
create mode 100644 tools/build/Makefile.rust
create mode 100644 tools/build/feature/test-zlib-rs.c
--
2.56.0.317.g454f8302e1-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v2 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test
2026-10-30 20:27 [RFC PATCH v2 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
@ 2026-10-30 20:27 ` Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 3/3] bpftool: " Ian Rogers
2 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-10-30 20:27 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).
- 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 | 160 +++++++++++++++++++++++++++++
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, 225 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..4b7e47968b7b
--- /dev/null
+++ b/tools/build/Makefile.rust
@@ -0,0 +1,160 @@
+# 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
+ FEATURE_LIBS-zlib-rs := $(FEATURE_STATIC-zlib-rs) -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.317.g454f8302e1-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v2 2/3] perf build: Prefer zlib-rs over zlib when available
2026-10-30 20:27 [RFC PATCH v2 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
@ 2026-10-30 20:27 ` Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 3/3] bpftool: " Ian Rogers
2 siblings, 0 replies; 5+ messages in thread
From: Ian Rogers @ 2026-10-30 20:27 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.
- 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 | 88 ++++++++++++++----------
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, 105 insertions(+), 41 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..d447f4bd8f5b 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
@@ -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 $(ZLIB_LIBS)
endif
CFLAGS += -DHAVE_LIBBFD_SUPPORT
@@ -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.317.g454f8302e1-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v2 3/3] bpftool: Prefer zlib-rs over zlib when available
2026-10-30 20:27 [RFC PATCH v2 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
@ 2026-10-30 20:27 ` Ian Rogers
2026-11-02 16:20 ` Quentin Monnet
2 siblings, 1 reply; 5+ messages in thread
From: Ian Rogers @ 2026-10-30 20:27 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.
Decompression of kernel configuration (/proc/config.gz) and compressed
ELF/BTF sections (via libbpf, libelf, and libbfd) 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 | 57 ++++++++++++++++++++++++++++++++----
2 files changed, 52 insertions(+), 6 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..16b9a00963e3 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
@@ -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.317.g454f8302e1-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH v2 3/3] bpftool: Prefer zlib-rs over zlib when available
2026-10-30 20:27 ` [RFC PATCH v2 3/3] bpftool: " Ian Rogers
@ 2026-11-02 16:20 ` Quentin Monnet
0 siblings, 0 replies; 5+ messages in thread
From: Quentin Monnet @ 2026-11-02 16:20 UTC (permalink / raw)
To: Ian Rogers, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Jiri Olsa, Adrian Hunter,
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
Hi Ian, thanks for the v2,
2026-10-30 13:27 UTC-0700 ~ Ian Rogers <irogers@google.com>
> 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.
>
> Decompression of kernel configuration (/proc/config.gz) and compressed
> ELF/BTF sections (via libbpf, libelf, and libbfd) processes data that
Is there any mechanism in place that prevents libbpf, libelf, and libbfd
to link to different versions of zlib (zlib vs zlib-rs, I mean)? I
imagine you could have bpftool linking against zlib-rs, but the libs
installed on the system linking against zlib? Also I think the static
build with the LLVM disassembler [0] passes -lz -lzstd in LIBS and I'm
not sure how it would combine with the change, I need to take a closer look.
> 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>
Recalling our discussion from v1:
>> Hi Ian, bpftool doesn't make an intensive use of zlib (mostly, it's a
>> requirement from other dependencies; we may also use it to unzip the
>> kernel config on the host if necessary for probing BPF features on the
>> system, but only on some distributions). So I'm struggling to understand
>> the motivation for your proposal, what do we gain by switching to
>> zlib-rs when available? I understand this implementation is in Rust, but
>> I'm not sure the added complexity and feature probing in the build
>> system is worth it.
>
> Hi Quentin,
>
> At my workplace, we are transitioning from zlib to zlib-rs for both
> security and performance reasons. I'd like to keep upstream tools
> aligned but they don't have to be, it just seems nice. I agree zlib is
> of a lower priority to users than, say, zstd. For attackers, like with
> brotli, it is probably an area of interest. Knowing the implementation
> is memory safe is at least something in favor of zlib-rs. I sent this
> series out as an RFC because I obviously have no way to mandate what
> upstream should or shouldn't be doing. There are things that can make
> life a little nicer and easier, and this patch series, for me, is one
> of them.
I understand you're transitioning to zlib-rs, but the current patch is
not a full transition, in the sense that it doesn't replace zlib with
zlib-rs but allows any of the two options; and I don't see support for
the standard zlib being removed from bpftool anytime soon, which means
that in practice, we've got to maintain compatibility with the two
versions going forward. Others may want to chime in, but I'm still not
convinced this is worth the burden.
You also mention zstd, do you plan to add support for a zstd alternative
as well in perf and bpftool in the future?
(By the way, if you allow me a short digression, you had a patch related
to the zstd probing for perf and bpftool [0] and I don't see in the
tree, do you know if it was ever merged?)
Best regards,
Quentin
[0]
https://github.com/libbpf/bpftool/blob/main/.github/workflows/static-build.yaml
[1] https://lore.kernel.org/all/20260909204122.1993010-4-irogers@google.com/
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-02 16:20 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 20:27 [RFC PATCH v2 0/3] tools: Add Rust library build infrastructure and prefer zlib-rs Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 1/3] tools build: Add Rust library build infrastructure and zlib-rs feature test Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 2/3] perf build: Prefer zlib-rs over zlib when available Ian Rogers
2026-10-30 20:27 ` [RFC PATCH v2 3/3] bpftool: " Ian Rogers
2026-11-02 16:20 ` Quentin Monnet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®