libmakepkg: automatically add library sonames to provides

Message ID 20211212105440.1129363-4-allan@archlinux.org
State New
Headers show
Series libmakepkg: automatically add library sonames to provides | expand

Commit Message

Allan McRae Dec. 12, 2021, 10:54 a.m. UTC
When the option "autodeps" is enabled, makepkg will add provides
entries for libraries found in the directories specified in LIB_DIRS
in makepkg.conf.  The entries LIB_DIRS array have the format
"prefix:directory".  For example, the entry "lib:usr/lib" will search
$pkgdir/usr/lib for library sonames and add "lib:libfoo.so.1" to the
provides array.

Signed-off-by: Allan McRae <allan@archlinux.org>
---
 doc/makepkg.conf.5.asciidoc                   | 11 ++++
 etc/makepkg.conf.in                           |  2 +
 .../libmakepkg/autodep/library_provides.sh.in | 56 +++++++++++++++++++
 scripts/libmakepkg/autodep/meson.build        | 18 ++++++
 scripts/libmakepkg/meson.build                |  1 +
 5 files changed, 88 insertions(+)
 create mode 100644 scripts/libmakepkg/autodep/library_provides.sh.in
 create mode 100644 scripts/libmakepkg/autodep/meson.build

Patch

diff --git a/doc/makepkg.conf.5.asciidoc b/doc/makepkg.conf.5.asciidoc
index 76c27f6a..39c5c808 100644
--- a/doc/makepkg.conf.5.asciidoc
+++ b/doc/makepkg.conf.5.asciidoc
@@ -193,6 +193,11 @@  Options
 		Enable building packages using link time optimization. Adds '-flto'
 		to both CFLAGS and CXXFLAGS.
 
+	*autodep*;;
+		Enable the automatic addition of libraries to the depends and
+		provides arrays. Search library directories are controlled by
+		the LIB_DIRS variable defined below.
+
 **INTEGRITY_CHECK=(**check1 ...**)**::
 	File integrity checks to use. Multiple checks may be specified; this
 	affects both generation and checking. The current valid options are:
@@ -223,6 +228,12 @@  Options
 	that are located in opt/, you may need to add the directory to this
 	array. *NOTE:* Do not add the leading slash to the directory name.
 
+**LIB_DIRS=(**lib:usr/lib ...**)**::
+	If `autodeps` is specified in the `OPTIONS` array, this variable will
+	instruct makepkg where to look to find librarys to add to the `provides`
+	array. The format is "prefix:path", where provides will be added for
+	libraries found in "path" with the specified prefix added.
+
 **PURGE_TARGETS=(**usr/{,share}/info/dir .podlist *.pod...**)**::
 	If `purge` is specified in the `OPTIONS` array, this variable will
 	instruct makepkg which files to remove from the package. This is
diff --git a/etc/makepkg.conf.in b/etc/makepkg.conf.in
index f69a7add..0c911cce 100644
--- a/etc/makepkg.conf.in
+++ b/etc/makepkg.conf.in
@@ -109,6 +109,8 @@  DOC_DIRS=(usr/{,local/}{,share/}{doc,gtk-doc} opt/*/{doc,gtk-doc})
 PURGE_TARGETS=(usr/{,share}/info/dir .packlist *.pod)
 #-- Directory to store source code in for debug packages
 DBGSRCDIR="/usr/src/debug"
+#-- Prefix and directories for library autodeps
+LIB_DIRS=('lib:/usr/lib' 'lib32:/usr/lib32')
 
 #########################################################################
 # PACKAGE OUTPUT
diff --git a/scripts/libmakepkg/autodep/library_provides.sh.in b/scripts/libmakepkg/autodep/library_provides.sh.in
new file mode 100644
index 00000000..5cd497fa
--- /dev/null
+++ b/scripts/libmakepkg/autodep/library_provides.sh.in
@@ -0,0 +1,56 @@ 
+#!/bin/bash
+#
+#   library_provides.sh - Automatically add a packages libraries to provides
+#
+#   Copyright (c) 2021 Pacman Development Team <pacman-dev@lists.archlinux.org>
+#
+#   This program is free software; you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation; either version 2 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+[[ -n "$LIBMAKEPKG_AUTODEP_LIBRARY_PROVIDES_SH" ]] && return
+LIBMAKEPKG_AUTODEP_LIBRARY_PROVIDES_SH=1
+
+LIBRARY=${LIBRARY:-'@libmakepkgdir@'}
+
+autodep_functions+=('library_provides')
+
+library_provides() {
+	if check_option "autodeps" "y"; then
+		for lib in ${LIB_DIRS[@]}; do
+			dir=${lib/*:}
+			prefix=${lib/:*}
+
+			if [[ ! -d "$pkgdir/$dir" ]]; then
+				continue;
+			fi
+
+			mapfile -t filenames < <(find "$pkgdir/$dir" -type f | LC_ALL=C sort)
+
+			for fn in "${filenames[@]}"; do
+				# check we have a shared library
+				if LC_ALL=C readelf -h "$fn" 2>/dev/null | grep -q '.*Type:.*DYN (Shared object file).*'; then
+					# extract library soname
+					local sofile=$(LC_ALL=C readelf -d "$fn" 2>/dev/null | sed -n 's/.*Library soname: \[\(.*\)\].*/\1/p')
+
+					if [[ -z "$sofile" ]]; then
+						# the library is not versioned
+						continue
+					fi
+
+					provides+=("$prefix:$sofile")
+				fi
+			done
+		done
+	fi
+}
diff --git a/scripts/libmakepkg/autodep/meson.build b/scripts/libmakepkg/autodep/meson.build
new file mode 100644
index 00000000..e0af26a6
--- /dev/null
+++ b/scripts/libmakepkg/autodep/meson.build
@@ -0,0 +1,18 @@ 
+libmakepkg_module = 'tidy'
+
+sources = [
+  'library_provides.sh.in',
+
+]
+
+foreach src : sources
+  output_dir = join_paths(get_option('datadir'), 'makepkg', libmakepkg_module)
+
+  custom_target(
+    libmakepkg_module + '_' + src.underscorify(),
+    command : [ SCRIPT_EDITOR, '@INPUT@', '@OUTPUT@' ],
+    input : src,
+    output : '@BASENAME@',
+    install : true,
+    install_dir : output_dir)
+endforeach
diff --git a/scripts/libmakepkg/meson.build b/scripts/libmakepkg/meson.build
index 50eb905b..6e83a4a8 100644
--- a/scripts/libmakepkg/meson.build
+++ b/scripts/libmakepkg/meson.build
@@ -1,4 +1,5 @@ 
 libmakepkg_modules = [
+  { 'name' : 'autodep',       'has_subdir' : true },
   { 'name' : 'buildenv',      'has_subdir' : true },
   { 'name' : 'executable',    'has_subdir' : true },
   { 'name' : 'integrity',     'has_subdir' : true },