From 2874e849d99e4e96154fc2a7ce4b2e5d8ed4e699 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Wed, 22 May 2019 18:19:55 +0200 Subject: [PATCH 1/3] addOpenGLRunpath: Add new hook for setting RUNPATH. This hook allows to add NixOS driver libraries path to given ELF objects' RUNPATH. We use it instead of settings RUNPATH manually everywhere. It must be invoked in postFixup so that RUNPATH stripping does not remove the path. It puts the path first instead of last so that system-wide drivers are always preferred. --- .../add-opengl-runpath/default.nix | 12 ++++++++ .../add-opengl-runpath/setup-hook.sh | 28 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 3 files changed, 42 insertions(+) create mode 100644 pkgs/build-support/add-opengl-runpath/default.nix create mode 100644 pkgs/build-support/add-opengl-runpath/setup-hook.sh diff --git a/pkgs/build-support/add-opengl-runpath/default.nix b/pkgs/build-support/add-opengl-runpath/default.nix new file mode 100644 index 00000000000..5cab0937e07 --- /dev/null +++ b/pkgs/build-support/add-opengl-runpath/default.nix @@ -0,0 +1,12 @@ +{ lib, stdenv }: + +stdenv.mkDerivation { + name = "add-opengl-runpath"; + + driverLink = "/run/opengl-driver" + lib.optionalString stdenv.isi686 "-32"; + + buildCommand = '' + mkdir -p $out/nix-support + substituteAll ${./setup-hook.sh} $out/nix-support/setup-hook + ''; +} diff --git a/pkgs/build-support/add-opengl-runpath/setup-hook.sh b/pkgs/build-support/add-opengl-runpath/setup-hook.sh new file mode 100644 index 00000000000..7645033ca20 --- /dev/null +++ b/pkgs/build-support/add-opengl-runpath/setup-hook.sh @@ -0,0 +1,28 @@ +# Set RUNPATH so that driver libraries in /run/opengl-driver(-32)/lib can be found. +# This is needed to not rely on LD_LIBRARY_PATH which does not work with setuid +# executables. Fixes https://github.com/NixOS/nixpkgs/issues/22760. It must be run +# in postFixup because RUNPATH stripping in fixup would undo it. Note that patchelf +# actually sets RUNPATH not RPATH, which applies only to dependencies of the binary +# it set on (including for dlopen), so the RUNPATH must indeed be set on these +# libraries and would not work if set only on executables. +addOpenGLRunpath() { + local forceRpath= + + while [ $# -gt 0 ]; do + case "$1" in + --) shift; break;; + --force-rpath) shift; forceRpath=1;; + --*) + echo "addOpenGLRunpath: ERROR: Invalid command line" \ + "argument: $1" >&2 + return 1;; + *) break;; + esac + done + + for file in "$@"; do + local origRpath="$(patchelf --print-rpath "$file")" + patchelf --set-rpath "@driverLink@/lib:$origRpath" ${forceRpath:+--force-rpath} "$file" + done +} + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b86fa5c3d08..a60df81e929 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -126,6 +126,8 @@ in } ''); + addOpenGLRunpath = callPackage ../build-support/add-opengl-runpath { }; + # Zip file format only allows times after year 1980, which makes e.g. Python wheel building fail with: # ValueError: ZIP does not support timestamps before 1980 ensureNewerSourcesForZipFilesHook = ensureNewerSourcesHook { year = "1980"; }; From 1860e506e7f2fd66982929cfb75ec83b0a586acb Mon Sep 17 00:00:00 2001 From: Ambroz Bizjak Date: Wed, 22 May 2019 18:30:05 +0200 Subject: [PATCH 2/3] libglvnd, ocl-icd, vulkan-loader: Add driver library paths to RUNPATH. Previously we were relying on LD_LIBRARY_PATH to discover driver libraries (libGL, ligGLX, libEGL, OpenCL and Vulkan). This has the problem that setuid programs (in particular VirtualBox) ignore LD_LIBRARY_PATH. Fix it by setting RUNPATH in various dispatch libraries. This is not needed for libvdpau because it is already configured to look for libraries in the driver paths. Fixes https://github.com/NixOS/nixpkgs/issues/22760. --- .../development/libraries/libglvnd/default.nix | 18 +++++++++++------- pkgs/development/libraries/ocl-icd/default.nix | 12 +++++++++--- .../libraries/vulkan-loader/default.nix | 12 +++++++++--- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/pkgs/development/libraries/libglvnd/default.nix b/pkgs/development/libraries/libglvnd/default.nix index c7b76497fa8..62c6b45c5d4 100644 --- a/pkgs/development/libraries/libglvnd/default.nix +++ b/pkgs/development/libraries/libglvnd/default.nix @@ -1,8 +1,6 @@ -{ stdenv, lib, fetchFromGitHub, fetchpatch, autoreconfHook, python2, pkgconfig, libX11, libXext, xorgproto }: +{ stdenv, lib, fetchFromGitHub, fetchpatch, autoreconfHook, python2, pkgconfig, libX11, libXext, xorgproto, addOpenGLRunpath }: -let - driverLink = "/run/opengl-driver" + lib.optionalString stdenv.isi686 "-32"; -in stdenv.mkDerivation rec { +stdenv.mkDerivation rec { name = "libglvnd-${version}"; version = "1.0.0"; @@ -13,7 +11,7 @@ in stdenv.mkDerivation rec { sha256 = "1a126lzhd2f04zr3rvdl6814lfl0j077spi5dsf2alghgykn5iif"; }; - nativeBuildInputs = [ autoreconfHook pkgconfig python2 ]; + nativeBuildInputs = [ autoreconfHook pkgconfig python2 addOpenGLRunpath ]; buildInputs = [ libX11 libXext xorgproto ]; postPatch = lib.optionalString stdenv.isDarwin '' @@ -26,7 +24,7 @@ in stdenv.mkDerivation rec { NIX_CFLAGS_COMPILE = [ "-UDEFAULT_EGL_VENDOR_CONFIG_DIRS" # FHS paths are added so that non-NixOS applications can find vendor files. - "-DDEFAULT_EGL_VENDOR_CONFIG_DIRS=\"${driverLink}/share/glvnd/egl_vendor.d:/etc/glvnd/egl_vendor.d:/usr/share/glvnd/egl_vendor.d\"" + "-DDEFAULT_EGL_VENDOR_CONFIG_DIRS=\"${addOpenGLRunpath.driverLink}/share/glvnd/egl_vendor.d:/etc/glvnd/egl_vendor.d:/usr/share/glvnd/egl_vendor.d\"" ] ++ lib.optional stdenv.cc.isClang "-Wno-error"; # Indirectly: https://bugs.freedesktop.org/show_bug.cgi?id=35268 @@ -45,7 +43,13 @@ in stdenv.mkDerivation rec { }); outputs = [ "out" "dev" ]; - passthru = { inherit driverLink; }; + # Set RUNPATH so that driver libraries in /run/opengl-driver(-32)/lib can be found. + # See the explanation in addOpenGLRunpath. + postFixup = '' + addOpenGLRunpath $out/lib/libGLX.so $out/lib/libEGL.so + ''; + + passthru = { inherit (addOpenGLRunpath) driverLink; }; meta = with stdenv.lib; { description = "The GL Vendor-Neutral Dispatch library"; diff --git a/pkgs/development/libraries/ocl-icd/default.nix b/pkgs/development/libraries/ocl-icd/default.nix index ec6dc5f9052..abdc7502052 100644 --- a/pkgs/development/libraries/ocl-icd/default.nix +++ b/pkgs/development/libraries/ocl-icd/default.nix @@ -1,4 +1,4 @@ -{stdenv, fetchurl, ruby, opencl-headers, libGL_driver }: +{stdenv, fetchurl, ruby, opencl-headers, addOpenGLRunpath }: stdenv.mkDerivation rec { name = "ocl-icd-${version}"; @@ -9,12 +9,18 @@ stdenv.mkDerivation rec { sha256 = "0f14gpa13sdm0kzqv5yycp4pschbmi6n5fj7wl4ilspzsrqcgqr2"; }; - nativeBuildInputs = [ ruby ]; + nativeBuildInputs = [ ruby addOpenGLRunpath ]; buildInputs = [ opencl-headers ]; postPatch = '' - sed -i 's,"/etc/OpenCL/vendors","${libGL_driver.driverLink}/etc/OpenCL/vendors",g' ocl_icd_loader.c + sed -i 's,"/etc/OpenCL/vendors","${addOpenGLRunpath.driverLink}/etc/OpenCL/vendors",g' ocl_icd_loader.c + ''; + + # Set RUNPATH so that driver libraries in /run/opengl-driver(-32)/lib can be found. + # See the explanation in addOpenGLRunpath. + postFixup = '' + addOpenGLRunpath $out/lib/libOpenCL.so ''; meta = with stdenv.lib; { diff --git a/pkgs/development/libraries/vulkan-loader/default.nix b/pkgs/development/libraries/vulkan-loader/default.nix index 7d53065ba32..891ad373e02 100644 --- a/pkgs/development/libraries/vulkan-loader/default.nix +++ b/pkgs/development/libraries/vulkan-loader/default.nix @@ -1,5 +1,5 @@ { stdenv, fetchFromGitHub, cmake, python3, vulkan-headers, pkgconfig -, xlibsWrapper, libxcb, libXrandr, libXext, wayland, libGL_driver }: +, xlibsWrapper, libxcb, libXrandr, libXext, wayland, addOpenGLRunpath }: let version = "1.1.106"; @@ -17,17 +17,23 @@ stdenv.mkDerivation rec { sha256 = "0zhrwj1gi90x2w8gaaaw5h4b969a8gfy244kn0drrplhhb1nqz3b"; }; - nativeBuildInputs = [ pkgconfig ]; + nativeBuildInputs = [ pkgconfig addOpenGLRunpath ]; buildInputs = [ cmake python3 xlibsWrapper libxcb libXrandr libXext wayland ]; enableParallelBuilding = true; cmakeFlags = [ - "-DFALLBACK_DATA_DIRS=${libGL_driver.driverLink}/share:/usr/local/share:/usr/share" + "-DFALLBACK_DATA_DIRS=${addOpenGLRunpath.driverLink}/share:/usr/local/share:/usr/share" "-DVULKAN_HEADERS_INSTALL_DIR=${vulkan-headers}" ]; outputs = [ "out" "dev" ]; + # Set RUNPATH so that driver libraries in /run/opengl-driver(-32)/lib can be found. + # See the explanation in addOpenGLRunpath. + postFixup = '' + addOpenGLRunpath $out/lib/libvulkan.so + ''; + meta = with stdenv.lib; { description = "LunarG Vulkan loader"; homepage = https://www.lunarg.com; From 28a09189166c767ad284adb9f7e137a3f98546a4 Mon Sep 17 00:00:00 2001 From: Ambroz Bizjak Date: Wed, 22 May 2019 18:34:09 +0200 Subject: [PATCH 3/3] Add driver library path to some packages to find CUDA libraries. This is to avoid relying on LD_LIBRARY_PATH for finding the CUDA driver libraries. --- pkgs/applications/misc/blender/default.nix | 14 ++++++++++++-- pkgs/development/compilers/cudatoolkit/default.nix | 14 ++++++++++++-- .../libraries/science/math/cudnn/generic.nix | 9 +++++++++ .../libraries/science/math/nccl/default.nix | 8 ++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/pkgs/applications/misc/blender/default.nix b/pkgs/applications/misc/blender/default.nix index 353cf620ee7..5445c7efb59 100644 --- a/pkgs/applications/misc/blender/default.nix +++ b/pkgs/applications/misc/blender/default.nix @@ -2,7 +2,7 @@ , ilmbase, libXi, libX11, libXext, libXrender , libjpeg, libpng, libsamplerate, libsndfile , libtiff, libGLU_combined, openal, opencolorio, openexr, openimageio, openjpeg_1, pythonPackages -, zlib, fftw, opensubdiv, freetype, jemalloc, ocl-icd +, zlib, fftw, opensubdiv, freetype, jemalloc, ocl-icd, addOpenGLRunpath , jackaudioSupport ? false, libjack2 , cudaSupport ? config.cudaSupport or false, cudatoolkit , colladaSupport ? true, opencollada @@ -21,8 +21,9 @@ stdenv.mkDerivation rec { sha256 = "1g4kcdqmf67srzhi3hkdnr4z1ph4h9sza1pahz38mrj998q4r52c"; }; + nativeBuildInputs = [ cmake ] ++ optional cudaSupport addOpenGLRunpath; buildInputs = - [ boost cmake ffmpeg gettext glew ilmbase + [ boost ffmpeg gettext glew ilmbase libXi libX11 libXext libXrender freetype libjpeg libpng libsamplerate libsndfile libtiff libGLU_combined openal opencolorio openexr openimageio openjpeg_1 python zlib fftw jemalloc @@ -80,6 +81,15 @@ stdenv.mkDerivation rec { --prefix PYTHONPATH : ${pythonPackages.numpy}/${python.sitePackages} ''; + # Set RUNPATH so that libcuda and libnvrtc in /run/opengl-driver(-32)/lib can be + # found. See the explanation in libglvnd. + postFixup = optionalString cudaSupport '' + for program in $out/bin/blender $out/bin/.blender-wrapped; do + isELF "$program" || continue + addOpenGLRunpath "$program" + done + ''; + meta = with stdenv.lib; { description = "3D Creation/Animation/Publishing System"; homepage = https://www.blender.org; diff --git a/pkgs/development/compilers/cudatoolkit/default.nix b/pkgs/development/compilers/cudatoolkit/default.nix index e2c3c8fe587..6a18c05f38e 100644 --- a/pkgs/development/compilers/cudatoolkit/default.nix +++ b/pkgs/development/compilers/cudatoolkit/default.nix @@ -1,6 +1,7 @@ { lib, stdenv, makeWrapper, fetchurl, requireFile, perl, ncurses5, expat, python27, zlib , gcc48, gcc49, gcc5, gcc6, gcc7 , xorg, gtk2, gdk_pixbuf, glib, fontconfig, freetype, unixODBC, alsaLib, glibc +, addOpenGLRunpath }: let @@ -39,7 +40,7 @@ let outputs = [ "out" "lib" "doc" ]; - nativeBuildInputs = [ perl makeWrapper ]; + nativeBuildInputs = [ perl makeWrapper addOpenGLRunpath ]; buildInputs = [ gdk_pixbuf ]; # To get $GDK_PIXBUF_MODULE_FILE via setup-hook runtimeDependencies = [ ncurses5 expat python zlib glibc @@ -143,10 +144,19 @@ let else rpath2=$rpath:$lib/lib:$out/jre/lib/amd64/jli:$out/lib:$out/lib64:$out/nvvm/lib:$out/nvvm/lib64 fi - patchelf --set-rpath $rpath2 --force-rpath $i + patchelf --set-rpath "$rpath2" --force-rpath $i done < <(find $out $lib $doc -type f -print0) ''; + # Set RPATH so that libcuda and other libraries in + # /run/opengl-driver(-32)/lib can be found. See the explanation in + # addOpenGLRunpath. Don't try to figure out which libraries really need + # it, just patch all (but not the stubs libraries). Note that + # --force-rpath prevents changing RPATH (set above) to RUNPATH. + postFixup = '' + addOpenGLRunpath --force-rpath {$out,$lib}/lib/lib*.so + ''; + # cuda-gdb doesn't run correctly when not using sandboxing, so # temporarily disabling the install check. This should be set to true # when we figure out how to get `cuda-gdb --version` to run correctly diff --git a/pkgs/development/libraries/science/math/cudnn/generic.nix b/pkgs/development/libraries/science/math/cudnn/generic.nix index bb1258655b5..3c448abeccf 100644 --- a/pkgs/development/libraries/science/math/cudnn/generic.nix +++ b/pkgs/development/libraries/science/math/cudnn/generic.nix @@ -7,6 +7,7 @@ , lib , cudatoolkit , fetchurl +, addOpenGLRunpath }: stdenv.mkDerivation rec { @@ -19,6 +20,8 @@ stdenv.mkDerivation rec { inherit sha256; }; + nativeBuildInputs = [ addOpenGLRunpath ]; + installPhase = '' function fixRunPath { p=$(patchelf --print-rpath $1) @@ -31,6 +34,12 @@ stdenv.mkDerivation rec { cp -a lib64 $out/lib64 ''; + # Set RUNPATH so that libcuda in /run/opengl-driver(-32)/lib can be found. + # See the explanation in addOpenGLRunpath. + postFixup = '' + addOpenGLRunpath $out/lib/lib*.so + ''; + propagatedBuildInputs = [ cudatoolkit ]; diff --git a/pkgs/development/libraries/science/math/nccl/default.nix b/pkgs/development/libraries/science/math/nccl/default.nix index badd08291de..a099b779a78 100644 --- a/pkgs/development/libraries/science/math/nccl/default.nix +++ b/pkgs/development/libraries/science/math/nccl/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchFromGitHub, which, cudatoolkit }: +{ stdenv, fetchFromGitHub, which, cudatoolkit, addOpenGLRunpath }: stdenv.mkDerivation rec { name = "nccl-${version}-cuda-${cudatoolkit.majorVersion}"; @@ -13,7 +13,7 @@ stdenv.mkDerivation rec { outputs = [ "out" "dev" ]; - nativeBuildInputs = [ which ]; + nativeBuildInputs = [ which addOpenGLRunpath ]; buildInputs = [ cudatoolkit ]; @@ -28,6 +28,10 @@ stdenv.mkDerivation rec { postFixup = '' moveToOutput lib/libnccl_static.a $dev + + # Set RUNPATH so that libnvidia-ml in /run/opengl-driver(-32)/lib can be found. + # See the explanation in addOpenGLRunpath. + addOpenGLRunpath $out/lib/lib*.so ''; NIX_CFLAGS_COMPILE = [ "-Wno-unused-function" ];