1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# No 'set -e': the script uses explicit checks for its error paths, and 5# is also run via '$(SHELL) .../install-build-deps.sh' from the make 6# target in tools/perf/Makefile.perf, where a shebang option would be 7# ignored anyway, so direct and make-driven runs behave the same. 8# 9# Install the development packages needed to build tools/perf. 10# 11# The package set is derived from the feature tests in tools/build/feature/: 12# each feature test that perf may compile is mapped to the devel package 13# that provides the headers/libraries it checks, so that a subsequent 14# 'make -C tools/perf' build enables the corresponding perf features. 15# 16# This initial version installs the base toolchain needed by any build; 17# the per-feature package mapping is added, per supported distro, by the 18# follow-up patches in this series, which also validate each mapping in a 19# fresh container, so the host system is not modified. 20# 21# Usage: install-build-deps.sh [OPTIONS] 22# 23# Options: 24# --list list the packages that would be installed, then exit 25# --dry-run show the install command that would be run, without 26# running it 27# --distro ID force a distro: fedora, ubuntu (default: auto-detect) 28# -h, --help print this help message 29# 30# Requires root (or passwordless sudo) to actually install packages. 31 32set -u 33 34DISTRO="" 35 36help() { 37 cat <<EOF 38Usage: $(basename "$0") [--list] [--dry-run] [--distro ID] [-h|--help] 39 40Install the development packages needed to build tools/perf. 41 42Options: 43 --list list the packages that would be installed, then exit 44 --dry-run show the install command that would be run, without running it 45 --distro ID force a distro: fedora, ubuntu 46 -h, --help print this help message 47EOF 48 exit 0 49} 50 51# --------------------------------------------------------------------- 52# Distro detection. The install command that follows only differs in 53# the package manager, which here is keyed off the distro ID; the 54# per-feature package mapping is added per distro by the follow-up 55# patches. 56# --------------------------------------------------------------------- 57detect_distro() { 58 if [ -n "$DISTRO" ]; then 59 echo "$DISTRO" 60 return 61 fi 62 local id 63 id=$( . /etc/os-release 2>/dev/null && echo "${ID:-}" ) 64 case "$id" in 65 fedora) echo "fedora" ;; 66 ubuntu) echo "ubuntu" ;; 67 # RHEL and its derivatives share most Fedora package names, but the 68 # mapping is only validated on Fedora, so don't auto-detect them. 69 rhel|centos|rocky|alma|ol) echo "" ;; 70 *) echo "" ;; 71 esac 72} 73 74# Base packages needed by any perf build, regardless of feature tests: 75# compiler, libc headers, flex/bison for the parser, kernel headers 76# for UAPI headers with no in-tree copy, e.g. <linux/capability.h>, and 77# gcc-c++ (dnf) / g++ (apt) for the C++-based feature tests 78# (cxa-demangle, llvm, llvm-perf), compiled with $(CXX), and 79# pulls in libstdc++-devel / libstdc++-*-dev. 80# python3-setuptools is needed to build the python binding (perf's 81# util/setup.py uses it; without it binding is skipped with a warning). 82# rust is not a header-based feature test: test-rust.bin just checks 83# "$(RUSTC) --version" (tools/build/feature/Makefile), so it is mapped 84# here like the other toolchain packages. 85fedora_base_pkgs="gcc gcc-c++ make flex bison glibc-devel kernel-headers python3-setuptools rust" 86debian_base_pkgs="gcc g++ make flex bison libc6-dev linux-libc-dev python3-setuptools rustc" 87 88# --------------------------------------------------------------------- 89# Assemble the unique package list. While the per-feature mapping is 90# being added per distro, only the base toolchain above is installed. 91# --------------------------------------------------------------------- 92package_set() { 93 local distro="$1" srcdir="$2" 94 case "$distro" in 95 fedora) echo "$fedora_base_pkgs" ;; 96 ubuntu) echo "$debian_base_pkgs" ;; 97 esac 98} 99 100# --------------------------------------------------------------------- 101# The install command proper for each supported package manager, plus 102# the command massaged for --dry-run. 103# --------------------------------------------------------------------- 104install_cmd() { 105 local distro="$1"; shift 106 case "$distro" in 107 fedora) 108 echo "dnf install -y $*" 109 ;; 110 ubuntu) 111 # a fresh container has no package index, so update first. 112 echo "apt-get update && apt-get install -y $*" 113 ;; 114 esac 115} 116 117main() { 118 local action="install" 119 local srcdir distro pkgs cmd 120 121 while [ $# -gt 0 ]; do 122 case "$1" in 123 --list) action="list"; shift ;; 124 --dry-run) action="dry-run"; shift ;; 125 --distro) 126 [ $# -ge 2 ] || { 127 echo "error: --distro requires an argument (fedora, rhel, ubuntu, debian)" >&2 128 exit 1 129 } 130 DISTRO="$2"; shift 2 ;; 131 -h|--help) help ;; 132 *) echo "error: unknown argument: $1" >&2; exit 1 ;; 133 esac 134 done 135 136 srcdir=$(cd "$(dirname "$0")/../../.." && pwd) 137 distro=$(detect_distro) 138 case "$distro" in 139 fedora|ubuntu) ;; 140 *) 141 echo "error: unsupported distro (got '$distro'); the package mapping is not validated on other distros." >&2 142 exit 1 143 ;; 144 esac 145 146 pkgs=$(package_set "$distro" "$srcdir") 147 148 case "$action" in 149 list) 150 echo "$pkgs" | tr ' ' '\n' | grep -v '^$' | sort 151 exit 0 152 ;; 153 dry-run) 154 install_cmd "$distro" $pkgs 155 exit 0 156 ;; 157 esac 158 159 echo "The following packages will be installed to enable perf features:" 160 echo "$pkgs" | tr ' ' '\n' | grep -v '^$' | sort | sed 's/^/ /' 161 echo 162 cmd=$(install_cmd "$distro" $pkgs) 163 if [ "$(id -u)" -eq 0 ]; then 164 sh -c "$cmd" 165 else 166 sudo sh -c "$cmd" 167 fi || { 168 echo "error: the install command failed, see the output above" >&2 169 exit 1 170 } 171} 172 173main "$@"