blob: 3340853335ab116af13854d0506637e06ce64094 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
declare -a autoPatchelfLibs
gatherLibraries() {
autoPatchelfLibs+=("$1/lib")
}
envHooks+=(gatherLibraries)
isExecutable() {
[ "$(file -b -N --mime-type "$1")" = application/x-executable ]
}
findElfs() {
find "$1" -type f -exec "$SHELL" -c '
while [ -n "$1" ]; do
mimeType="$(file -b -N --mime-type "$1")"
if [ "$mimeType" = application/x-executable \
-o "$mimeType" = application/x-sharedlib ]; then
echo "$1"
fi
shift
done
' -- {} +
}
declare -a cachedDependencies
addToDepCache() {
local existing
for existing in "${cachedDependencies[@]}"; do
if [ "$existing" = "$1" ]; then return; fi
done
cachedDependencies+=("$1")
}
declare -gi depCacheInitialised=0
declare -gi doneRecursiveSearch=0
declare -g foundDependency
getDepsFromSo() {
ldd "$1" 2> /dev/null | sed -n -e 's/[^=]*=> *\(.\+\) \+([^)]*)$/\1/p'
}
checkElfDep() {
local errors ldout="$(ldd "$1")"
if errors="$(echo "$ldout" | grep -F "not found")"; then
echo -e "Library dependencies missing for $1:\n$errors"
fi
}
populateCacheWithRecursiveDeps() {
local so found foundso
for so in "${cachedDependencies[@]}"; do
for found in $(getDepsFromSo "$so"); do
local libdir="${found%/*}"
local base="${found##*/}"
local soname="${base%.so*}"
for foundso in "${found%/*}/$soname".so*; do
addToDepCache "$foundso"
done
done
done
}
findDependency() {
local filename="$1"
local lib dep
if [ $depCacheInitialised -eq 0 ]; then
for lib in "${autoPatchelfLibs[@]}"; do
for so in "$lib/"*.so*; do addToDepCache "$so"; done
done
depCacheInitialised=1
fi
for dep in "${cachedDependencies[@]}"; do
if [ "$filename" = "${dep##*/}" ]; then
foundDependency="$dep"
return 0
fi
done
if [ $doneRecursiveSearch -eq 0 ]; then
populateCacheWithRecursiveDeps
doneRecursiveSearch=1
findDependency "$filename" || return 1
return 0
fi
return 1
}
autoPatchelfFile() {
local dep rpath="" toPatch="$1"
local interpreter="$(cat $NIX_CC/nix-support/dynamic-linker)"
if isExecutable "$toPatch"; then
patchelf --set-interpreter "$interpreter" "$toPatch"
if [ -n "$runtimeDependencies" ]; then
for dep in $runtimeDependencies; do
rpath="$rpath${rpath:+:}$dep/lib"
done
fi
fi
patchelf --remove-rpath "$toPatch"
local missing="$(
ldd "$toPatch" | sed -n -e 's/^[\t ]*\([^ ]\+\) => not found.*/\1/p'
)"
for dep in $missing; do
echo -n "searching for dependency $dep..." >&2
if findDependency "$dep"; then
rpath="$rpath${rpath:+:}${foundDependency%/*}"
echo " found: $foundDependency" >&2
else
echo " not found" >&2
fi
done
if [ -n "$rpath" ]; then
echo "setting RPATH of $toPatch to $rpath" >&2
patchelf --set-rpath "$rpath" "$toPatch"
fi
}
autoPatchelf() {
echo "automatically fixing dependencies for ELF files" >&2
cachedDependencies+=(
$(find "$out" \! -type d \( -name '*.so' -o -name '*.so.*' \))
)
local elffile
findElfs "$prefix" | while read -r elffile; do
autoPatchelfFile "$elffile"
done
}
postInstallHooks+=(autoPatchelf)
|