[pacman-dev] [PATCH 2/2] makepkg: add sodepends support

dave reisner d at falconindy.com
Mon Jan 31 16:35:54 EST 2011


On Mon, Jan 31, 2011 at 2:15 PM, Florian Pritz <bluewind at server-speed.net>wrote:

> From: Florian Pritz <bluewind at 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 at archlinux.org>
> Support-by: Christoph Schied <Christoph.Schied at uni-ulm.de>
> Signed-off-by: Florian Pritz <bluewind at 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
>
>


More information about the pacman-dev mailing list