From 4f8a99e9e1b2b54f215f800a1a1411391da02a71 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Thu, 13 Feb 2020 21:07:29 +0100 Subject: [PATCH] autoPatchelfHook: Support arbitrary paths in runtimeDependencies Previously, the setup hooks configuration variable only accepted packages and added lib subdirectory of those packages to rpath. That was insufficient for including shared libraries like `lib/libv4l/v4l2convert.so` so this patch allows for passing .so file paths whose parent directory will be added to rpath. The patch also makes the process more strict, failing when a package not containing lib or not a .so file is passed to avoid hard to debug failures like passing a wrong output. --- doc/stdenv/stdenv.xml | 5 ++++- pkgs/build-support/setup-hooks/auto-patchelf.sh | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/stdenv/stdenv.xml b/doc/stdenv/stdenv.xml index 891490edf9ad89..912d194b4e2417 100644 --- a/doc/stdenv/stdenv.xml +++ b/doc/stdenv/stdenv.xml @@ -2000,11 +2000,14 @@ addEnvHooks "$hostOffset" myBashFunction This is a special setup hook which helps in packaging proprietary software in that it automatically tries to find missing shared library dependencies of ELF files based on the given buildInputs and nativeBuildInputs. - You can also specify a runtimeDependencies variable which lists dependencies to be unconditionally added to rpath of all executables. + You can also specify a runtimeDependencies variable which lists dependencies or paths to shared libraries to be unconditionally added to rpath of all executables. This is useful for programs that use dlopen 3 to load libraries at runtime. + + When you pass a library path such as ${libv4l}/lib/libv4l/v4l2convert.so to runtimeDependencies, the whole ${libv4l}/lib/libv4l directory is added to rpath. This enables the patched program to find all other libraries in the directory, not just the single library you chose. + In certain situations you may want to run the main command (autoPatchelf) of the setup hook on a file or a set of directories instead of unconditionally patching all outputs. This can be done by setting the dontAutoPatchelf environment variable to a non-empty value. diff --git a/pkgs/build-support/setup-hooks/auto-patchelf.sh b/pkgs/build-support/setup-hooks/auto-patchelf.sh index 52c50091d08cb2..744bf0df5b351c 100644 --- a/pkgs/build-support/setup-hooks/auto-patchelf.sh +++ b/pkgs/build-support/setup-hooks/auto-patchelf.sh @@ -106,7 +106,15 @@ autoPatchelfFile() { patchelf --set-interpreter "$interpreter" "$toPatch" if [ -n "$runtimeDependencies" ]; then for dep in $runtimeDependencies; do - rpath="$rpath${rpath:+:}$dep/lib" + if [[ -f "$dep" && "$dep" =~ \.so(\.[0-9]+)*$ ]]; then + rpath="$rpath${rpath:+:}$(dirname "$dep")" + elif [[ -d "$dep" && -d "$dep/lib" ]]; then + rpath="$rpath${rpath:+:}$dep/lib" + else + echo "autoPatchelfFile: ERROR: $dep passed to \$runtimeDependencies must be" \ + "either a directory containing lib subdirectory or a .so file." + return 1 + fi done fi fi