···
1
+
declare -a autoPatchelfLibs
4
+
autoPatchelfLibs+=("$1/lib")
7
+
addEnvHooks "$targetOffset" gatherLibraries
10
+
[ "$(file -b -N --mime-type "$1")" = application/x-executable ]
14
+
find "$1" -type f -exec "$SHELL" -c '
15
+
while [ -n "$1" ]; do
16
+
mimeType="$(file -b -N --mime-type "$1")"
17
+
if [ "$mimeType" = application/x-executable \
18
+
-o "$mimeType" = application/x-sharedlib ]; then
26
+
# We cache dependencies so that we don't need to search through all of them on
27
+
# every consecutive call to findDependency.
28
+
declare -a cachedDependencies
32
+
for existing in "${cachedDependencies[@]}"; do
33
+
if [ "$existing" = "$1" ]; then return; fi
35
+
cachedDependencies+=("$1")
38
+
declare -gi depCacheInitialised=0
39
+
declare -gi doneRecursiveSearch=0
40
+
declare -g foundDependency
43
+
ldd "$1" 2> /dev/null | sed -n -e 's/[^=]*=> *\(.\+\) \+([^)]*)$/\1/p'
46
+
populateCacheWithRecursiveDeps() {
47
+
local so found foundso
48
+
for so in "${cachedDependencies[@]}"; do
49
+
for found in $(getDepsFromSo "$so"); do
50
+
local libdir="${found%/*}"
51
+
local base="${found##*/}"
52
+
local soname="${base%.so*}"
53
+
for foundso in "${found%/*}/$soname".so*; do
54
+
addToDepCache "$foundso"
61
+
objdump -f "$1" | sed -ne 's/^architecture: *\([^,]\+\).*/\1/p'
64
+
# NOTE: If you want to use this function outside of the autoPatchelf function,
65
+
# keep in mind that the dependency cache is only valid inside the subshell
66
+
# spawned by the autoPatchelf function, so invoking this directly will possibly
67
+
# rebuild the dependency cache. See the autoPatchelf function below for more
74
+
if [ $depCacheInitialised -eq 0 ]; then
75
+
for lib in "${autoPatchelfLibs[@]}"; do
76
+
for so in "$lib/"*.so*; do addToDepCache "$so"; done
78
+
depCacheInitialised=1
81
+
for dep in "${cachedDependencies[@]}"; do
82
+
if [ "$filename" = "${dep##*/}" ]; then
83
+
if [ "$(getSoArch "$dep")" = "$arch" ]; then
84
+
foundDependency="$dep"
90
+
# Populate the dependency cache with recursive dependencies *only* if we
91
+
# didn't find the right dependency so far and afterwards run findDependency
92
+
# again, but this time with $doneRecursiveSearch set to 1 so that it won't
93
+
# recurse again (and thus infinitely).
94
+
if [ $doneRecursiveSearch -eq 0 ]; then
95
+
populateCacheWithRecursiveDeps
96
+
doneRecursiveSearch=1
97
+
findDependency "$filename" "$arch" || return 1
103
+
autoPatchelfFile() {
104
+
local dep rpath="" toPatch="$1"
106
+
local interpreter="$(< "$NIX_CC/nix-support/dynamic-linker")"
107
+
if isExecutable "$toPatch"; then
108
+
patchelf --set-interpreter "$interpreter" "$toPatch"
109
+
if [ -n "$runtimeDependencies" ]; then
110
+
for dep in $runtimeDependencies; do
111
+
rpath="$rpath${rpath:+:}$dep/lib"
116
+
echo "searching for dependencies of $toPatch" >&2
118
+
# We're going to find all dependencies based on ldd output, so we need to
119
+
# clear the RPATH first.
120
+
patchelf --remove-rpath "$toPatch"
123
+
ldd "$toPatch" 2> /dev/null | \
124
+
sed -n -e 's/^[\t ]*\([^ ]\+\) => not found.*/\1/p'
127
+
# This ensures that we get the output of all missing dependencies instead
128
+
# of failing at the first one, because it's more useful when working on a
129
+
# new package where you don't yet know its dependencies.
130
+
local -i depNotFound=0
132
+
for dep in $missing; do
133
+
echo -n " $dep -> " >&2
134
+
if findDependency "$dep" "$(getSoArch "$toPatch")"; then
135
+
rpath="$rpath${rpath:+:}${foundDependency%/*}"
136
+
echo "found: $foundDependency" >&2
138
+
echo "not found!" >&2
143
+
# This makes sure the builder fails if we didn't find a dependency, because
144
+
# the stdenv setup script is run with set -e. The actual error is emitted
145
+
# earlier in the previous loop.
146
+
[ $depNotFound -eq 0 ]
148
+
if [ -n "$rpath" ]; then
149
+
echo "setting RPATH to: $rpath" >&2
150
+
patchelf --set-rpath "$rpath" "$toPatch"
155
+
echo "automatically fixing dependencies for ELF files" >&2
157
+
# Add all shared objects of the current output path to the start of
158
+
# cachedDependencies so that it's choosen first in findDependency.
159
+
cachedDependencies+=(
160
+
$(find "$prefix" \! -type d \( -name '*.so' -o -name '*.so.*' \))
164
+
# Here we actually have a subshell, which also means that
165
+
# $cachedDependencies is final at this point, so whenever we want to run
166
+
# findDependency outside of this, the dependency cache needs to be rebuilt
167
+
# from scratch, so keep this in mind if you want to run findDependency
168
+
# outside of this function.
169
+
findElfs "$prefix" | while read -r elffile; do
170
+
autoPatchelfFile "$elffile"
174
+
fixupOutputHooks+=(autoPatchelf)