On Mon, Jan 31, 2011 at 2:15 PM, Florian Pritz <bluewind@server-speed.net>wrote:
From: Florian Pritz <bluewind@xssn.at>
The user adds libaries to the depends array without a version. These must end with .so. Example: depends=(glibc libc.so)
find_sodepends() looks for ELF files (not symlinks because these could point outside of pkgdir) in $pkgdir, extracts the library sonames the binary liks to and outputs depends seperated by spaces. This list contains all libraries needed by the package. Example: libfoo.so=3-64
write_pkginfo() only keeps .so depends with version information and warns the user about unneded ones.
Support-by: Thomas Bächler <thomas@archlinux.org> Support-by: Christoph Schied <Christoph.Schied@uni-ulm.de> Signed-off-by: Florian Pritz <bluewind@server-speed.net> --- scripts/makepkg.sh.in | 41 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 40 insertions(+), 1 deletions(-)
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 0d811b6..422b4c0 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -933,6 +933,31 @@ tidy_install() { fi }
+find_sodepends() { + local sodepends + find $pkgdir -type f | while read filename + do + # get architecture of the file; if soarch is empty it's not an ELF binary + soarch=$(LC_ALL=C readelf -h "$filename" 2>/dev/null | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p')
Can I suggest using a lower level approach less prone to breakage because of a change in output format? It's a little more verbose, but it directly follows the ELF standard: magic=$(dd if="$filename" bs=1 skip=1 count=3 2>/dev/null) [[ "$magic" = ELF ]] || continue read _ elfclass < <(hexdump -s5 -n1 "$filename") case $elfclass in *(0)1) soarch=32 ;; *(0)2) soarch=64 ;; esac [[ $soarch ]] || continue Note: this requires extglob, which we don't currently have enabled in makepkg.
+ [ -n "$soarch" ] || continue + # process all libraries needed by the binary + for sofile in $(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -nr 's/.*Shared library: \[(.*)\].*/\1/p')
This can be read directly from the binary with hexdump/dd as well, but requires a bit more voodoo, as you have to locate the dynamic linking section via the header and then read each null delimited linkage. 2 or more successive null bytes indicates the end of the section. If this is something we want, I can put in the legwork for it.
+ do + # extract the library name: libfoo.so + soname="${sofile%%\.so\.*}.so" + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + if in_array "${soname}" ${depends[@]}; then + if ! in_array "${soname}=${soversion}-${soarch}" ${sodepends[@]}; then + # libfoo.so=1-64 + echo "${soname}=${soversion}-${soarch}" + sodepends=(${sodepends[@]} "${soname}=${soversion}-${soarch}") + fi + fi + done + done +} + find_soprovides() { local soprovides find "$pkgdir" -type f -name \*.so\* | while read filename @@ -989,7 +1014,6 @@ write_pkginfo() { [[ $license ]] && printf "license = %s\n" "${license[@]}" [[ $replaces ]] && printf "replaces = %s\n" "${replaces[@]}" [[ $groups ]] && printf "group = %s\n" "${groups[@]}" - [[ $depends ]] && printf "depend = %s\n" "${depends[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" @@ -997,7 +1021,22 @@ write_pkginfo() { local it
soprovides=$(find_soprovides) + sodepends=$(find_sodepends) provides=("${provides[@]}" ${soprovides}) + depends=("${depends[@]}" ${sodepends}) + + for it in "${depends[@]}"; do + if [[ $it = *.so ]]; then + # check if the entry has been found by find_sodepends + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $sodepends =~ (^|\s)${it}=.* ]]; then + error "$(gettext "Can't find library listed in \$depends: %s")" "$it" + return 1 + fi + else + echo "depend = $it" + fi + done
for it in "${provides[@]}"; do # ignore versionless entires (those come from the PKGBUILD) -- 1.7.3.5