blob: 1429ae926d913560bd48ab5d463b54be3969479b (
plain)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# Dependeny and ordering functions
pkg_depends() {
# Resolve all dependencies and generate an ordered list.
# This does a depth-first search. The deepest dependencies are
# listed first and then the parents in reverse order.
contains "$deps" "$1" || {
# Filter out non-explicit, aleady installed dependencies.
# Only filter installed if called from 'pkg_build()'.
[ "$pkg_build" ] && [ -z "$2" ] &&
(pkg_list "$1" >/dev/null) && return
while read -r dep type || [ "$dep" ]; do
# Skip comments and empty lines.
[ "${dep##\#*}" ] || continue
# Skip test dependencies unless $CPT_TEST is set to 1.
#
# Skip make dependencies on the 'tree' operation for child packages
# or when the 'first-nomake' argument is given.
case $type in
test) [ "$CPT_TEST" = 1 ] || continue ;;
make) [ "$2" = tree ] && [ -z "${3#first-nomake}" ] && continue
esac
# Recurse through the dependencies of the child packages. Forward
# the 'tree' operation.
if [ "$2" = tree ]; then
pkg_depends "$dep" tree
else
pkg_depends "$dep"
fi
done 2>/dev/null < "$(pkg_find "$1")/depends" ||:
# After child dependencies are added to the list,
# add the package which depends on them.
[ "$2" = explicit ] || [ "$3" ] || deps="$deps $1 "
}
}
pkg_order() {
# Order a list of packages based on dependence and
# take into account pre-built tarballs if this is
# to be called from 'cpt i'.
order=; redro=; deps=
for pkg do case $pkg in
*.tar.*) deps="$deps $pkg " ;;
*) pkg_depends "$pkg" raw
esac done
# Filter the list, only keeping explicit packages.
# The purpose of these two loops is to order the
# argument list based on dependence.
for pkg in $deps; do ! contains "$*" "$pkg" || {
order="$order $pkg "
redro=" $pkg $redro"
} done
deps=
}
pkg_fix_deps() {
# Dynamically look for missing runtime dependencies by checking each binary
# and library with either 'ldd' or 'readelf'. This catches any extra
# libraries and or dependencies pulled in by the package's build suite.
log "$1" "Checking for missing dependencies"
# Go to the directory containing the built package to
# simplify path building.
cd "$pkg_dir/$1/$pkg_db/$1"
# Make a copy of the depends file if it exists to have a
# reference to 'diff' against.
if [ -f depends ]; then
cp -f depends "$mak_dir/d"
dep_file=$mak_dir/d
else
dep_file=/dev/null
fi
# Generate a list of all installed manifests.
pkg_name=$1
set +f; set -f -- "$sys_db/"*/manifest
# Get a list of binaries and libraries, false files
# will be found, however it's faster to get 'ldd' to check
# them anyway than to filter them out.
find "$pkg_dir/$pkg_name/" -type f 2>/dev/null |
while read -r file; do
case ${elf_prog:-ldd} in
*readelf) "$elf_prog" -d "$file" 2>/dev/null ;;
*) ldd "$file" 2>/dev/null ;;
esac |
while read -r dep; do
# Skip lines containing 'ldd'.
[ "${dep##*ldd*}" ] || continue
case $dep in *NEEDED*\[*\] | *'=>'*) ;; *) continue; esac
# readelf output:
# 0x0000 (NEEDED) Shared library: [libc.so]
dep=${dep##*\[}
dep=${dep%%\]*}
# ldd output:
# libc.so => /lib/ld-musl-x86_64.so.1
dep=${dep#* => }
dep=${dep% *}
# Figure out which package owns the file. Skip file if it is owned
# by the current package. This also handles cases where a '*-bin'
# package exists on the system, so the package manager doesn't think
# that the package we are building depends on the *-bin version of
# itself, or any other renamed versions of the same software.
pkg_owner -l "/${dep#/}\$" "$PWD/manifest" >/dev/null && continue
pkg_owner -l "/${dep#/}\$" "$@" ||:
done ||:
done >> depends
# Remove duplicate entries from the new depends file.
# This removes duplicate lines looking *only* at the
# first column.
sort -uk1,1 -o depends depends 2>/dev/null ||:
# Display a diff of the new dependencies against the old ones.
diff -U 3 "$dep_file" depends 2>/dev/null ||:
# Remove the depends file if it is empty.
[ -s depends ] || rm -f depends
}
pkg_get_base() (
# Print the packages defined in the /etc/cpt-base file.
# If an argument is given, it prints a space seperated list instead
# of a list seperated by newlines.
# cpt-base is an optional file, return with success if it doesn't exist.
[ -f "$CPT_ROOT/etc/cpt-base" ] || return 0
nonl=$1; set --
# Older versions of shellcheck warns us that the variable is changing on the
# subshell. That is our purpose here, thank you very much.
# shellcheck disable=SC2030
while read -r pkgname _; do
[ "${pkgname##\#*}" ] || continue
set -- "$@" "$pkgname"
done < "$CPT_ROOT/etc/cpt-base"
if [ "$nonl" ]; then printf '%s ' "$@"; else printf '%s\n' "$@"; fi
)
pkg_gentree() (
# Generate an ordered dependency tree of a package. Useful for testing
# whether the generated dependency tree is enough to actually building a
# given package. A second argument can be given as a combination of
# characters (similar to 'tar(1)' keys) which will be used as an option
# parser. See the documentation for more information on the keys.
# shellcheck disable=2030
deps='' reverse='' nonl='' make_deps=first
for op in $(sepchar "$2"); do
case "$op" in
b) deps="$(pkg_get_base nonl)" ;;
x) make_deps=first-nomake ;;
r) reverse=1 ;;
n) nonl=1 ;;
*) return 1
esac
done
pkg_depends "$1" tree "${make_deps:+first}"
eval set -- "$deps"
pkg_order "$@"
if [ "$reverse" ]; then eval set -- "$redro"; else eval set -- "$order"; fi
if [ "$nonl" ]; then printf '%s ' "$@"; else printf '%s\n' "$@"; fi
)
# Local Variables:
# mode: sh
# End:
|