[PATCH 2/5] build: add support for fixing up library soname

Felix Fietkau nbd at nbd.name
Fri Feb 12 07:56:13 EST 2021


This makes it possible to declare a package ABI_VERSION independent from the
upstream soname by setting PKG_ABI_VERSION in the package makefile.
The library filename is fixed up for files installed to packages and to the
staging dir. References to the original from executables within the same
package are also fixed up

Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 include/package-ipkg.mk    |  5 +++
 include/package.mk         |  2 ++
 rules.mk                   |  6 ++++
 scripts/set-abi-version.sh | 73 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+)
 create mode 100755 scripts/set-abi-version.sh

diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk
index ead4b5742cb5..fb1b7549fbf8 100644
--- a/include/package-ipkg.mk
+++ b/include/package-ipkg.mk
@@ -152,6 +152,7 @@ ifeq ($(DUMP),)
 	mkdir -p $(PKG_BUILD_DIR)/.pkgdir/$(1)
 	$(call Package/$(1)/install,$(PKG_BUILD_DIR)/.pkgdir/$(1))
 	$(call Package/$(1)/install_lib,$(PKG_BUILD_DIR)/.pkgdir/$(1))
+	$(if $(PKG_ABI_VERSION),$(SET_ABI_VERSION) "$(PKG_ABI_VERSION)" "$(PKG_BUILD_DIR)/.pkgdir/$(1)" "$(STAGING_DIR)/packages/$(STAGING_FILES_LIST)")
 	touch $$@
 
     $(STAGING_DIR_ROOT)/stamp/.$(1)_installed: $(PKG_BUILD_DIR)/.pkgdir/$(1).installed
@@ -191,11 +192,15 @@ $(_endef)
     $$(IPKG_$(1)) : export DESCRIPTION=$$(Package/$(1)/description)
     $$(IPKG_$(1)) : export PATH=$$(TARGET_PATH_PKG)
     $$(IPKG_$(1)) : export PKG_SOURCE_DATE_EPOCH:=$(PKG_SOURCE_DATE_EPOCH)
+    ifdef Build/InstallDev
+      $$(IPKG_$(1)): $(STAMP_INSTALLED)
+    endif
     $(PKG_INFO_DIR)/$(1).provides $$(IPKG_$(1)): $(STAMP_BUILT) $(INCLUDE_DIR)/package-ipkg.mk
 	@rm -rf $$(IDIR_$(1)); \
 		$$(call remove_ipkg_files,$(1),$$(call opkg_package_files,$(call gen_ipkg_wildcard,$(1))))
 	mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/CONTROL $(PKG_INFO_DIR)
 	$(call Package/$(1)/install,$$(IDIR_$(1)))
+	$(if $(PKG_ABI_VERSION),$(SET_ABI_VERSION) "$(PKG_ABI_VERSION)" "$$(IDIR_$(1))" "$(STAGING_DIR)/packages/$(STAGING_FILES_LIST)")
 	$(if $(Package/$(1)/install-overlay),mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/rootfs-overlay)
 	$(call Package/$(1)/install-overlay,$$(IDIR_$(1))/rootfs-overlay)
 	-find $$(IDIR_$(1)) -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| $(XARGS) rm -rf
diff --git a/include/package.mk b/include/package.mk
index b23826bd7817..2ca0c54274d7 100644
--- a/include/package.mk
+++ b/include/package.mk
@@ -178,6 +178,7 @@ Build/Exports=$(Build/Exports/Default)
 define Build/CoreTargets
   STAMP_PREPARED:=$$(STAMP_PREPARED)
   STAMP_CONFIGURED:=$$(STAMP_CONFIGURED)
+  PKG_ABI_VERSION:=$$(PKG_ABI_VERSION)
 
   $(if $(QUILT),$(Build/Quilt))
   $(call Build/Autoclean)
@@ -236,6 +237,7 @@ define Build/CoreTargets
 			"$(STAGING_DIR)/packages/$(STAGING_FILES_LIST)" \
 			"$(STAGING_DIR)"; \
 	fi
+	$(if $(PKG_ABI_VERSION),$(SET_ABI_VERSION) "$(PKG_ABI_VERSION)" $(TMP_DIR)/stage-$(PKG_DIR_NAME))
 	if [ -d $(TMP_DIR)/stage-$(PKG_DIR_NAME) ]; then \
 		(cd $(TMP_DIR)/stage-$(PKG_DIR_NAME); find ./ > $(TMP_DIR)/stage-$(PKG_DIR_NAME).files); \
 		$(call locked, \
diff --git a/rules.mk b/rules.mk
index cbe1b0cb4c7f..c6bd7327c585 100644
--- a/rules.mk
+++ b/rules.mk
@@ -339,6 +339,10 @@ else
     $(SCRIPT_DIR)/rstrip.sh
 endif
 
+SET_ABI_VERSION= \
+    PATCHELF="$(STAGING_DIR_HOST)/bin/patchelf" \
+	$(SCRIPT_DIR)/set-abi-version.sh
+
 ifeq ($(CONFIG_IPV6),y)
   DISABLE_IPV6:=
 else
@@ -428,6 +432,8 @@ $(shell \
 )
 endef
 
+abi_version_str = $(subst -,,$(subst _,,$(subst .,,$(1))))
+
 COMMITCOUNT = $(if $(DUMP),0,$(call commitcount))
 AUTORELEASE = $(if $(DUMP),0,$(call commitcount,1))
 
diff --git a/scripts/set-abi-version.sh b/scripts/set-abi-version.sh
new file mode 100755
index 000000000000..a61c842c6dcb
--- /dev/null
+++ b/scripts/set-abi-version.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+# 
+# Copyright (C) 2020 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+SELF=${0##*/}
+
+[ -n "$PATCHELF" ] || {
+  echo "$SELF: patchelf command not defined (PATCHELF variable not set)"
+  exit 1
+}
+
+ABI_VER="$1"
+PATCH_DIR="$2"
+REF_LIST="$3"
+
+[ -n "$ABI_VER" -a -n "$PATCH_DIR" ] || {
+	echo "$SELF: no ABI version or files/directories specified"
+	echo "usage: $SELF <VERSION> [<PATH>...]"
+	exit 1
+}
+
+cmd() {
+	echo "$@" >&2
+	"$@" || exit 1
+}
+
+gen_lib_list() {
+	while read F; do
+		F="${F##*/}"
+		case "$F" in
+			lib*.so*);;
+			*) continue;;
+		esac
+		echo -n "$F:"
+	done < "$REF_LIST"
+}
+
+find "$PATCH_DIR" -type f -a -name 'lib*.so*' | \
+(
+	while read F; do
+		NEW_F="${F%%.so*}.so.$ABI_VER"
+		NEW_NAME="${NEW_F##*/}"
+		[ "$NEW_F" != "$F" ] || continue
+		cmd mv "$F" "$NEW_F"
+		[ "$REF_LIST" ] || cmd ln -s "$NEW_NAME" "$F"
+		cmd $PATCHELF --set-soname "$NEW_NAME" "$NEW_F"
+	done
+)
+
+[ -n "$REF_LIST" ] || exit 0
+
+LIBS="$(gen_lib_list)"
+LIBS="${LIBS%%:}"
+find "$PATCH_DIR" -type f -a -exec file {} \; | \
+  sed -n -e 's/^\(.*\):.*ELF.*\(executable\|relocatable\|shared object\).*,.*/\1:\2/p' | \
+(
+	IFS=":"
+	while read F S; do
+		$PATCHELF --print-needed "$F" | while read L; do
+			BASE_L="${L%%.so*}"
+			for lib in $LIBS; do
+				base_lib="${lib%%.so*}"
+				[ "$BASE_L" = "$base_lib" ] || continue
+				[ "$l" = "$lib" ] && continue
+				cmd $PATCHELF --replace-needed "$L" "$lib" "$F"
+			done
+		done
+	done
+	true
+)
-- 
2.28.0




More information about the openwrt-devel mailing list