diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-08-11 15:28:55 -0300 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2026-08-12 06:17:48 -0700 |
| commit | bc3fdd6adb9903b1f1fd85cd9532c7bfc961dcbc (patch) | |
| tree | 391436895196aefccf418737d365ffaf0e061132 /tools/perf | |
| parent | 380e3f23bb9b394dba6fc8d6b5ef70cbd67f0081 (diff) | |
| download | linux-next-bc3fdd6adb9903b1f1fd85cd9532c7bfc961dcbc.tar.gz linux-next-bc3fdd6adb9903b1f1fd85cd9532c7bfc961dcbc.zip | |
perf build: Add install-build-deps framework to install devel packages
Installing the development packages needed to build perf is
error-prone on a fresh distro install: the packages are scattered
across the feature tests in tools/build/feature/, each checking for a
specific header/library, and the build only tells you what's missing
after failing a check.
This series adds a 'make -C tools/perf install-build-deps' target to
install them in one go, deriving the package list from the feature tests
themselves.
This commit adds the framework, on top of the parse-time compiler
probe guard from the previous commit:
- the install-build-deps target in tools/perf/Makefile.perf, exempted
from the config/feature detection pass, since it must run in a fresh
container, before gcc or pkg-config exist, to install them;
- the install-build-deps.sh script, with --list, --dry-run and
--distro options, distro detection (Fedora and Ubuntu), dnf and
apt-get drivers, root/passwordless-sudo handling, and the base
packages common to any build: compiler, C++ compiler, make, flex,
bison, libc and kernel headers, python3-setuptools (needed by the
python binding) and rust (checked by the rust feature test);
- the parse-time probes for optional tools, like pkg-config, use
'command -v' with stderr discarded, so a fresh container without
them gets no 'which: no pkg-config in (...)' spew from make;
- the script does not rely on 'set -e': its error paths are explicit,
since the make target runs it via $(SHELL), where a shebang option
would be ignored anyway, so direct and make-driven runs behave the
same.
The per-feature mappings, from each feature test to the devel package
providing its headers on a given distro, are added by the follow-up
patches, one per distro, together with the validation of each mapping
in a fresh container: until then the target installs just the base
toolchain.
Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/Makefile.perf | 20 | ||||
| -rwxr-xr-x | tools/perf/scripts/install-build-deps.sh | 173 |
2 files changed, 190 insertions, 3 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index acc6309a84a1..49a58d714e42 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -177,7 +177,7 @@ LD += $(EXTRA_LDFLAGS) # Some distros provide the command $(CROSS_COMPILE)pkg-config for # searching packges installed with Multiarch. Use it for cross # compilation if it is existed. -ifneq (, $(shell which $(CROSS_COMPILE)pkg-config)) +ifneq (, $(shell command -v $(CROSS_COMPILE)pkg-config 2>/dev/null)) PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config else PKG_CONFIG ?= pkg-config @@ -214,7 +214,12 @@ AWK = awk # non-config cases config := 1 -NON_CONFIG_TARGETS := clean python-clean TAGS tags cscope help +# install-build-deps runs the install-build-deps.sh script, which +# derives the package list from the feature test sources in +# tools/build/feature/, so it needs neither the fixdep build nor a +# config/feature detection pass: in a fresh container without gcc or +# pkg-config those would fail before the script could install them. +NON_CONFIG_TARGETS := clean python-clean TAGS tags cscope help install-build-deps ifdef MAKECMDGOALS ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) @@ -748,6 +753,7 @@ help: @echo ' HINT: use "prefix" or "DESTDIR" to install to a particular' @echo ' path like "make prefix=/usr/local install install-doc"' @echo ' install - install compiled binaries' + @echo ' install-build-deps - install the development packages needed to build' @echo ' install-doc - install *all* documentation' @echo ' install-man - install manpage documentation' @echo ' install-html - install html documentation' @@ -892,6 +898,14 @@ install-bin: install-tools install-tests install: install-bin try-install-man +# Install the development packages needed to build perf, derived from the +# feature tests in tools/build/feature/. This first installs just the +# base toolchain; per-distro package mappings are added by the follow-up +# commits. INSTALL_BUILD_DEPS_ARGS, when set, is passed to the script, so +# extra options like --list, --dry-run or --distro can be given from make. +install-build-deps: + $(Q)$(SHELL) $(srctree)/tools/perf/scripts/install-build-deps.sh $(INSTALL_BUILD_DEPS_ARGS) + install-python_ext: $(PYTHON_WORD) util/setup.py $(python_setup_quiet) install --root='/$(DESTDIR_SQ)' @@ -960,7 +974,7 @@ endif FORCE: -.PHONY: all install clean config-clean strip install-gtk +.PHONY: all install install-build-deps clean config-clean strip install-gtk .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope FORCE prepare bpf-skel-prepare .PHONY: python_perf_target diff --git a/tools/perf/scripts/install-build-deps.sh b/tools/perf/scripts/install-build-deps.sh new file mode 100755 index 000000000000..351fdd581e56 --- /dev/null +++ b/tools/perf/scripts/install-build-deps.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# No 'set -e': the script uses explicit checks for its error paths, and +# is also run via '$(SHELL) .../install-build-deps.sh' from the make +# target in tools/perf/Makefile.perf, where a shebang option would be +# ignored anyway, so direct and make-driven runs behave the same. +# +# Install the development packages needed to build tools/perf. +# +# The package set is derived from the feature tests in tools/build/feature/: +# each feature test that perf may compile is mapped to the devel package +# that provides the headers/libraries it checks, so that a subsequent +# 'make -C tools/perf' build enables the corresponding perf features. +# +# This initial version installs the base toolchain needed by any build; +# the per-feature package mapping is added, per supported distro, by the +# follow-up patches in this series, which also validate each mapping in a +# fresh container, so the host system is not modified. +# +# Usage: install-build-deps.sh [OPTIONS] +# +# Options: +# --list list the packages that would be installed, then exit +# --dry-run show the install command that would be run, without +# running it +# --distro ID force a distro: fedora, ubuntu (default: auto-detect) +# -h, --help print this help message +# +# Requires root (or passwordless sudo) to actually install packages. + +set -u + +DISTRO="" + +help() { + cat <<EOF +Usage: $(basename "$0") [--list] [--dry-run] [--distro ID] [-h|--help] + +Install the development packages needed to build tools/perf. + +Options: + --list list the packages that would be installed, then exit + --dry-run show the install command that would be run, without running it + --distro ID force a distro: fedora, ubuntu + -h, --help print this help message +EOF + exit 0 +} + +# --------------------------------------------------------------------- +# Distro detection. The install command that follows only differs in +# the package manager, which here is keyed off the distro ID; the +# per-feature package mapping is added per distro by the follow-up +# patches. +# --------------------------------------------------------------------- +detect_distro() { + if [ -n "$DISTRO" ]; then + echo "$DISTRO" + return + fi + local id + id=$( . /etc/os-release 2>/dev/null && echo "${ID:-}" ) + case "$id" in + fedora) echo "fedora" ;; + ubuntu) echo "ubuntu" ;; + # RHEL and its derivatives share most Fedora package names, but the + # mapping is only validated on Fedora, so don't auto-detect them. + rhel|centos|rocky|alma|ol) echo "" ;; + *) echo "" ;; + esac +} + +# Base packages needed by any perf build, regardless of feature tests: +# compiler, libc headers, flex/bison for the parser, kernel headers +# for UAPI headers with no in-tree copy, e.g. <linux/capability.h>, and +# gcc-c++ (dnf) / g++ (apt) for the C++-based feature tests +# (cxa-demangle, llvm, llvm-perf), compiled with $(CXX), and +# pulls in libstdc++-devel / libstdc++-*-dev. +# python3-setuptools is needed to build the python binding (perf's +# util/setup.py uses it; without it binding is skipped with a warning). +# rust is not a header-based feature test: test-rust.bin just checks +# "$(RUSTC) --version" (tools/build/feature/Makefile), so it is mapped +# here like the other toolchain packages. +fedora_base_pkgs="gcc gcc-c++ make flex bison glibc-devel kernel-headers python3-setuptools rust" +debian_base_pkgs="gcc g++ make flex bison libc6-dev linux-libc-dev python3-setuptools rustc" + +# --------------------------------------------------------------------- +# Assemble the unique package list. While the per-feature mapping is +# being added per distro, only the base toolchain above is installed. +# --------------------------------------------------------------------- +package_set() { + local distro="$1" srcdir="$2" + case "$distro" in + fedora) echo "$fedora_base_pkgs" ;; + ubuntu) echo "$debian_base_pkgs" ;; + esac +} + +# --------------------------------------------------------------------- +# The install command proper for each supported package manager, plus +# the command massaged for --dry-run. +# --------------------------------------------------------------------- +install_cmd() { + local distro="$1"; shift + case "$distro" in + fedora) + echo "dnf install -y $*" + ;; + ubuntu) + # a fresh container has no package index, so update first. + echo "apt-get update && apt-get install -y $*" + ;; + esac +} + +main() { + local action="install" + local srcdir distro pkgs cmd + + while [ $# -gt 0 ]; do + case "$1" in + --list) action="list"; shift ;; + --dry-run) action="dry-run"; shift ;; + --distro) + [ $# -ge 2 ] || { + echo "error: --distro requires an argument (fedora, rhel, ubuntu, debian)" >&2 + exit 1 + } + DISTRO="$2"; shift 2 ;; + -h|--help) help ;; + *) echo "error: unknown argument: $1" >&2; exit 1 ;; + esac + done + + srcdir=$(cd "$(dirname "$0")/../../.." && pwd) + distro=$(detect_distro) + case "$distro" in + fedora|ubuntu) ;; + *) + echo "error: unsupported distro (got '$distro'); the package mapping is not validated on other distros." >&2 + exit 1 + ;; + esac + + pkgs=$(package_set "$distro" "$srcdir") + + case "$action" in + list) + echo "$pkgs" | tr ' ' '\n' | grep -v '^$' | sort + exit 0 + ;; + dry-run) + install_cmd "$distro" $pkgs + exit 0 + ;; + esac + + echo "The following packages will be installed to enable perf features:" + echo "$pkgs" | tr ' ' '\n' | grep -v '^$' | sort | sed 's/^/ /' + echo + cmd=$(install_cmd "$distro" $pkgs) + if [ "$(id -u)" -eq 0 ]; then + sh -c "$cmd" + else + sudo sh -c "$cmd" + fi || { + echo "error: the install command failed, see the output above" >&2 + exit 1 + } +} + +main "$@"
\ No newline at end of file |
