From 79f1a3c4a17223af2bfe35802c50e1ae431d25b5 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Wed, 10 Feb 2010 17:07:30 +0100 Subject: [PATCH 1/3] makepkg: add libprovides support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user adds libaries to the provides array without a version. These must end with .so. Example: provides=(readline libreadline.so) find_libprovides() looks for .so files (not symlinks because these could point outside of pkgdir) in $pkgdir, extracts the library soname (ld links the binary to this name) and outputs provides seperated by spaces. This list contains all libraries provided by the package. Example: libfoo.so=3-64 write_pkginfo() only keeps .so provides with version information and warns the user about unneded ones. Support-by: Thomas Bächler Support-by: Christoph Schied Signed-off-by: Florian Pritz --- scripts/makepkg.sh.in | 46 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index b0d0c235..6855aa6f 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -932,6 +932,33 @@ tidy_install() { fi } +find_libprovides() { + local libprovides + find "$pkgdir" -type f -name \*.so\* | while read filename + do + # check if we really have a shared object + if LC_ALL=C readelf -h "$filename" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then + # 64 + soarch=$(LC_ALL=C readelf -h "$filename" | sed -n 's/.*Class.*ELF\(32\|64\)/\1/p') + # get the string binaries link to: libfoo.so.1.2 -> libfoo.so.1 + sofile=$(LC_ALL=C readelf -d "$filename" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p') + [ -z "$sofile" ] && sofile="${$filename##*/}" + + # extract the library name: libfoo.so + soname="${sofile%%\.so\.*}.so" + # extract the major version: 1 + soversion="${sofile##*\.so\.}" + if in_array "${soname}" ${provides[@]}; then + if ! in_array "${soname}=${soversion}-${soarch}" ${libprovides[@]}; then + # libfoo.so=1-64 + echo "${soname}=${soversion}-${soarch}" + libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}") + fi + fi + fi + done +} + write_pkginfo() { local builddate=$(date -u "+%s") if [[ -n $PACKAGER ]]; then @@ -964,10 +991,27 @@ write_pkginfo() { [[ $depends ]] && printf "depend = %s\n" "${depends[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" - [[ $provides ]] && printf "provides = %s\n" "${provides[@]}" [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" local it + + libprovides=$(find_libprovides) + provides=("${provides[@]}" ${libprovides}) + + for it in "${provides[@]}"; do + # ignore versionless entires (those come from the PKGBUILD) + if [[ $it = *.so ]]; then + # check if the entry has been found by find_libprovides + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $libprovides =~ (^|\s)${it}=.* ]]; then + error "$(gettext "Can't find library listed in \$provides: %s")" "$it" + return 1 + fi + else + echo "provides = $it" + fi + done + for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then From 73d5eb1edf03e628ca1d3a09168e4e940adea914 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Wed, 10 Feb 2010 17:11:37 +0100 Subject: [PATCH 2/3] makepkg: add libdepends support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user adds libaries to the depends array without a version. These must end with .so. Example: depends=(glibc libc.so) find_libdepends() looks for ELF files (not symlinks because these could point outside of pkgdir) in $pkgdir, extracts the library sonames the binary links 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 Support-by: Christoph Schied Signed-off-by: Florian Pritz --- scripts/makepkg.sh.in | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 6855aa6f..34be1e69 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -932,6 +932,31 @@ tidy_install() { fi } +find_libdepends() { + local libdepends + find "$pkgdir" -type f -perm -u+x | 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}" ${libdepends[@]}; then + # libfoo.so=1-64 + echo "${soname}=${soversion}-${soarch}" + libdepends=(${libdepends[@]} "${soname}=${soversion}-${soarch}") + fi + fi + done + done +} + find_libprovides() { local libprovides find "$pkgdir" -type f -name \*.so\* | while read filename @@ -988,7 +1013,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[@]}" @@ -996,7 +1020,22 @@ write_pkginfo() { local it libprovides=$(find_libprovides) + libdepends=$(find_libdepends) provides=("${provides[@]}" ${libprovides}) + depends=("${depends[@]}" ${libdepends}) + + for it in "${depends[@]}"; do + if [[ $it = *.so ]]; then + # check if the entry has been found by find_libdepends + # if not, it's unneeded; tell the user so he can remove it + if [[ ! $libdepends =~ (^|\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) From 5689478c68bdda8ecbe0eae9a5bd28b072632b26 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Sat, 4 Jun 2011 17:28:45 +0200 Subject: [PATCH 3/3] doc/PKGBUILD: document libdeps Signed-off-by: Florian Pritz --- doc/PKGBUILD.5.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/PKGBUILD.5.txt b/doc/PKGBUILD.5.txt index c0fa5948..b9b7855b 100644 --- a/doc/PKGBUILD.5.txt +++ b/doc/PKGBUILD.5.txt @@ -150,6 +150,11 @@ name. The syntax is: `source=('filename::url')`. form 'name<>version', where <> is one of five comparisons: >= (greater than or equal to), <= (less than or equal to), = (equal to), > (greater than), or < (less than). ++ +If the dependency name appears to be a library (ends with .so), makepkg will +try to find a binary that depends on the library in the built package and +append the version needed by the binary. Appending the version yourself +disables auto detection. *makedepends (array)*:: An array of packages that this package depends on to build, but are not @@ -186,6 +191,10 @@ name. The syntax is: `source=('filename::url')`. dependency of other packages. Provisions involving the '>' and '<' operators are invalid as only specific versions of a package may be provided. ++ +If the provision name appears to be a library (ends with .so), makepkg will +try to find the library in the built package and append the correct +version. Appending the version yourself disables auto detection. *replaces (array)*:: An array of packages that this package should replace, and can be used