build: add support for fixing up library soname
authorFelix Fietkau <nbd@nbd.name>
Fri, 12 Feb 2021 08:56:56 +0000 (09:56 +0100)
committerFelix Fietkau <nbd@nbd.name>
Sun, 14 Feb 2021 18:41:51 +0000 (19:41 +0100)
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@nbd.name>
include/package-ipkg.mk
include/package.mk
rules.mk
scripts/set-abi-version.sh [new file with mode: 0755]

index ead4b5742cb508676b5fbd0238fd969a75f5e0be..fb1b7549fbf801319c0fb4fc5a6f4d41856a4fe5 100644 (file)
@@ -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
index d38d52908ef3075ea2f5727e6817b2aabb7696d5..0f1dd5cc5069dc4586fd5a0e1604eed265879e0c 100644 (file)
@@ -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, \
index cbe1b0cb4c7f6fa9753f30ae90b2a7e1f08f7a83..c6bd7327c5857d2eac0771e23ad23a666764c8db 100644 (file)
--- 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 (executable)
index 0000000..a61c842
--- /dev/null
@@ -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
+)