summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Galby <jordan.galby@cea.fr>2024-07-23 08:44:49 +0200
committerBernhard Kaindl <bernhardkaindl7@gmail.com>2024-08-07 13:34:07 +0200
commit6007a77a33156d50999dcfa4d79dce912adf8871 (patch)
treeb5d7fc8ca402b69de3b1e78294965c7c8b93d502
parenta2794f04bccfd93bb145f4cbbceb927527dd428e (diff)
downloadspack-6007a77a33156d50999dcfa4d79dce912adf8871.tar.gz
spack-6007a77a33156d50999dcfa4d79dce912adf8871.tar.bz2
spack-6007a77a33156d50999dcfa4d79dce912adf8871.tar.xz
spack-6007a77a33156d50999dcfa4d79dce912adf8871.zip
Add linux-perf
-rw-r--r--var/spack/repos/builtin/packages/linux-perf/package.py265
1 files changed, 265 insertions, 0 deletions
diff --git a/var/spack/repos/builtin/packages/linux-perf/package.py b/var/spack/repos/builtin/packages/linux-perf/package.py
new file mode 100644
index 0000000000..afd94f988d
--- /dev/null
+++ b/var/spack/repos/builtin/packages/linux-perf/package.py
@@ -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")