1{ lib
2, stdenv
3, fetchurl
4, fetchpatch
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 # Fix 6.10.0 holding pkg-config completely wrong.
65 # Patches from perf-tools-next, should be in 6.11 or hopefully backported.
66 patches = lib.optionals (lib.versionAtLeast kernel.version "6.10") [
67 (fetchpatch {
68 url = "https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/patch/?id=0f0e1f44569061e3dc590cd0b8cb74d8fd53706b";
69 hash = "sha256-9u/zhbsDgwOr4T4k9td/WJYRuSHIfbtfS+oNx8nbOlM=";
70 })
71 (fetchpatch {
72 url = "https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/patch/?id=366e17409f1f17ad872259ce4a4f8a92beb4c4ee";
73 hash = "sha256-NZK1u40qvMwWcgkgJPGpEax2eMo9xHrCQxSYYOK0rbo=";
74 })
75 (fetchpatch {
76 url = "https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/patch/?id=1d302f626c2a23e4fd05bb810eff300e8f2174fd";
77 hash = "sha256-KhCmof8LkyTcBBpfMEtolL3m3kmC5rukKzQvufVKCdI=";
78 })
79 ];
80
81 postPatch = ''
82 # Linux scripts
83 patchShebangs scripts
84 patchShebangs tools/perf/check-headers.sh
85 '' + lib.optionalString (lib.versionAtLeast kernel.version "6.3") ''
86 # perf-specific scripts
87 patchShebangs tools/perf/pmu-events
88 '' + ''
89 cd tools/perf
90
91 for x in util/build-id.c util/dso.c; do
92 substituteInPlace $x --replace /usr/lib/debug /run/current-system/sw/lib/debug
93 done
94
95 '' + lib.optionalString (lib.versionAtLeast kernel.version "5.8") ''
96 substituteInPlace scripts/python/flamegraph.py \
97 --replace "/usr/share/d3-flame-graph/d3-flamegraph-base.html" \
98 "${d3-flame-graph-templates}/share/d3-flame-graph/d3-flamegraph-base.html"
99
100 '' + lib.optionalString (lib.versionAtLeast kernel.version "6.0") ''
101 patchShebangs pmu-events/jevents.py
102 '';
103
104 makeFlags = [ "prefix=$(out)" "WERROR=0" "ASCIIDOC8=1" ] ++ kernel.makeFlags
105 ++ lib.optional (!withGtk) "NO_GTK2=1"
106 ++ lib.optional (!withZstd) "NO_LIBZSTD=1"
107 ++ lib.optional (!withLibcap) "NO_LIBCAP=1";
108
109 hardeningDisable = [ "format" ];
110
111 # perf refers both to newt and slang
112 nativeBuildInputs = [
113 asciidoc
114 xmlto
115 docbook_xsl
116 docbook_xml_dtd_45
117 libxslt
118 flex
119 bison
120 libiberty
121 audit
122 makeWrapper
123 pkg-config
124 python3
125 ];
126
127 buildInputs = [
128 elfutils
129 newt
130 slang
131 libtraceevent
132 libunwind
133 zlib
134 openssl
135 numactl
136 python3
137 perl
138 babeltrace
139 ] ++ (if (lib.versionAtLeast kernel.version "5.19")
140 then [ libbfd libopcodes ]
141 else [ libbfd_2_38 libopcodes_2_38 ])
142 ++ lib.optional (lib.meta.availableOn stdenv.hostPlatform systemtap) systemtap.stapBuild
143 ++ lib.optional withGtk gtk2
144 ++ lib.optional withZstd zstd
145 ++ lib.optional withLibcap libcap
146 ++ lib.optional (lib.versionAtLeast kernel.version "5.8") libpfm
147 ++ lib.optional (lib.versionAtLeast kernel.version "6.0") python3.pkgs.setuptools;
148
149 env.NIX_CFLAGS_COMPILE = toString [
150 "-Wno-error=cpp"
151 "-Wno-error=bool-compare"
152 "-Wno-error=deprecated-declarations"
153 "-Wno-error=stringop-truncation"
154 ];
155
156 doCheck = false; # requires "sparse"
157
158 installTargets = [ "install" "install-man" ];
159
160 # TODO: Add completions based on perf-completion.sh
161 postInstall = ''
162 # Same as perf. Remove.
163 rm -f $out/bin/trace
164 '';
165
166 separateDebugInfo = true;
167
168 preFixup = ''
169 # Pull in 'objdump' into PATH to make annotations work.
170 # The embedded Python interpreter will search PATH to calculate the Python path configuration(Should be fixed by upstream).
171 # Add python.interpreter to PATH for now.
172 wrapProgram $out/bin/perf \
173 --prefix PATH : ${lib.makeBinPath [ binutils-unwrapped python3 ]}
174 '';
175
176 meta = with lib; {
177 homepage = "https://perf.wiki.kernel.org/";
178 description = "Linux tools to profile with performance counters";
179 mainProgram = "perf";
180 maintainers = with maintainers; [ viric ];
181 platforms = platforms.linux;
182 broken = kernel.kernelOlder "5";
183 };
184}