Add linux-perf
This commit is contained in:
		 Jordan Galby
					Jordan Galby
				
			
				
					committed by
					
						 Bernhard Kaindl
						Bernhard Kaindl
					
				
			
			
				
	
			
			
			 Bernhard Kaindl
						Bernhard Kaindl
					
				
			
						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") | ||||
		Reference in New Issue
	
	Block a user