bug#54726: when linking a shared library on Linux, libtool 2.4.6 ignores libfoo.so arguments

Nicolas Boulenguez <[email protected]> Tue, 5 Apr 2022 12:50:59 +0200
Newsgroups gmane.comp.gnu.libtool.bugs
Message-ID <YkwfE+ADs54LpIHz@pegase>
Hello.

When linking a shared library or a program against a (locally built, not
installed) foo library, it is recommended to prefer
  dir/libfoo.so
over
  -Ldir -lfoo
which only adds complexity and unwanted ambiguity (for example,
/usr/lib/libfoo.{a,so} may silently be selected if dir/libfoo.so is
unexpectedly missing).

Libtool recognizes such options when linking a program, but ignores
them when linking a shared library.

The attached reproducer
* builds with -Ldir -lfoo in order to ensure that the sources are
  correct
* demonstrates the link failure with a direct path
* builds with the attached patch applied and a direct path

Just in case it helps, the original bug report is here:
Bug-Debian: https://bugs.debian.org/960469

Thanks.

_______________________________________________
Bug-libtool mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-libtool
draft960469.diff (text/x-diff, 1.1 KB)
Description: allow dir/libfoo.so as argument when linking a shared library
 This already works for programs, and is actually recommended for
 uninstalled yet libraries instead of the more ambiguous -Ldir -lfoo.
Bug-Debian: https://bugs.debian.org/960469
Author: Nicolas Boulenguez <[email protected]>

--- a/build-aux/ltmain.in
+++ b/build-aux/ltmain.in
@@ -5517,6 +5517,13 @@
 	continue
 	;;
 
+      *.so)
+	# An explicit path to a shared library.
+	func_append deplibs " $arg"
+	func_append old_deplibs " $arg"
+	continue
+	;;
+
       *.la)
 	# A libtool-controlled library.
 
@@ -5871,6 +5878,16 @@
 	  func_resolve_sysroot "$deplib"
 	  lib=$func_resolve_sysroot_result
 	  ;;
+	*.so)
+	  # FIXME: linkmode=prog copies .so arguments without this stanza. Duplicate code?
+	  if test lib = "$linkmode"; then
+	    deplibs="$deplib $deplibs"
+	    test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+	  elif test prog != "$linkmode"; then
+	    func_warning "shared library '$deplib' ignored for archive/object"
+	  fi
+	  continue
+	  ;;
 	*.$libext)
 	  if test conv = "$pass"; then
 	    deplibs="$deplib $deplibs"
reproducer (text/plain, 1.9 KB)
#!/bin/sh
# Demonstrate the issue and check the fix.
# Tested with GNU libtool 2.4.6 on Debian 5.10/GNU Linux x86_64.
fix=draft960469.diff
tmpdir=reproducer_temporary_directory

set -C -e -f -u -v

mkdir $tmpdir
cd $tmpdir

recreate_template() {
    find . -mindepth 1 -delete

    cat > hello.c <<EOF
#include <stdio.h>
void hello (void) {
  printf ("If you are reading this, all probably went OK.\n");
}
EOF

    cat > redirect.c <<EOF
void hello (void);
void redirect (void) {
  hello ();
}
EOF

    cat > main.c <<EOF
void redirect (void);
int main (void) {
  redirect ();
  return 0;
}
EOF

    cat > configure.ac <<EOF
AC_INIT([foo], [0.0.0])
AC_CONFIG_MACRO_DIRS([m4])
AM_INIT_AUTOMAKE([foreign])
LT_INIT
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
EOF

    cat > Makefile.am <<EOF
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = libredirect.la
main_LDFLAGS = -Wl,-rpath-link=.

lib_LTLIBRARIES = libredirect.la
libredirect_la_SOURCES = redirect.c

# For unrelated reasons, libhello is unable to use libtool.
libhello.so: CFLAGS += -fPIC
libhello.so: hello.o
	\$(LINK.c) -shared -o \$@ \$^
EOF

}

# Pass --no-undefined to the linker so that the bug is reported soon.
# Without it, libtool would fail later when trying to link main.o.
export LDFLAGS=-Wl,--no-undefined

# Traditional way (-L. -l:libhello.so).  Should succeed.
recreate_template
echo 'libredirect_la_LIBADD = -L. -l:libhello.so'      >> Makefile.am
echo 'EXTRA_libredirect_la_DEPENDENCIES = libhello.so' >> Makefile.am
autoreconf -i
./configure
make
LD_LIBRARY_PATH=. ./main

# Recommended way (libhello.so).  Currently fails.
recreate_template
echo 'libredirect_la_LIBADD = libhello.so' >> Makefile.am
autoreconf -i
./configure
! make

# Recommended way, with libtool patched.  Should succeed.
recreate_template
echo 'libredirect_la_LIBADD = libhello.so' >> Makefile.am
autoreconf -i
./configure
patch -p2 libtool ../$fix
make
LD_LIBRARY_PATH=. ./main