1{ lib
2, stdenv
3, fetchurl
4, elfutils
5, xorg
6, patchelf
7, libxcb
8, libxshmfence
9, perl
10, zlib
11, expat
12, libffi
13, libselinux
14, libdrm
15, udev
16, kernel ? null
17}:
18
19with lib;
20
21let
22
23 bitness = if stdenv.is64bit then "64" else "32";
24
25 libArch =
26 if stdenv.hostPlatform.system == "i686-linux" then
27 "i386-linux-gnu"
28 else if stdenv.hostPlatform.system == "x86_64-linux" then
29 "x86_64-linux-gnu"
30 else throw "amdgpu-pro is Linux only. Sorry.";
31
32in stdenv.mkDerivation rec {
33
34 version = "21.30";
35 pname = "amdgpu-pro";
36 build = "${version}-1290604";
37
38 src = fetchurl {
39 url = "https://drivers.amd.com/drivers/linux/amdgpu-pro-${build}-ubuntu-20.04.tar.xz";
40 sha256 = "sha256-WECqxjo2WLP3kMWeVyJgYufkvHTzwGaj57yeMGXiQ4I=";
41 curlOpts = "--referer https://www.amd.com/en/support/kb/release-notes/rn-amdgpu-unified-linux-21-30";
42 };
43
44 postUnpack = ''
45 mkdir root
46 pushd $sourceRoot
47 for deb in *_all.deb *_${if stdenv.is64bit then "amd64" else "i386"}.deb
48 do
49 ar p $deb data.tar.xz | tar -C ../root -xJ
50 done
51 popd
52 # if we don't use a short sourceRoot, compilation can fail due to command
53 # line length
54 sourceRoot=root
55 '';
56
57 passthru = optionalAttrs (kernel != null) {
58 kmod = stdenv.mkDerivation rec {
59 inherit version src postUnpack;
60 name = "${pname}-${version}-kmod-${kernel.dev.version}";
61
62 postPatch = ''
63 pushd usr/src/amdgpu-*
64 patchShebangs amd/dkms/*.sh
65 substituteInPlace amd/dkms/pre-build.sh --replace "./configure" "./configure --with-linux=${kernel.dev}/lib/modules/${kernel.modDirVersion}/source --with-linux-obj=${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
66 popd
67 '';
68
69 preConfigure = ''
70 pushd usr/src/amdgpu-*
71 makeFlags="$makeFlags M=$(pwd)"
72 amd/dkms/pre-build.sh ${kernel.version}
73 popd
74 '';
75
76 postBuild = ''
77 pushd usr/src/amdgpu-*
78 find -name \*.ko -exec xz {} \;
79 popd
80 '';
81
82 makeFlags = optionalString (kernel != null) "-C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build modules";
83
84 installPhase = ''
85 runHook preInstall
86
87 pushd usr/src/amdgpu-*
88 find -name \*.ko.xz -exec install -Dm444 {} $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/gpu/drm/{} \;
89 popd
90
91 runHook postInstall
92 '';
93
94 # without this we get a collision with the ttm module from linux
95 meta.priority = 4;
96 };
97
98 fw = stdenv.mkDerivation rec {
99 inherit version src postUnpack;
100 name = "${pname}-${version}-fw";
101
102 installPhase = ''
103 runHook preInstall
104
105 mkdir -p $out/lib
106 cp -r usr/src/amdgpu-*/firmware $out/lib/firmware
107
108 runHook postInstall
109 '';
110 };
111 };
112
113 outputs = [ "out" "vulkan" ];
114
115 depLibPath = makeLibraryPath [
116 stdenv.cc.cc.lib
117 zlib
118 libxcb
119 libxshmfence
120 elfutils
121 expat
122 libffi
123 libselinux
124 # libudev is not listed in any dependencies, but is loaded dynamically
125 udev
126 xorg.libXext
127 xorg.libX11
128 xorg.libXfixes
129 xorg.libXdamage
130 xorg.libXxf86vm
131 ];
132
133 installPhase = ''
134 runHook preInstall
135
136 mkdir -p $out
137
138 cp -r usr/lib/${libArch} $out/lib
139 cp -r usr/share $out/share
140
141 mkdir -p $out/opt/amdgpu{,-pro}
142 cp -r opt/amdgpu-pro/lib/${libArch} $out/opt/amdgpu-pro/lib
143 cp -r opt/amdgpu/lib/${libArch} $out/opt/amdgpu/lib
144
145 pushd $out/lib
146 ln -s ../opt/amdgpu-pro/lib/libGL.so* .
147 ln -s ../opt/amdgpu-pro/lib/libEGL.so* .
148 popd
149
150 # short name to allow replacement below
151 ln -s lib/dri $out/dri
152
153 '' + optionalString (stdenv.is64bit) ''
154 mkdir -p $out/etc
155 pushd etc
156 cp -r modprobe.d udev amd $out/etc
157 popd
158
159 cp -r lib/udev/rules.d/* $out/etc/udev/rules.d
160 cp -r opt/amdgpu/lib/xorg $out/lib/xorg
161 cp -r opt/amdgpu-pro/lib/xorg/* $out/lib/xorg
162 cp -r opt/amdgpu/share $out/opt/amdgpu/share
163 '' + ''
164
165 mkdir -p $vulkan/share/vulkan/icd.d
166 install opt/amdgpu-pro/etc/vulkan/icd.d/amd_icd${bitness}.json $vulkan/share/vulkan/icd.d
167
168 runHook postInstall
169 '';
170
171 preFixup = (if stdenv.is64bit
172 # this could also be done with LIBGL_DRIVERS_PATH, but it would need to be
173 # set in the user session and for Xorg
174 then ''
175 expr1='s:/opt/amdgpu/lib/x86_64-linux-gnu/dri\0:/run/opengl-driver/lib/dri\0\0\0\0\0\0\0\0\0\0\0:g'
176 expr2='s:/usr/lib/x86_64-linux-gnu/dri[\0\:]:/run/opengl-driver/lib/dri\0\0\0\0:g'
177 perl -pi -e "$expr2" $out/lib/xorg/modules/extensions/libglx.so
178 ''
179 else ''
180 expr1='s:/opt/amdgpu/lib/i386-linux-gnu/dri\0:/run/opengl-driver-32/lib/dri\0\0\0\0\0\0:g'
181 # we replace a different path on 32-bit because it's the only one long
182 # enough to fit the target path :(
183 expr2='s:/usr/lib/i386-linux-gnu/dri[\0\:]:/run/opengl-driver-32/dri\0\0\0:g'
184 '') + ''
185 perl -pi -e "$expr1" \
186 $out/opt/amdgpu/lib/libEGL.so.1.0.0 \
187 $out/opt/amdgpu/lib/libgbm.so.1.0.0 \
188 $out/opt/amdgpu/lib/libGL.so.1.2.0
189
190 perl -pi -e "$expr2" \
191 $out/opt/amdgpu-pro/lib/libEGL.so.1 \
192 $out/opt/amdgpu-pro/lib/libGL.so.1.2 \
193 $out/opt/amdgpu-pro/lib/libGLX_amd.so.0
194
195 find $out -type f -exec perl -pi -e 's:/opt/amdgpu-pro/:/run/amdgpu-pro/:g' {} \;
196 find $out -type f -exec perl -pi -e 's:/opt/amdgpu/:/run/amdgpu/:g' {} \;
197
198 substituteInPlace $vulkan/share/vulkan/icd.d/*.json --replace /opt/amdgpu-pro/lib/${libArch} "$out/opt/amdgpu-pro/lib"
199 '';
200
201 # doing this in post because shrinking breaks things that dynamically load
202 postFixup = ''
203 libPath="$out/opt/amdgpu/lib:$out/opt/amdgpu-pro/lib:$depLibPath"
204 find "$out" -name '*.so*' -type f -exec patchelf --set-rpath "$libPath" {} \;
205 '';
206
207 buildInputs = [
208 libdrm
209 patchelf
210 perl
211 ];
212
213 enableParallelBuilding = true;
214
215 meta = with lib; {
216 description = "AMDGPU-PRO drivers";
217 homepage = "https://www.amd.com/en/support";
218 license = licenses.unfree;
219 platforms = platforms.linux;
220 maintainers = with maintainers; [ corngood ];
221 };
222}