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 --- 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