local it
@@ -934,7 +957,14 @@ write_pkginfo() {
echo "group = $it" >>.PKGINFO
done
for it in "${depends[@]}"; do
- echo "depend = $it" >>.PKGINFO
+ if grep -q ".*.so$" <<< "$it"; then
+ if ! grep -q "(^|s)${it}=.*" <<< $sodepends; then
+ error "$(gettext "Can't find library listed in $depends: %s")" "$it"
+ return 1
+ fi
+ else
+ echo "depend = $it" >>.PKGINFO
+ fi
done
for it in "${optdepends[@]}"; do
echo "optdepend = $it" >>.PKGINFO
--
1.7.0.4
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index cf7dbb9..a851983 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -917,6 +917,27 @@ tidy_install() {
fi
}
+find_sodepends() {
+ local sodepends
+ find $pkgdir -type f | while read filename
+ do
+ soarch="$(objdump -a "$filename" 2>/dev/null |
+ sed -rn 's/.* file format elf[0-9]+-(.*)$/1/p' | tr - _)_$(uname -s)"
+ [ -n "$soarch" ] || continue
+ for sofile in $(readelf -d "$filename" 2> /dev/null | sed -nr 's/.*Shared library: [(.*)].*/1/p')
+ do
+ soname=$(sed -rn 's/(.*).so.*/1.so/p' <<< "$sofile")
+ soversion=$(sed -rn 's/.*.so.(.*)/1/p' <<< "$sofile")
+ if in_array "${soname}" ${depends[@]}; then
+ if ! in_array "${soname}=${soversion}-${soarch}" ${sodepends[@]}; then
+ 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
@@ -969,7 +990,6 @@ write_pkginfo() {
[[ $license ]] && printf "license = %s
" "${license[@]}"
[[ $replaces ]] && printf "replaces = %s
" "${replaces[@]}"
[[ $groups ]] && printf "group = %s
" "${groups[@]}"
- [[ $depends ]] && printf "depend = %s
" "${depends[@]}"
[[ $optdepends ]] && printf "optdepend = %s
" "${optdepends[@]}"
[[ $conflicts ]] && printf "conflict = %s
" "${conflicts[@]}"
[[ $backup ]] && printf "backup = %s
" "${backup[@]}"
@@ -977,7 +997,20 @@ write_pkginfo() {
local it
soprovides=$(find_soprovides)
+ sodepends=$(find_sodepends)
provides=("${provides[@]}" ${soprovides})
+ depends=("${depends[@]}" ${sodepends})
+
+ for it in "${depends[@]}"; do
+ if grep -q ".*.so$" <<< "$it"; then
+ if ! grep -q "(^|s)${it}=.*" <<< $sodepends; 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
if grep -q ".*.so$" <<< "$it"; then
--
1.7.3.5
01-31-2011, 06:15 PM
Florian Pritz
makepkg: add sodepends support
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.
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')
+ [ -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')
+ 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
" "${license[@]}"
[[ $replaces ]] && printf "replaces = %s
" "${replaces[@]}"
[[ $groups ]] && printf "group = %s
" "${groups[@]}"
- [[ $depends ]] && printf "depend = %s
" "${depends[@]}"
[[ $optdepends ]] && printf "optdepend = %s
" "${optdepends[@]}"
[[ $conflicts ]] && printf "conflict = %s
" "${conflicts[@]}"
[[ $backup ]] && printf "backup = %s
" "${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
01-31-2011, 08:35 PM
dave reisner
makepkg: add sodepends support
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:
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
" "${license[@]}"
> [[ $replaces ]] && printf "replaces = %s
" "${replaces[@]}"
> [[ $groups ]] && printf "group = %s
" "${groups[@]}"
> - [[ $depends ]] && printf "depend = %s
" "${depends[@]}"
> [[ $optdepends ]] && printf "optdepend = %s
" "${optdepends[@]}"
> [[ $conflicts ]] && printf "conflict = %s
" "${conflicts[@]}"
> [[ $backup ]] && printf "backup = %s
" "${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
>
>
02-01-2011, 01:51 PM
Florian Pritz
makepkg: add sodepends support
On 31.01.2011 22:35, dave reisner wrote:
>> + 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
And I already though the current implementation is too obfuscated...
If you really want to do that, please move it to a script/binary with a
few options so we can just get exactly the strings we need, but keep
makepkg readable.