Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f12bd000b9a7
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: afbdeb7b9b0d
Choose a head ref
  • 8 commits
  • 2 files changed
  • 2 contributors

Commits on Nov 19, 2018

  1. autoPatchelfHook: Make easier to run autoPatchelf

    The autoPatchelf main function which is run against all of the outputs
    was pretty much tailored towards this specific setup-hook and was
    relying on $prefix to be set globally.
    
    So if you wanted to run autoPatchelf manually - let's say during
    buildPhase - you would have needed to run it like this:
    
      prefix=/some/directory autoPatchelf
    
    This is now more intuitive and all you need to do is run the following:
    
      autoPatchelf /some/directory
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 19, 2018
    Copy the full SHA
    d03e4ff View commit details
  2. autoPatchelfHook: Allow to prevent automatic run

    If you want to only run autoPatchelf on a specific path and leave
    everything else alone, we now have a $dontAutoPatchelf environment
    variable, which causes the postFixup hook to not run at all.
    
    The name "dontAutoPatchelf" probably is a bit weird in conjunction with
    putting "autoPatchelfHook" in nativeBuildInputs, but unless someone
    comes up with a better name I keep it that way because it's consistent
    with all the other dontStrip, dontPatchShebangs, dontPatchELF and
    whatnot.
    
    A specific example where this is needed is when building the Android SDK
    emulator, which contains a few ARM binaries in subdirectories that
    should not be patched. If we were to run autoPatchelf on all outputs
    unconditionally we'd run into errors because some ARM libraries couldn't
    be found.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 19, 2018
    Copy the full SHA
    e4fbb24 View commit details
  3. autoPatchelfHook: Add --no-recurse flag

    This is to be used with the autoPatchelf command and allows to only
    patch a specific file or directory without recursing into
    subdirectories.
    
    Apart from being able to run the command in a standalone way, as
    detailled in the previous commit this is also needed for the Android SDK
    emulator, because according to @svanderburg there are subdirectories we
    don't want to patch.
    
    The reason why I didn't use GNU getopt is that it might not be available
    on all operating systems and the getopts bash builtin doesn't support
    long arguments. Apart from that, the implementation for recognizing the
    flag is pretty trivial and it's also using bash builtins only, so if we
    want to do something really fancy someday, we can still change it.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 19, 2018
    Copy the full SHA
    3ca35ce View commit details
  4. doc/stdenv: Document autoPatchelfHook changes

    First of all, this makes the existing documentation a bit more clear on
    what autoPatchelfHook is all about, because after discussing with
    @svanderburg - who wrote a similar implementation - the rationale about
    autoPatchelfHook wasn't very clear in the documentation.
    
    I also added the recent changes around being able to use autoPatchelf
    manually and the new --no-recurse flag.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 19, 2018
    Copy the full SHA
    503b41b View commit details

Commits on Nov 25, 2018

  1. autoPatchelfHook: Add addAutoPatchelfSearchPath

    This function is useful if autoPatchelf is invoked during some of the
    phases of a build and allows to add arbitrary shared objects to the
    search path.
    
    So far the same functionality was in autoPatchelf itself, but not
    available as a separate function, so when adding shared objects to the
    dependency cache one would have to do so manually.
    
    The function also has the --no-recurse flag, which prevents recursing
    into subdirectories.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 25, 2018
    Copy the full SHA
    2faf905 View commit details

Commits on Nov 26, 2018

  1. autoPatchelfHook: Fix type of norecurse variable

    While declaring it as an array doesn't do any harm in our usage, it
    might be a bit confusing when reading the code.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    aszlig committed Nov 26, 2018
    Copy the full SHA
    9f23a63 View commit details
  2. autoPatchelfHook: Skip on missing segment headers

    If the file in question is not a shared object file but an ELF, we
    really want to skip the file, because we won't have anything to patch
    there.
    
    For example if the file is created via "gcc -c -o foo.o foo.c", we don't
    get a segment header and so far autoPatchelf was trying to patch such a
    file.
    
    By checking for missing segment headers, we're now no longer going to
    attempt patching such a file.
    
    Signed-off-by: aszlig <aszlig@nix.build>
    Reported-by: Sander van der Burg <svanderburg@gmail.com>
    aszlig committed Nov 26, 2018
    Copy the full SHA
    4a6e3e4 View commit details

Commits on Nov 27, 2018

  1. Merge pull request #50802 from aszlig/autopatchelf-improvements

    autoPatchelfHook: Fixes/improvements for Android SDK emulator
    Mic92 authored Nov 27, 2018
    Copy the full SHA
    afbdeb7 View commit details
Showing with 83 additions and 15 deletions.
  1. +25 −6 doc/stdenv.xml
  2. +58 −9 pkgs/build-support/setup-hooks/auto-patchelf.sh
31 changes: 25 additions & 6 deletions doc/stdenv.xml
Original file line number Diff line number Diff line change
@@ -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>
67 changes: 58 additions & 9 deletions pkgs/build-support/setup-hooks/auto-patchelf.sh
Original file line number Diff line number Diff line change
@@ -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
')