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

Florian Pritz bluewind at server-speed.net
Mon Jan 31 14:15:34 EST 2011


From: Florian Pritz <bluewind at xssn.at>

The user adds libaries to the provides array without a version. These
must end with .so.
Example: provides=(readline libreadline.so)

find_soprovides() 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 <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 |   46 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index b1b1b75..0d811b6 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -933,6 +933,33 @@ tidy_install() {
 	fi
 }
 
+find_soprovides() {
+	local soprovides
+	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}" ${soprovides[@]}; then
+					# libfoo.so=1-64
+					echo "${soname}=${soversion}-${soarch}"
+					soprovides=(${soprovides[@]} "${soname}=${soversion}-${soarch}")
+				fi
+			fi
+    fi
+	done
+}
+
 write_pkginfo() {
 	local builddate=$(date -u "+%s")
 	if [[ -n $PACKAGER ]]; then
@@ -965,10 +992,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
+
+	soprovides=$(find_soprovides)
+	provides=("${provides[@]}" ${soprovides})
+
+	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_soprovides
+			# if not, it's unneeded; tell the user so he can remove it
+			if [[ ! $soprovides =~ (^|\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
-- 
1.7.3.5


More information about the pacman-dev mailing list