summaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts/install-build-deps.sh
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-02 12:17:24 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-02 12:17:24 -0700
commit3f1fe48a36b0b6722dc3fd421d93512bac138e9a (patch)
treeb767d7f6e26bc64334d3f14f8422d187239dc45d /tools/perf/scripts/install-build-deps.sh
downloadlinux-stable-3f1fe48a36b0b6722dc3fd421d93512bac138e9a.tar.gz
linux-stable-3f1fe48a36b0b6722dc3fd421d93512bac138e9a.zip
Merge tag 'io_uring-7.3-20261002' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linuxgrafted
Pull io_uring fixes from Jens Axboe: - Fix a task_work add use-after-free with SQPOLL. The sqpoll thread could pop and complete the last request while io_req_normal_work_add() was still looking at them after the mpscq push. Use the same approach as DEFER_TASKRUN to protect from that, holding an RCU read lock across the add, and have exit wait for an RCU grace period for SQPOLL rings as well. - CQE32 ring fixes: correct the free entry check for 32b CQEs, zero the big_cqe for aux CQEs, and only post the dummy skip CQE on CQE_MIXED rings - Mark the source filter table as COW when cloning bpf filters, so registering another filter on the source doesn't modify the shared table in place - Initialize the task context before running the BPF loop - Requeue zcrx multishot receives stopped by a local resource - End a TX_TIMESTAMP multishot cmd when the CQ is full (lollipopkit) * tag 'io_uring-7.3-20261002' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux: io_uring: fix task_work add use-after-free with SQPOLL io_uring/cmd_net: end TX_TIMESTAMP multishot when the CQ is full io_uring/zcrx: requeue multishot receives stopped by a local resource io_uring: initialize task context before running the BPF loop io_uring: zero big_cqe for aux CQEs on CQE32 rings io_uring: fix free entry check for 32b CQEs on CQE32 rings io_uring: only post the dummy skip CQE on CQE_MIXED rings io_uring/bpf_filter: mark source as COW when cloning filters
Diffstat (limited to 'tools/perf/scripts/install-build-deps.sh')
-rwxr-xr-xtools/perf/scripts/install-build-deps.sh603
1 files changed, 603 insertions, 0 deletions
diff --git a/tools/perf/scripts/install-build-deps.sh b/tools/perf/scripts/install-build-deps.sh
new file mode 100755
index 000000000..d003e7fab
--- /dev/null
+++ b/tools/perf/scripts/install-build-deps.sh
@@ -0,0 +1,603 @@
+#!/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.
+#
+# Currently supported distros, each validated in a fresh container:
+#
+# - Fedora, on dnf, validated on Fedora 44, in a toolbx container:
+#
+# toolbox create fedora:44
+# toolbox enter fedora:44
+#
+# - Ubuntu, on apt-get, validated on Ubuntu 26.04, in a distrobox
+# container:
+#
+# distrobox create --image ubuntu:26.04
+# distrobox enter ubuntu-26-04
+#
+# The apt-get install runs with a noninteractive debconf frontend:
+# default-jdk, needed by the jvmti feature tests, pulls in tzdata,
+# which prompts for the timezone on a terminal and would block the
+# install, e.g. in a container shared with an interactive session.
+#
+# - Debian, on apt-get, reusing the Ubuntu mapping, validated on
+# Debian 13 (trixie), in a distrobox container:
+#
+# distrobox create --image debian:trixie
+# distrobox enter debian-trixie
+#
+# - RHEL and its variants (RHEL, CentOS Stream, Rocky Linux, AlmaLinux,
+# Oracle Linux), on dnf (RHEL 8 and later), validated on CentOS
+# Stream 10, in a distrobox container:
+#
+# distrobox create --image quay.io/centos/centos:stream10
+# distrobox enter centos-stream10
+#
+# The RHEL family reuses most Fedora package names, with these
+# differences, handled by probing the enabled repos:
+#
+# - zlib.h comes from zlib-ng-compat-devel on the RHEL 10 family,
+# zlib-devel on RHEL 9 and earlier;
+# - the JDK devel package is versioned, there is no
+# java-latest-openjdk-devel: java-21-openjdk-devel on the RHEL
+# 10 family, java-17-openjdk-devel on RHEL 9, java-11-openjdk-
+# devel on RHEL 8;
+# - libbpf-devel and capstone-devel are in the CRB repo on RHEL
+# and CentOS Stream 10 ('dnf config-manager --set-enabled crb')
+# and in EPEL on RHEL 9 and earlier;
+# - libbabeltrace2-devel is not packaged on the RHEL 10 family.
+#
+# On the RHEL family, packages not available on the enabled repos
+# are skipped and listed at the end of the run, so that a distro
+# with CRB/EPEL enabled gets the full set, and a distro without
+# them still installs what it can.
+#
+# Running inside a container keeps the host system unmodified.
+#
+# 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, rhel, ubuntu, debian
+# (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.
+
+The package set is derived from the feature tests in tools/build/feature/,
+mapping each one with an external dependency to the devel package providing
+it, so the corresponding feature gets enabled on a build.
+
+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, rhel, ubuntu, debian
+ -h, --help print this help message
+
+Distros supported: Fedora (dnf), validated in a toolbx container on
+Fedora 44, Ubuntu (apt-get), validated in a distrobox container on
+Ubuntu 26.04, Debian (apt-get), reusing the Ubuntu mapping, validated
+in a distrobox container on Debian 13 (trixie), and the RHEL family
+(dnf, RHEL 8 and later), validated on CentOS Stream 10 in a distrobox
+container. On the RHEL family, packages not available on the enabled
+repos are skipped and listed at the end; some there, e.g.
+libbpf-devel and capstone-devel, come from the CRB repo on RHEL and
+CentOS Stream 10 ('dnf config-manager --set-enabled crb') and from
+EPEL on RHEL 9 and earlier.
+EOF
+ exit 0
+}
+
+# ---------------------------------------------------------------------
+# Return the Fedora package(s) providing the devel requirements of a
+# feature test in tools/build/feature/. Multiple packages are separated
+# by spaces; an empty result means the test has no external devel
+# dependency (pure toolchain/glibc, or no equivalent Fedora package).
+#
+# The mapping was built by checking, for each feature test, which Fedora
+# devel package provides the headers the test compiles against.
+# ---------------------------------------------------------------------
+fedora_pkg_for() {
+ local feat="$1"
+ case "$feat" in
+ libelf|libelf-getphdrnum|libelf-gelf_getnote|libelf-getshdrstrndx)
+ echo "elfutils-libelf-devel"
+ ;;
+ libelf-zstd)
+ echo "elfutils-libelf-devel libzstd-devel"
+ ;;
+ libdw)
+ echo "elfutils-devel"
+ ;;
+ # test-libdebuginfod.c includes <elfutils/debuginfod.h>, which is
+ # provided by elfutils-debuginfod-client-devel, not elfutils-devel.
+ libdebuginfod)
+ echo "elfutils-debuginfod-client-devel"
+ ;;
+ libnuma|numa_num_possible_cpus)
+ echo "numactl-devel"
+ ;;
+ libzstd)
+ echo "libzstd-devel"
+ ;;
+ zlib)
+ echo "zlib-devel"
+ ;;
+ lzma)
+ echo "xz-devel"
+ ;;
+ libslang)
+ echo "slang-devel"
+ ;;
+ libcapstone)
+ echo "capstone-devel"
+ ;;
+ libpython)
+ echo "python3-devel"
+ ;;
+ libtraceevent)
+ echo "libtraceevent-devel"
+ ;;
+ cxa-demangle)
+ echo "libstdc++-devel"
+ ;;
+ libbpf)
+ echo "libbpf-devel"
+ ;;
+ babeltrace2-ctf-writer)
+ echo "libbabeltrace2-devel"
+ ;;
+ libopenssl)
+ echo "openssl-devel"
+ ;;
+ libpfm4)
+ echo "libpfm-devel"
+ ;;
+ sdt)
+ echo "systemtap-sdt-devel"
+ ;;
+ clang-bpf-co-re)
+ echo "clang-devel"
+ ;;
+ llvm|llvm-perf)
+ echo "llvm-devel"
+ ;;
+ jvmti|jvmti-cmlr)
+ echo "java-latest-openjdk-devel"
+ ;;
+ esac
+ # Pure toolchain/libc features (backtrace, eventfd, fortify-source,
+ # gettid, glibc, hello, reallocarray, pthread-*, stackprotector-all,
+ # timerfd, scandirat, sched_getcpu, setns, file-handle,
+ # bionic...) need no external package: their
+ # requirements are covered by the base packages below. Features that
+ # perf's own build does not check (libcap, libcheck, libcpupower,
+ # libtracefs, whose feature tests exist for rtla/bpftool/rv) and the
+ # opt-in features, which a default build does not enable: the libbfd
+ # disassembler family (libbfd, libbfd-threadsafe, libbfd-liberty,
+ # disassembler-*, cplus-demangle), only linked on BUILD_NONDISTRO
+ # builds and deprecated in favor of capstone, GTK2, LIBPERL and
+ # LIBUNWIND support (ifdef GTK2 / ifdef LIBPERL / LIBUNWIND=1),
+ # and CoreSight (ifdef CORESIGHT), are deliberately not mapped.
+ # libaio is not mapped either: its
+ # test uses the POSIX AIO API (aio.h, aio_*, -lrt), provided by
+ # glibc headers (pulled in by the libc headers package) in the
+ # base set, not the native libaio.h/io_submit API that
+ # libaio-devel provides.
+}
+
+# ---------------------------------------------------------------------
+# Check whether the first argument is provided by the enabled repos, or
+# is already installed, returning 0 if so and printing nothing.
+#
+# dnf repoquery exits 0 even when the pattern does not match anything,
+# so availability is judged by the output being non-empty, not by the
+# exit code.
+# ---------------------------------------------------------------------
+pkg_available() {
+ local p out
+ for p in "$@"; do
+ out=$(dnf repoquery --quiet --available "$p" 2>/dev/null)
+ [ -n "$out" ] || out=$(dnf repoquery --quiet --installed "$p" 2>/dev/null)
+ [ -n "$out" ] && return 0
+ done
+ return 1
+}
+
+# ---------------------------------------------------------------------
+# Return the first of its arguments that pkg_available() accepts.
+# ---------------------------------------------------------------------
+pick_available() {
+ local p
+ for p in "$@"; do
+ if pkg_available "$p"; then
+ echo "$p"
+ return 0
+ fi
+ done
+ return 1
+}
+
+# ---------------------------------------------------------------------
+# Return the RHEL-family package(s) providing the devel requirements of
+# a feature test. This family reuses the Fedora mapping, whose names
+# apply to it as well, except for the features whose Fedora package
+# does not exist there, kept in the case below.
+#
+# Whether the resulting package is actually installable is checked in
+# package_set(), as some of these names live in the CRB or EPEL repos,
+# which may not be enabled: on the RHEL 10 family libbpf-devel and
+# capstone-devel come from CRB, and libbabeltrace2-devel is not
+# packaged at all.
+# ---------------------------------------------------------------------
+rhel_pkg_for() {
+ local feat="$1"
+ case "$feat" in
+ zlib)
+ # zlib-ng-compat-devel on the RHEL 10 family, zlib-devel on
+ # RHEL 9 and earlier. If neither is on the enabled repos,
+ # fall back to the first candidate so that package_set()
+ # reports it as missing instead of silently dropping the
+ # feature from the end-of-run note.
+ pick_available zlib-devel zlib-ng-compat-devel || echo "zlib-devel"
+ ;;
+ jvmti|jvmti-cmlr)
+ # No java-latest-openjdk-devel on the RHEL family: the JDK
+ # devel package is versioned per release.
+ pick_available java-latest-openjdk-devel java-21-openjdk-devel java-17-openjdk-devel java-11-openjdk-devel || echo "java-latest-openjdk-devel"
+ ;;
+ *)
+ fedora_pkg_for "$feat"
+ ;;
+ esac
+}
+
+# ---------------------------------------------------------------------
+# Return the Debian/Ubuntu package(s) providing the devel requirements
+# of a feature test in tools/build/feature/. This mapping is shared by
+# Debian and Ubuntu, whose package names for these devel packages match,
+# and is validated on Ubuntu 26.04 and Debian 13 (trixie).
+# ---------------------------------------------------------------------
+debian_pkg_for() {
+ local feat="$1"
+ case "$feat" in
+ libelf|libelf-getphdrnum|libelf-gelf_getnote|libelf-getshdrstrndx)
+ echo "libelf-dev"
+ ;;
+ libelf-zstd)
+ echo "libelf-dev libzstd-dev"
+ ;;
+ libdw)
+ echo "libdw-dev"
+ ;;
+ libdebuginfod)
+ echo "libdebuginfod-dev"
+ ;;
+ libnuma|numa_num_possible_cpus)
+ echo "libnuma-dev"
+ ;;
+ libzstd)
+ echo "libzstd-dev"
+ ;;
+ zlib)
+ echo "zlib1g-dev"
+ ;;
+ lzma)
+ echo "liblzma-dev"
+ ;;
+ libslang)
+ echo "libslang2-dev"
+ ;;
+ libcapstone)
+ echo "libcapstone-dev"
+ ;;
+ libpython)
+ echo "python3-dev"
+ ;;
+ libtraceevent)
+ echo "libtraceevent-dev"
+ ;;
+ # The cxa-demangle feature test links against libstdc++ builtin
+ # demangling, so on Debian-derived distros it is covered by the
+ # g++ base package below, which pulls in libstdc++-*-dev.
+ cxa-demangle)
+ ;;
+ libbpf)
+ echo "libbpf-dev"
+ ;;
+ babeltrace2-ctf-writer)
+ echo "libbabeltrace2-dev"
+ ;;
+ libopenssl)
+ echo "libssl-dev"
+ ;;
+ libpfm4)
+ echo "libpfm4-dev"
+ ;;
+ sdt)
+ echo "systemtap-sdt-dev"
+ ;;
+ # test-clang-bpf-co-re.c invokes the clang binary (not libclang-cpp),
+ # so clang suffices; llvm-dev brings llvm-config, needed by the
+ # llvm/llvm-perf tests below.
+ clang-bpf-co-re)
+ echo "clang llvm-dev"
+ ;;
+ llvm|llvm-perf)
+ echo "llvm-dev"
+ ;;
+ jvmti|jvmti-cmlr)
+ echo "default-jdk"
+ ;;
+ esac
+ # Same rationale as in fedora_pkg_for() above for unmapped tests.
+}
+
+# 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) is needed by 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"
+# pkg-config mirrors the pkgconf-pkg-config package that Fedora
+# installs by default, needed by the babeltrace2 feature test and
+# libopenssl's pkg-config checks.
+debian_base_pkgs="gcc g++ make pkg-config flex bison libc6-dev linux-libc-dev python3-setuptools rustc"
+# pkg-config: like Fedora, on pkgconf since Fedora 26 / RHEL 8, with
+# 'pkgconfig' live only as a virtual Provides of the pkgconf-pkg-config
+# subpackage. List it explicitly because, unlike Fedora, a minimal
+# RHEL-family container may not have it preinstalled.
+rhel_base_pkgs="gcc gcc-c++ make flex bison glibc-devel kernel-headers pkgconf-pkg-config python3-setuptools rust"
+
+# ---------------------------------------------------------------------
+# Distro detection
+# ---------------------------------------------------------------------
+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" ;;
+ rhel|centos|rocky|almalinux|ol)
+ # All share the Fedora package names (with the exceptions
+ # handled by rhel_pkg_for()) and dnf.
+ echo "rhel" ;;
+ ubuntu) echo "ubuntu" ;;
+ debian) echo "debian" ;;
+ *) echo "" ;;
+ esac
+}
+
+# ---------------------------------------------------------------------
+# Feature test enumeration: mirror of the tests checked during a build,
+# from the actual test-*.c / test-*.cpp sources in tools/build/feature/.
+# ---------------------------------------------------------------------
+feature_tests() {
+ local srcdir="$1"
+ local f
+ for f in "$srcdir"/tools/build/feature/test-*.c "$srcdir"/tools/build/feature/test-*.cpp; do
+ [ -e "$f" ] || continue
+ basename "$f" | sed -e 's/^test-//' -e 's/\.c$//' -e 's/\.cpp$//'
+ done
+}
+
+# ---------------------------------------------------------------------
+# Assemble the unique package list. Since the full feature set is mapped
+# unconditionally, this installs the complete devel environment; installing
+# an already-present package is a no-op for both dnf and apt-get, making
+# this idempotent. On the RHEL family, packages not available on the
+# enabled repos are skipped and echoed on stderr, reported at the end of
+# the run by the caller (package_set() runs in a subshell, so a variable
+# would not survive it).
+# ---------------------------------------------------------------------
+package_set() {
+ local distro="$1" srcdir="$2"
+ local feat pkg pkgs base_pkgs missing_pkgs=""
+ case "$distro" in
+ fedora) pkgs="$fedora_base_pkgs" ;;
+ rhel) pkgs="$rhel_base_pkgs" ;;
+ ubuntu|debian) pkgs="$debian_base_pkgs" ;;
+ esac
+
+ # The base set must be checked against the enabled repos as well:
+ # e.g. 'rust' is only shipped as the rust-toolset AppStream module
+ # on RHEL 8 and 9, where dnf would abort the whole transaction
+ # with "No match for argument: rust" instead of skipping it, so
+ # unavailable base packages are skipped and noted like the mapped
+ # ones below.
+ if [ "$distro" = "rhel" ]; then
+ base_pkgs="$pkgs"
+ pkgs=""
+ for pkg in $base_pkgs; do
+ if pkg_available "$pkg"; then
+ pkgs="$pkgs $pkg"
+ else
+ missing_pkgs="$missing_pkgs $pkg"
+ fi
+ done
+ fi
+
+ for feat in $(feature_tests "$srcdir"); do
+ case "$distro" in
+ fedora) pkg=$(fedora_pkg_for "$feat") ;;
+ rhel) pkg=$(rhel_pkg_for "$feat") ;;
+ *) pkg=$(debian_pkg_for "$feat") ;;
+ esac
+ # An empty result means the feature test has no external devel
+ # dependency (see the unmapped list in fedora_pkg_for()), so
+ # there is nothing to install and nothing to report as missing:
+ # packages that are genuinely unavailable on the RHEL family
+ # surface through rhel_pkg_for() falling back to its first
+ # candidate, so that the pkg_available() check below catches
+ # them and adds them to missing_pkgs.
+ [ -n "$pkg" ] || continue
+ for pkg in $pkg; do
+ if [ "$distro" = "rhel" ] && ! pkg_available "$pkg"; then
+ missing_pkgs="$missing_pkgs $pkg"
+ continue
+ fi
+ case " $pkgs " in
+ *" $pkg "*) ;;
+ *) pkgs="$pkgs $pkg" ;;
+ esac
+ done
+ done
+ [ -n "$missing_pkgs" ] && echo "$missing_pkgs" >&2
+ echo "$pkgs"
+}
+
+# ---------------------------------------------------------------------
+# Report the RHEL-family packages that were skipped because the enabled
+# repos do not provide them.
+# ---------------------------------------------------------------------
+note_missing() {
+ [ -n "$1" ] || return 0
+ echo "Note: these packages are not available on the enabled repos" >&2
+ echo "and were not installed, so the features they enable will stay" >&2
+ echo "off in a perf build:" >&2
+ echo "$1" | tr ' ' '\n' | grep -v '^$' | sort -u | sed 's/^/ /' >&2
+ echo >&2
+}
+
+# ---------------------------------------------------------------------
+# 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|rhel)
+ echo "dnf install -y $*"
+ ;;
+ ubuntu|debian)
+ # a fresh container has no package index, so update first; run
+ # with a noninteractive debconf frontend: default-jdk, used by
+ # the jvmti feature tests, pulls in tzdata, which prompts for
+ # the timezone on a terminal and would block the install. The
+ # env var prefix works with the 'sh -c' invocation below, and
+ # shows up in --dry-run.
+ echo "DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y $*"
+ ;;
+ esac
+}
+
+main() {
+ local action="install"
+ # Package accumulation happens in package_set(), which, together
+ # with the *_pkg_for() helpers, declares the per-feature 'pkg'
+ # locals; main() holds no per-feature package state, just the
+ # distro-wide list assembled by package_set().
+ local srcdir distro pkgs cmd missing_file missing_pkgs
+
+ 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|rhel|ubuntu|debian) ;;
+ *)
+ echo "error: unsupported distro (got '$distro'); the package mapping is not validated on other distros." >&2
+ echo "Supported and validated: Fedora 44 (toolbx container), Ubuntu 26.04 and Debian 13 (distrobox containers), and CentOS Stream 10 (distrobox container)." >&2
+ exit 1
+ ;;
+ esac
+
+ # The RHEL family mapping probes the enabled repos with dnf
+ # repoquery and installs with dnf, so reject the yum-only members of
+ # the family (RHEL 7 and earlier, e.g. Oracle Linux 7) with a clear
+ # error instead of silently judging every package as unavailable.
+ if [ "$distro" = "rhel" ] && ! command -v dnf >/dev/null 2>&1; then
+ echo "error: dnf not found, the RHEL family package mapping requires dnf (RHEL 8 and later)." >&2
+ exit 1
+ fi
+
+ missing_file=$(mktemp) || {
+ echo "error: cannot create a temporary file (mktemp failed)" >&2
+ exit 1
+ }
+ # package_set() runs in a subshell, doing dnf repoquery loops that
+ # may be interrupted: a Ctrl-C during those loops hits these traps,
+ # turning SIGINT/SIGTERM into an exit that triggers the EXIT trap,
+ # removing the temp file, so the script terminates instead of
+ # resuming after the interrupted command, leaving no file behind.
+ trap 'rm -f "$missing_file"' EXIT
+ trap 'exit 1' INT TERM
+ pkgs=$(package_set "$distro" "$srcdir" 2>"$missing_file")
+ missing_pkgs=$(cat "$missing_file")
+ rm -f "$missing_file"
+ trap - EXIT INT TERM
+
+ case "$action" in
+ list)
+ echo "$pkgs" | tr ' ' '\n' | grep -v '^$' | sort
+ note_missing "$missing_pkgs"
+ exit 0
+ ;;
+ dry-run)
+ install_cmd "$distro" $pkgs
+ note_missing "$missing_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
+ }
+ note_missing "$missing_pkgs"
+}
+
+main "$@"