1{ lib
2, stdenv
3, fetchpatch
4, fetchurl
5, kernel
6, elfutils
7, python3
8, perl
9, newt
10, slang
11, asciidoc
12, xmlto
13, makeWrapper
14, docbook_xsl
15, docbook_xml_dtd_45
16, libxslt
17, flex
18, bison
19, pkg-config
20, libunwind
21, binutils-unwrapped
22, libiberty
23, audit
24, libbfd
25, libbfd_2_38
26, libopcodes
27, libopcodes_2_38
28, libpfm
29, libtraceevent
30, openssl
31, systemtap
32, numactl
33, zlib
34, babeltrace
35, withGtk ? false
36, gtk2
37, withZstd ? true
38, zstd
39, withLibcap ? true
40, libcap
41}:
42let
43 d3-flame-graph-templates = stdenv.mkDerivation rec {
44 pname = "d3-flame-graph-templates";
45 version = "4.1.3";
46
47 src = fetchurl {
48 url = "https://registry.npmjs.org/d3-flame-graph/-/d3-flame-graph-${version}.tgz";
49 sha256 = "sha256-W5/Vh5jarXUV224aIiTB2TnBFYT3naEIcG2945QjY8Q=";
50 };
51
52 installPhase = ''
53 install -D -m 0755 -t $out/share/d3-flame-graph/ ./dist/templates/*
54 '';
55 };
56in
57
58stdenv.mkDerivation {
59 pname = "perf-linux";
60 version = kernel.version;
61
62 inherit (kernel) src;
63
64 postPatch = ''
65 # Linux scripts
66 patchShebangs scripts
67 patchShebangs tools/perf/check-headers.sh
68 '' + lib.optionalString (lib.versionAtLeast kernel.version "6.3") ''
69 # perf-specific scripts
70 patchShebangs tools/perf/pmu-events
71 '' + ''
72 cd tools/perf
73
74 for x in util/build-id.c util/dso.c; do
75 substituteInPlace $x --replace /usr/lib/debug /run/current-system/sw/lib/debug
76 done
77
78 '' + lib.optionalString (lib.versionAtLeast kernel.version "5.8") ''
79 substituteInPlace scripts/python/flamegraph.py \
80 --replace "/usr/share/d3-flame-graph/d3-flamegraph-base.html" \
81 "${d3-flame-graph-templates}/share/d3-flame-graph/d3-flamegraph-base.html"
82
83 '' + lib.optionalString (lib.versionAtLeast kernel.version "6.0") ''
84 patchShebangs pmu-events/jevents.py
85 '';
86
87 makeFlags = [ "prefix=$(out)" "WERROR=0" "ASCIIDOC8=1" ] ++ kernel.makeFlags
88 ++ lib.optional (!withGtk) "NO_GTK2=1"
89 ++ lib.optional (!withZstd) "NO_LIBZSTD=1"
90 ++ lib.optional (!withLibcap) "NO_LIBCAP=1";
91
92 hardeningDisable = [ "format" ];
93
94 # perf refers both to newt and slang
95 nativeBuildInputs = [
96 asciidoc
97 xmlto
98 docbook_xsl
99 docbook_xml_dtd_45
100 libxslt
101 flex
102 bison
103 libiberty
104 audit
105 makeWrapper
106 pkg-config
107 python3
108 ];
109
110 buildInputs = [
111 elfutils
112 newt
113 slang
114 libtraceevent
115 libunwind
116 zlib
117 openssl
118 numactl
119 python3
120 perl
121 babeltrace
122 ] ++ (if (lib.versionAtLeast kernel.version "5.19")
123 then [ libbfd libopcodes ]
124 else [ libbfd_2_38 libopcodes_2_38 ])
125 ++ lib.optional (lib.meta.availableOn stdenv.hostPlatform systemtap) systemtap.stapBuild
126 ++ lib.optional withGtk gtk2
127 ++ lib.optional withZstd zstd
128 ++ lib.optional withLibcap libcap
129 ++ lib.optional (lib.versionAtLeast kernel.version "5.8") libpfm
130 ++ lib.optional (lib.versionAtLeast kernel.version "6.0") python3.pkgs.setuptools;
131
132 env.NIX_CFLAGS_COMPILE = toString ([
133 "-Wno-error=cpp"
134 "-Wno-error=bool-compare"
135 "-Wno-error=deprecated-declarations"
136 "-Wno-error=stringop-truncation"
137 ] ++ lib.optionals (stdenv.cc.isGNU && lib.versions.major stdenv.cc.version == "13") [
138 # Workaround gcc bug that causes enev simplest `perf top` runs to
139 # crash: https://gcc.gnu.org/PR111009.
140 # Can be removed once gcc-13 is updated past 13.2.0.
141 "-O1"
142 ]);
143
144 doCheck = false; # requires "sparse"
145
146 installTargets = [ "install" "install-man" ];
147
148 # TODO: Add completions based on perf-completion.sh
149 postInstall = ''
150 # Same as perf. Remove.
151 rm -f $out/bin/trace
152 '';
153
154 separateDebugInfo = true;
155
156 preFixup = ''
157 # Pull in 'objdump' into PATH to make annotations work.
158 # The embedded Python interpreter will search PATH to calculate the Python path configuration(Should be fixed by upstream).
159 # Add python.interpreter to PATH for now.
160 wrapProgram $out/bin/perf \
161 --prefix PATH : ${lib.makeBinPath [ binutils-unwrapped python3 ]}
162 '';
163
164 meta = with lib; {
165 homepage = "https://perf.wiki.kernel.org/";
166 description = "Linux tools to profile with performance counters";
167 mainProgram = "perf";
168 maintainers = with maintainers; [ viric ];
169 platforms = platforms.linux;
170 broken = kernel.kernelOlder "5";
171 };
172}