[pacman-dev] [PATCH] makepkg: rework libdepends

Allan McRae allan at archlinux.org
Sat May 19 09:22:36 EDT 2012


Rewrite the handling of libdepends. The primary advantage are:
 - Moves functionality from write_pkginfo() to find_libdepends().
 - The order of the depends array in the PKGBUILD is kept in the package.
 - An unneeded libdepends is only a warning and not an error. This allows
   putting a libdepend on a library that is dlopened.
 - It is now modular so can be extended to library types other than
   ELF *.so.
 - Finding the list of libraries a package depends only occurs when a
   libdepend is specified in the depends array.

Signed-off-by: Allan McRae <allan at archlinux.org>
---
 scripts/makepkg.sh.in |  126 +++++++++++++++++++++++++++++--------------------
 1 file changed, 76 insertions(+), 50 deletions(-)

diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 8d018c0..8930ec4 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -1131,32 +1131,76 @@ tidy_install() {
 }
 
 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?(+(.+([0-9])))}".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
-					printf "%s" "${soname}=${soversion}-${soarch}"
-					libdepends+=("${soname}=${soversion}-${soarch}")
+	local d sodepends;
+
+	sodepends=0;
+	for d in "${depends[@]}"; do
+		if [[ $d = *.so ]]; then
+			sodepends=1;
+			break;
+		fi
+	done
+
+	if (( sodepends == 0 )); then
+		printf '%s\n' "${depends[@]}"
+		return;
+	fi
+
+	local libdeps;
+	declare -A libdeps;
+
+	if (( sodepends == 1 )); then
+		local filename soarch sofile soname soversion
+
+		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?(+(.+([0-9])))}".so
+				# extract the major version: 1
+				soversion="${sofile##*\.so\.}"
+
+				if [[ ${libdeps[$soname]} ]]; then
+					if [[ ! ${libdeps[$soname]} = *${soversion}-${soarch}* ]]; then
+						libdeps[$soname]+=" ${soversion}-${soarch}"
+					fi
+				else
+					libdeps[$soname]="${soversion}-${soarch}"
 				fi
-			fi
-		done
+			done
+		done < <(find "$pkgdir" -type f -perm -u+x)
+	fi
+
+	local libdepends v
+	for d in "${depends[@]}"; do
+		case "$d" in
+			*.so)
+				if [[ ${libdeps[$d]} ]]; then
+					for v in ${libdeps[$d]}; do
+						libdepends+=("$d=$v")
+					done
+				else
+					warning "$(gettext "Library listed in %s is not required by any files: %s")" "'depends'" "$d"
+					libdepends+=("$d")
+				fi
+				;;
+			*)
+				libdepends+=("$d")
+				;;
+		esac
 	done
+
+	printf '%s\n' "${libdepends[@]}"
 }
 
+
 find_libprovides() {
-	local libprovides missing
+	local p libprovides missing
 	for p in "${provides[@]}"; do
 		missing=0
 		case "$p" in
@@ -1246,38 +1290,20 @@ write_pkginfo() {
 	printf "size = %s\n" "$size"
 	printf "arch = %s\n" "$pkgarch"
 
-	[[ $license ]]    && printf "license = %s\n"   "${license[@]}"
-	[[ $replaces ]]   && printf "replaces = %s\n"  "${replaces[@]}"
-	[[ $groups ]]     && printf "group = %s\n"     "${groups[@]}"
-	[[ $optdepends ]] && printf "optdepend = %s\n" "${optdepends[@]//+([[:space:]])/ }"
-	[[ $conflicts ]]  && printf "conflict = %s\n"  "${conflicts[@]}"
-
 	mapfile -t provides < <(find_libprovides)
-	[[ $provides ]]   && printf "provides = %s\n"  "${provides[@]}"
-
-	[[ $backup ]]     && printf "backup = %s\n"    "${backup[@]}"
-
+	mapfile -t depends < <(find_libdepends)
+
+	[[ $license ]]     && printf "license = %s\n"    "${license[@]}"
+	[[ $replaces ]]    && printf "replaces = %s\n"   "${replaces[@]}"
+	[[ $groups ]]      && printf "group = %s\n"      "${groups[@]}"
+	[[ $conflicts ]]   && printf "conflict = %s\n"   "${conflicts[@]}"
+	[[ $provides ]]    && printf "provides = %s\n"   "${provides[@]}"
+	[[ $backup ]]      && printf "backup = %s\n"     "${backup[@]}"
+	[[ $depends ]]     && printf "depend = %s\n"     "${depends[@]}"
+	[[ $optdepends ]]  && printf "optdepend = %s\n"  "${optdepends[@]//+([[:space:]])/ }"
+	[[ $makedepends ]] && printf "makedepend = %s\n" "${makedepends[@]}"
 
 	local it
-	mapfile -t libdepends < <(find_libdepends)
-	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
-			printf -v re '(^|\s)%s=.*' "$it"
-			if [[ ! $libdepends =~ $re ]]; then
-				error "$(gettext "Cannot find library listed in %s: %s")" "'depends'" "$it"
-				return 1
-			fi
-		else
-			printf "depend = %s\n" "$it"
-		fi
-	done
-
-	[[ $makedepends ]]  && printf "makedepend = %s\n"  "${makedepends[@]}"
-
 	for it in "${packaging_options[@]}"; do
 		check_option "$it" "y"
 		case $? in
-- 
1.7.10.2



More information about the pacman-dev mailing list