Add linux-perf
This commit is contained in:
parent
a2794f04bc
commit
6007a77a33
265
var/spack/repos/builtin/packages/linux-perf/package.py
Normal file
265
var/spack/repos/builtin/packages/linux-perf/package.py
Normal file
@ -0,0 +1,265 @@
|
||||
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os.path
|
||||
import re
|
||||
from textwrap import dedent
|
||||
|
||||
import llnl.util.tty as tty
|
||||
|
||||
from spack.package import *
|
||||
|
||||
|
||||
class LinuxPerf(Package):
|
||||
"""The Linux perf tool."""
|
||||
|
||||
homepage = "https://www.kernel.org/"
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.5.5.tar.xz"
|
||||
|
||||
executables = ["^perf$"]
|
||||
|
||||
maintainers("Jordan474")
|
||||
|
||||
version("6.9.10", sha256="efd12e335fa67d13a3eae30e4b7b7546e74b8ccc90682e4c3fffab0b22654da1")
|
||||
version("6.6.41", sha256="9ec99c578158ab85d99b37791a76643d2ea4c3f72ecbef7b5eb6d60f3de032ef")
|
||||
version("5.15.163", sha256="025fc7d8b1560cf456ccae50591fe1ca21c990645df9791aed25820fe78db302")
|
||||
|
||||
variant("libtraceevent", default=True, description="recommended dependency")
|
||||
variant("python", default=True, description="Python support")
|
||||
variant("perl", default=True, description="perl script extension")
|
||||
variant("slang", default=True, description="TUI support")
|
||||
variant("libpfm4", default=True, description="libpfm4 events extension")
|
||||
variant("babeltrace", default=True, description="libbabeltrace support for CTF data format")
|
||||
variant("libcap", default=True, description="process capabilities considered by perf")
|
||||
variant("numactl", default=True, description="numa perf benchmark")
|
||||
variant(
|
||||
"libaudit",
|
||||
default=False,
|
||||
description=(
|
||||
"get perf-trace syscall table from libaudit at runtime,"
|
||||
" rather than unistd.h at buildtime"
|
||||
),
|
||||
)
|
||||
variant("debuginfod", default=False, description="support debuginfod")
|
||||
variant(
|
||||
"zstd",
|
||||
default=True,
|
||||
description="Zstandard based runtime trace compression in record mode",
|
||||
)
|
||||
variant("xz", default=True, description="xz kernel module decompression")
|
||||
variant(
|
||||
"openssl",
|
||||
default=True,
|
||||
description="support generating build-ids for ELFs generated by jitdump",
|
||||
)
|
||||
variant("jvmti", default=False, description="build jvmti agent")
|
||||
|
||||
depends_on("gmake", type="build")
|
||||
depends_on("pkgconfig", type="build")
|
||||
depends_on("flex", type="build")
|
||||
depends_on("bison", type="build")
|
||||
|
||||
depends_on("elfutils")
|
||||
depends_on("elfutils +debuginfod", when="+debuginfod")
|
||||
depends_on("libunwind components=ptrace")
|
||||
depends_on("libiberty")
|
||||
depends_on("binutils", type=("build", "link", "run"))
|
||||
depends_on("zlib-api")
|
||||
|
||||
depends_on("libtraceevent", when="+libtraceevent")
|
||||
|
||||
# jevents requires python >= 3.6
|
||||
depends_on("python@3.6:", type=("build", "link", "run"), when="+python")
|
||||
depends_on("py-setuptools", type="build", when="+python")
|
||||
depends_on("perl", when="+perl")
|
||||
depends_on("slang", when="+slang")
|
||||
depends_on("libpfm4", when="+libpfm4")
|
||||
depends_on("babeltrace@1.5:", when="+babeltrace")
|
||||
depends_on("libcap", when="+libcap")
|
||||
depends_on("audit-userspace", when="+libaudit")
|
||||
depends_on("numactl", when="+numactl")
|
||||
depends_on("zstd", when="+zstd")
|
||||
depends_on("xz", when="+xz")
|
||||
depends_on("openssl", when="+openssl")
|
||||
depends_on("openssl@1.1:", when="@5.19: +openssl")
|
||||
depends_on("java", when="+jvmti")
|
||||
|
||||
depends_on("asciidoc", type="build")
|
||||
depends_on("xmlto", type="build")
|
||||
|
||||
conflicts(
|
||||
"~libtraceevent",
|
||||
when="@6.2:",
|
||||
msg="linux 6.2 removed internal libtraceevent, and it's highly recommended",
|
||||
)
|
||||
|
||||
def url_for_version(self, version):
|
||||
return f"https://cdn.kernel.org/pub/linux/kernel/v{version[0]}.x/linux-{version}.tar.xz"
|
||||
|
||||
def setup_build_environment(self, env):
|
||||
# This variable is used in the Makefile. If it is defined on the
|
||||
# system, it can break the build if there is no build recipe for
|
||||
# that specific ARCH
|
||||
env.unset("ARCH")
|
||||
|
||||
@property
|
||||
def archive_files(self):
|
||||
return [join_path(self.stage.source_path, "tools/perf/FEATURE-DUMP")]
|
||||
|
||||
def install(self, spec, prefix):
|
||||
# TODO:
|
||||
# - GTK2=
|
||||
# - NO_LIBBPF=1 ?
|
||||
# - d3 flamegraph resources (libexec/perf-core/scripts/python/flamegraph.py)
|
||||
|
||||
version = self.spec.version
|
||||
|
||||
args = [
|
||||
"LIBDW_DIR={}".format(spec["elfutils"].prefix),
|
||||
"LIBUNWIND_DIR={}".format(spec["libunwind"].prefix),
|
||||
"NO_SHELLCHECK=1",
|
||||
]
|
||||
# Features to check post-install against `perf version --build-options`
|
||||
checks = {"dwarf", "libunwind", "libbfd", "zlib"}
|
||||
|
||||
if version >= Version("6.4"):
|
||||
args.append("BUILD_NONDISTRO=1")
|
||||
|
||||
if "+libaudit" in spec:
|
||||
checks.add("libaudit")
|
||||
args.append("NO_SYSCALL_TABLE=1") # will look for libaudit
|
||||
else:
|
||||
checks.add("syscall_table")
|
||||
args.append("NO_LIBAUDIT=1")
|
||||
|
||||
if "+debuginfod" in spec:
|
||||
if version >= Version("5.19"): # Not in --build-options before that
|
||||
checks.add("debuginfod")
|
||||
else:
|
||||
args.append("NO_LIBDEBUGINFOD=1")
|
||||
|
||||
if "+python" in spec:
|
||||
checks.add("libpython")
|
||||
args.extend(
|
||||
[
|
||||
"PYTHON={}".format(spec["python"].command),
|
||||
"PYTHON_CONFIG={}".format(spec["python"].prefix.bin.join("python-config")),
|
||||
]
|
||||
)
|
||||
else:
|
||||
args.append("NO_LIBPYTHON=1")
|
||||
|
||||
if "+perl" in spec:
|
||||
checks.add("libperl")
|
||||
else:
|
||||
args.append("NO_LIBPERL=1")
|
||||
|
||||
if "+openssl" in spec:
|
||||
checks.add("libcrypto")
|
||||
else:
|
||||
args.append("NO_LIBCRYPTO=1")
|
||||
|
||||
if "+slang" in spec:
|
||||
checks.add("libslang")
|
||||
else:
|
||||
args.append("NO_SLANG=1")
|
||||
|
||||
if "+libpfm4" in spec:
|
||||
checks.add("libpfm4")
|
||||
if version < Version("6.4"):
|
||||
args.append("LIBPFM4=1")
|
||||
else:
|
||||
if version >= Version("6.4"):
|
||||
args.append("NO_LIBPFM4=1")
|
||||
|
||||
if "+babeltrace" in spec:
|
||||
# checks.add("babeltrace") # Not in --build-options ?
|
||||
args.append("LIBBABELTRACE_DIR={}".format(spec["babeltrace"].prefix))
|
||||
else:
|
||||
args.append("NO_LIBBABELTRACE=1")
|
||||
|
||||
if "+libcap" in spec:
|
||||
# checks.add("libcap") # Not in --build-options ?
|
||||
pass
|
||||
else:
|
||||
args.append("NO_LIBCAP=1")
|
||||
|
||||
if "+numactl" in spec:
|
||||
checks.add("libnuma")
|
||||
else:
|
||||
args.append("NO_LIBNUMA=1")
|
||||
|
||||
if "+xz" in spec:
|
||||
checks.add("lzma")
|
||||
else:
|
||||
args.append("NO_LZMA=1")
|
||||
|
||||
if "+zstd" in spec:
|
||||
checks.add("zstd")
|
||||
args.append("LIBZSTD_DIR={}".format(spec["zstd"].prefix))
|
||||
else:
|
||||
args.append("NO_LIBZSTD=1")
|
||||
|
||||
if "+libtraceevent" in spec:
|
||||
if version >= Version("6.2"): # Not in --build-options before that
|
||||
checks.add("libtraceevent")
|
||||
if version >= Version("6.10"):
|
||||
args.append("LIBTRACEEVENT_DIR={}".format(spec["libtraceevent"].prefix))
|
||||
if version < Version("6.2"):
|
||||
args.append("LIBTRACEEVENT_DYNAMIC=1")
|
||||
else:
|
||||
if version >= Version("6.2"):
|
||||
args.append("NO_LIBTRACEEVENT=1")
|
||||
|
||||
if "+jvmti" in spec:
|
||||
# checks.add("jvmti") # Not in --build-options ?
|
||||
args.append("JDIR={}".format(spec["java"].prefix))
|
||||
else:
|
||||
args.append("NO_JVMTI=1")
|
||||
|
||||
with working_dir("tools/perf"):
|
||||
make(
|
||||
"V=1",
|
||||
f"JOBS={make_jobs}",
|
||||
f"prefix={prefix}",
|
||||
"DESTDIR=",
|
||||
*args,
|
||||
"all",
|
||||
"install",
|
||||
parallel=False,
|
||||
)
|
||||
|
||||
# Create a perfconfig with binutils paths
|
||||
perfconfig = str(prefix.join("etc/perfconfig"))
|
||||
assert not os.path.exists(perfconfig)
|
||||
mkdirp(os.path.dirname(perfconfig))
|
||||
with open(perfconfig, "w") as f:
|
||||
f.write(
|
||||
dedent(
|
||||
"""\
|
||||
[annotate]
|
||||
addr2line = {addr2line}
|
||||
objdump = {objdump}
|
||||
"""
|
||||
).format(
|
||||
addr2line=spec["binutils"].prefix.bin.join("addr2line"),
|
||||
objdump=spec["binutils"].prefix.bin.join("objdump"),
|
||||
)
|
||||
)
|
||||
|
||||
# Post-install dependency check:
|
||||
# $ perf version --build-options
|
||||
# perf version 6.5.7
|
||||
# dwarf: [ on ] # HAVE_DWARF_SUPPORT
|
||||
# ...
|
||||
perf = Executable(self.prefix.bin.perf)
|
||||
output = perf("version", "--build-options", output=str, error=str)
|
||||
tty.msg(output) # keep a trace in build log
|
||||
enabled = set(re.findall(r"^\s*(\S+)\s*:\s*\[\s*on\s*\]", output, re.MULTILINE))
|
||||
missing = set(checks) - enabled
|
||||
tty.msg(f"detected features: {sorted(enabled)!r}")
|
||||
tty.msg(f"expected features: {sorted(checks)!r}")
|
||||
if missing:
|
||||
raise InstallError(f"Perf is missing features {sorted(missing)!r}, see log")
|
Loading…
Reference in New Issue
Block a user