nixpkgs/pkgs/os-specific/linux/amdgpu-pro/default.nix
2023-11-29 09:45:17 +01:00

222 lines
5.9 KiB
Nix

{ lib
, stdenv
, fetchurl
, elfutils
, xorg
, patchelf
, libxcb
, libxshmfence
, perl
, zlib
, expat
, libffi
, libselinux
, libdrm
, udev
, kernel ? null
}:
with lib;
let
bitness = if stdenv.is64bit then "64" else "32";
libArch =
if stdenv.hostPlatform.system == "i686-linux" then
"i386-linux-gnu"
else if stdenv.hostPlatform.system == "x86_64-linux" then
"x86_64-linux-gnu"
else throw "amdgpu-pro is Linux only. Sorry ${stdenv.hostPlatform.system}.";
in stdenv.mkDerivation rec {
version = "21.30";
pname = "amdgpu-pro";
build = "${version}-1290604";
src = fetchurl {
url = "https://drivers.amd.com/drivers/linux/amdgpu-pro-${build}-ubuntu-20.04.tar.xz";
sha256 = "sha256-WECqxjo2WLP3kMWeVyJgYufkvHTzwGaj57yeMGXiQ4I=";
curlOpts = "--referer https://www.amd.com/en/support/kb/release-notes/rn-amdgpu-unified-linux-21-30";
};
postUnpack = ''
mkdir root
pushd $sourceRoot
for deb in *_all.deb *_${if stdenv.is64bit then "amd64" else "i386"}.deb
do
ar p $deb data.tar.xz | tar -C ../root -xJ
done
popd
# if we don't use a short sourceRoot, compilation can fail due to command
# line length
sourceRoot=root
'';
passthru = optionalAttrs (kernel != null) {
kmod = stdenv.mkDerivation rec {
inherit version src postUnpack;
name = "${pname}-${version}-kmod-${kernel.dev.version}";
postPatch = ''
pushd usr/src/amdgpu-*
patchShebangs amd/dkms/*.sh
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"
popd
'';
preConfigure = ''
pushd usr/src/amdgpu-*
makeFlags="$makeFlags M=$(pwd)"
amd/dkms/pre-build.sh ${kernel.version}
popd
'';
postBuild = ''
pushd usr/src/amdgpu-*
find -name \*.ko -exec xz {} \;
popd
'';
makeFlags = optionalString (kernel != null) "-C ${kernel.dev}/lib/modules/${kernel.modDirVersion}/build modules";
installPhase = ''
runHook preInstall
pushd usr/src/amdgpu-*
find -name \*.ko.xz -exec install -Dm444 {} $out/lib/modules/${kernel.modDirVersion}/kernel/drivers/gpu/drm/{} \;
popd
runHook postInstall
'';
# without this we get a collision with the ttm module from linux
meta.priority = 4;
};
fw = stdenv.mkDerivation rec {
inherit version src postUnpack;
name = "${pname}-${version}-fw";
installPhase = ''
runHook preInstall
mkdir -p $out/lib
cp -r usr/src/amdgpu-*/firmware $out/lib/firmware
runHook postInstall
'';
};
};
outputs = [ "out" "vulkan" ];
depLibPath = makeLibraryPath [
stdenv.cc.cc.lib
zlib
libxcb
libxshmfence
elfutils
expat
libffi
libselinux
# libudev is not listed in any dependencies, but is loaded dynamically
udev
xorg.libXext
xorg.libX11
xorg.libXfixes
xorg.libXdamage
xorg.libXxf86vm
];
installPhase = ''
runHook preInstall
mkdir -p $out
cp -r usr/lib/${libArch} $out/lib
cp -r usr/share $out/share
mkdir -p $out/opt/amdgpu{,-pro}
cp -r opt/amdgpu-pro/lib/${libArch} $out/opt/amdgpu-pro/lib
cp -r opt/amdgpu/lib/${libArch} $out/opt/amdgpu/lib
pushd $out/lib
ln -s ../opt/amdgpu-pro/lib/libGL.so* .
ln -s ../opt/amdgpu-pro/lib/libEGL.so* .
popd
# short name to allow replacement below
ln -s lib/dri $out/dri
'' + optionalString (stdenv.is64bit) ''
mkdir -p $out/etc
pushd etc
cp -r modprobe.d udev amd $out/etc
popd
cp -r lib/udev/rules.d/* $out/etc/udev/rules.d
cp -r opt/amdgpu/lib/xorg $out/lib/xorg
cp -r opt/amdgpu-pro/lib/xorg/* $out/lib/xorg
cp -r opt/amdgpu/share $out/opt/amdgpu/share
'' + ''
mkdir -p $vulkan/share/vulkan/icd.d
install opt/amdgpu-pro/etc/vulkan/icd.d/amd_icd${bitness}.json $vulkan/share/vulkan/icd.d
runHook postInstall
'';
preFixup = (if stdenv.is64bit
# this could also be done with LIBGL_DRIVERS_PATH, but it would need to be
# set in the user session and for Xorg
then ''
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'
expr2='s:/usr/lib/x86_64-linux-gnu/dri[\0\:]:/run/opengl-driver/lib/dri\0\0\0\0:g'
perl -pi -e "$expr2" $out/lib/xorg/modules/extensions/libglx.so
''
else ''
expr1='s:/opt/amdgpu/lib/i386-linux-gnu/dri\0:/run/opengl-driver-32/lib/dri\0\0\0\0\0\0:g'
# we replace a different path on 32-bit because it's the only one long
# enough to fit the target path :(
expr2='s:/usr/lib/i386-linux-gnu/dri[\0\:]:/run/opengl-driver-32/dri\0\0\0:g'
'') + ''
perl -pi -e "$expr1" \
$out/opt/amdgpu/lib/libEGL.so.1.0.0 \
$out/opt/amdgpu/lib/libgbm.so.1.0.0 \
$out/opt/amdgpu/lib/libGL.so.1.2.0
perl -pi -e "$expr2" \
$out/opt/amdgpu-pro/lib/libEGL.so.1 \
$out/opt/amdgpu-pro/lib/libGL.so.1.2 \
$out/opt/amdgpu-pro/lib/libGLX_amd.so.0
find $out -type f -exec perl -pi -e 's:/opt/amdgpu-pro/:/run/amdgpu-pro/:g' {} \;
find $out -type f -exec perl -pi -e 's:/opt/amdgpu/:/run/amdgpu/:g' {} \;
substituteInPlace $vulkan/share/vulkan/icd.d/*.json --replace /opt/amdgpu-pro/lib/${libArch} "$out/opt/amdgpu-pro/lib"
'';
# doing this in post because shrinking breaks things that dynamically load
postFixup = ''
libPath="$out/opt/amdgpu/lib:$out/opt/amdgpu-pro/lib:$depLibPath"
find "$out" -name '*.so*' -type f -exec patchelf --set-rpath "$libPath" {} \;
'';
buildInputs = [
libdrm
patchelf
perl
];
enableParallelBuilding = true;
meta = with lib; {
description = "AMDGPU-PRO drivers";
homepage = "https://www.amd.com/en/support";
license = licenses.unfree;
platforms = platforms.linux;
maintainers = with maintainers; [ corngood ];
};
}