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