summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJörg Thalheim <Mic92@users.noreply.github.com>2018-11-27 10:25:26 +0000
committerGitHub <noreply@github.com>2018-11-27 10:25:26 +0000
commitafbdeb7b9b0dab1fd502407103958608c9ba1e1e (patch)
tree8bfc9d5c364a46d6461af210ade54ff234c41727
parentf12bd000b9a7f72965c726012fd0d6cca6d4c629 (diff)
parent4a6e3e4185dcbe53c3d5eceaf2570d51516ad2b4 (diff)
Merge pull request #50802 from aszlig/autopatchelf-improvements
autoPatchelfHook: Fixes/improvements for Android SDK emulator
-rw-r--r--doc/stdenv.xml31
-rw-r--r--pkgs/build-support/setup-hooks/auto-patchelf.sh67
2 files changed, 83 insertions, 15 deletions
diff --git a/doc/stdenv.xml b/doc/stdenv.xml
index 40ff17aafa09..4c19b2867b5a 100644
--- a/doc/stdenv.xml
+++ b/doc/stdenv.xml
@@ -2428,12 +2428,31 @@ addEnvHooks "$hostOffset" myBashFunction
<para>
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. All packages within the
- <envar>runtimeDependencies</envar> environment variable are
- unconditionally added to executables, which is useful for programs that
- use <citerefentry>
- <refentrytitle>dlopen</refentrytitle>
- <manvolnum>3</manvolnum> </citerefentry> to load libraries at runtime.
+ dependencies of ELF files based on the given
+ <varname>buildInputs</varname> and <varname>nativeBuildInputs</varname>.
+ </para>
+ <para>
+ You can also specify a <envar>runtimeDependencies</envar> environment
+ variable which lists dependencies that are unconditionally added to all
+ executables.
+ </para>
+ <para>
+ This is useful for programs that use <citerefentry>
+ <refentrytitle>dlopen</refentrytitle>
+ <manvolnum>3</manvolnum>
+ </citerefentry> to load libraries at runtime.
+ </para>
+ <para>
+ In certain situations you may want to run the main command
+ (<command>autoPatchelf</command>) 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 <envar>dontAutoPatchelf</envar> environment
+ variable to a non-empty value.
+ </para>
+ <para>
+ The <command>autoPatchelf</command> command also recognizes a
+ <parameter class="command">--no-recurse</parameter> command line flag,
+ which prevents it from recursing into subdirectories.
</para>
</listitem>
</varlistentry>
diff --git a/pkgs/build-support/setup-hooks/auto-patchelf.sh b/pkgs/build-support/setup-hooks/auto-patchelf.sh
index d1ae317ff9a4..5bedd1a9f9ca 100644
--- a/pkgs/build-support/setup-hooks/auto-patchelf.sh
+++ b/pkgs/build-support/setup-hooks/auto-patchelf.sh
@@ -147,15 +147,56 @@ autoPatchelfFile() {
fi
}
+# Can be used to manually add additional directories with shared object files
+# to be included for the next autoPatchelf invocation.
+addAutoPatchelfSearchPath() {
+ local -a findOpts=()
+
+ # XXX: Somewhat similar to the one in the autoPatchelf function, maybe make
+ # it DRY someday...
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --) shift; break;;
+ --no-recurse) shift; findOpts+=("-maxdepth" 1);;
+ --*)
+ echo "addAutoPatchelfSearchPath: ERROR: Invalid command line" \
+ "argument: $1" >&2
+ return 1;;
+ *) break;;
+ esac
+ done
+
+ cachedDependencies+=(
+ $(find "$@" "${findOpts[@]}" \! -type d \
+ \( -name '*.so' -o -name '*.so.*' \))
+ )
+}
+
autoPatchelf() {
+ local norecurse=
+
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --) shift; break;;
+ --no-recurse) shift; norecurse=1;;
+ --*)
+ echo "autoPatchelf: ERROR: Invalid command line" \
+ "argument: $1" >&2
+ return 1;;
+ *) break;;
+ esac
+ done
+
+ if [ $# -eq 0 ]; then
+ echo "autoPatchelf: No paths to patch specified." >&2
+ return 1
+ fi
+
echo "automatically fixing dependencies for ELF files" >&2
# Add all shared objects of the current output path to the start of
# cachedDependencies so that it's choosen first in findDependency.
- cachedDependencies+=(
- $(find "$prefix" \! -type d \( -name '*.so' -o -name '*.so.*' \))
- )
- local elffile
+ addAutoPatchelfSearchPath ${norecurse:+--no-recurse} -- "$@"
# Here we actually have a subshell, which also means that
# $cachedDependencies is final at this point, so whenever we want to run
@@ -164,12 +205,15 @@ autoPatchelf() {
# outside of this function.
while IFS= read -r -d $'\0' file; do
isELF "$file" || continue
+ segmentHeaders="$(LANG=C readelf -l "$file")"
+ # Skip if the ELF file doesn't have segment headers (eg. object files).
+ echo "$segmentHeaders" | grep -q '^Program Headers:' || continue
if isExecutable "$file"; then
# Skip if the executable is statically linked.
- LANG=C readelf -l "$file" | grep -q "^ *INTERP\\>" || continue
+ echo "$segmentHeaders" | grep -q "^ *INTERP\\>" || continue
fi
autoPatchelfFile "$file"
- done < <(find "$prefix" -type f -print0)
+ done < <(find "$@" ${norecurse:+-maxdepth 1} -type f -print0)
}
# XXX: This should ultimately use fixupOutputHooks but we currently don't have
@@ -180,6 +224,11 @@ autoPatchelf() {
# So what we do here is basically run in postFixup and emulate the same
# behaviour as fixupOutputHooks because the setup hook for patchelf is run in
# fixupOutput and the postFixup hook runs later.
-postFixupHooks+=(
- 'for output in $outputs; do prefix="${!output}" autoPatchelf; done'
-)
+postFixupHooks+=('
+ if [ -z "$dontAutoPatchelf" ]; then
+ autoPatchelf -- $(for output in $outputs; do
+ [ -e "${!output}" ] || continue
+ echo "${!output}"
+ done)
+ fi
+')