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