[pacman-dev] [PATCH] WIP: makepkg: rework libprovides
This reworks the implmentation of libprovides for the following benefits: - Moves functionality from write_pkginfo() to find_libprovides() - Only calculates the version for libraries specifically requested and not all libraries. This has the disadvantage of running find over the $pkgdir for as many libraries as needed, but is unlikely to be an issue due to caching. - The order of the provides array in the PKGBUILD is kept in the package - There are more warning messages when things fail and those that were there are no longer errors (as I do not think failure of libprovides should result in complete packaging failure) - It is now modular so can be easy extended to other library types other than ELF *.so. Signed-off-by: Allan McRae <allan@archlinux.org> --- I cut and pasted the actual finding of the soarch/soversion etc, but that obviously needs fixed. WTF is the comment "# 64" supposed to mean? I also would like documentation about why we need the [ -z "$sofile" ] test (reminder: needs adjusted to double bracket format). Also, why do we extract "soname" when that should be what was already given in the provides array? scripts/makepkg.sh.in | 83 ++++++++++++++++++++++++++----------------------- 1 files changed, 44 insertions(+), 39 deletions(-) diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 7527329..dae229a 100644 --- a/scripts/makepkg.sh.in +++ b/scripts/makepkg.sh.in @@ -980,30 +980,47 @@ find_libdepends() { } 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}") + local libprovides missing + for p in ${provides[@]}; do + missing=0 + case "$p" in + *.so) + filename=$(find "$pkgdir" -type f -name $p\*) + if [[ $filename ]]; then + # 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\.}" + + libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}") + else + warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" + libprovides=(${libprovides[@]} "$p") + fi + else + libprovides=(${libprovides[@]} "$p") + missing=1 fi - fi - fi + ;; + *) + libprovides=(${libprovides[@]} "$p") + ;; + esac + + if (( missing )); then + warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p" + fi done + + echo ${libprovides[@]} } write_pkginfo() { @@ -1037,13 +1054,15 @@ write_pkginfo() { [[ $groups ]] && printf "group = %s\n" "${groups[@]}" [[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]}" [[ $conflicts ]] && printf "conflict = %s\n" "${conflicts[@]}" + + provides=("$(find_libprovides)") + [[ $provides ]] && printf "provides = %s\n" "${provides[@]}" + [[ $backup ]] && printf "backup = %s\n" "${backup[@]}" - local it - libprovides=$(find_libprovides) + local it libdepends=$(find_libdepends) - provides=("${provides[@]}" ${libprovides}) depends=("${depends[@]}" ${libdepends}) for it in "${depends[@]}"; do @@ -1059,20 +1078,6 @@ write_pkginfo() { fi done - 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 not find library listed in %s: %s")" "'provides'" "$it" - return 1 - fi - else - echo "provides = $it" - fi - done - for it in "${packaging_options[@]}"; do local ret="$(check_option $it)" if [[ $ret != "?" ]]; then -- 1.7.5.4
On 16.06.2011 10:59, Allan McRae wrote:
WTF is the comment "# 64" supposed to mean?
That is an example content of the soarch variable below (someone requested those once).
I also would like documentation about why we need the [ -z "$sofile" ] test (reminder: needs adjusted to double bracket format).
Shared objects don't have to have a SONAME and I've noticed packages that contain .so files without that field, for example libreoffice (/usr/lib/libreoffice/basis3.4/program/libucbhelper4gcc3.so; there are more).
Also, why do we extract "soname" when that should be what was already given in the provides array?
It was needed before you changed the patch. I think you can remove it now, but I don't know if it's possible that the soname and the file name differ.
+ local libprovides missing + for p in ${provides[@]}; do + missing=0 + case "$p" in + *.so) + filename=$(find "$pkgdir" -type f -name $p\*) + if [[ $filename ]]; then
find could return multiple files. For example Maemo's libcurl package ships libcurl.so.3 and libcurl.so.4. Just use a for loop and get rid of the [[ $filename ]] check since the loop won't run without files.
+ # 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\.}" + + libprovides=(${libprovides[@]} "${soname}=${soversion}-${soarch}") + else + warning "$(gettext "Library listed in %s is not a shared object: %s")" "'provides'" "$p" + libprovides=(${libprovides[@]} "$p") + fi + else + libprovides=(${libprovides[@]} "$p") + missing=1 fi - fi - fi + ;; + *) + libprovides=(${libprovides[@]} "$p") + ;; + esac + + if (( missing )); then + warning "$(gettext "Can not find library listed in %s: %s")" "'provides'" "$p" + fi done + + echo ${libprovides[@]} }
-- Florian Pritz
participants (2)
-
Allan McRae
-
Florian Pritz