Hi, I've investigated the testsuite with your feedback and it seems all problems I missed are coming from the line merging old_deplibs into dependency_libs.
It seems using the same loop as the snippet above, ie. checking for absolute path and adding pwd if needed, is enough to fix the absolute path requirement. The test was failing because, fortunately in the test, the referenced static archive was used from a different working directory. Then it was also failing on the test producing libltdl.so. It seems that I misunderstand this part of the code back then and though it would only affect old libraries because the linker would use $deplibs when building the shared library. However, the static archives would still be forwarded to dependency_libs in the final libtool archive because of that, which the testsuite fortunately catched too. By gating the code with a check on library_names (so assuming static archives are squashed into the shared libraries), I can finally pass this last remaining test. Here is a new revision. with this change. The main changes are commit message to reference this issue and this line: + func_append dependency_libs " $old_deplibs" Transformed into: + # Forward old library dependencies only when no shared + # library is being built. When building the shared library, + # the linker uses $deplibs to link the archives into it, but + # then we don't want to add it as transitive dependency. + if test -z "$library_names"; then + for lib in $old_deplibs; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append dependency_libs " $abs" + done + fi I've copied the code above for path handling without accounting whether refactoring could be interesting or not. Regards, -- Alexandre Janniaux Videolabs Le sam. 16 mai 2026 à 11:49, Alexandre Janniaux <[email protected]> a écrit : > Hi, > > Thanks for the review, sorry for the test failure. I'll provide a new > revision of the patches. > > Regards, > -- > Alexandre Janniaux > Videolabs > > Le ven. 15 mai 2026 à 19:59, Ileana Dumitrescu <[email protected]> > a écrit : > >> Follow-up Comment #1, patch #10569 (group libtool): >> >> Thank you for the patches! >> >> Unfortunately, these changes cause several libtool tests to fail on >> GNU/Linux >> due to a relative path of dlopen.a being added to the linking command. I >> converted the dependency_libs path into an absolute path, which fixed >> most of >> the tests, but a different failure was caused in configure-iface.at. I >> will >> try debugging this some more, but I may not be able to fix it before the >> next >> beta/stable releases. If you submit new patch files with a fix before me, >> I >> would be happy to test and hopefully apply them. >> >> >> >> >> _______________________________________________________ >> >> Reply to this item at: >> >> <https://savannah.gnu.org/patch/?10569> >> >> _______________________________________________ >> Message sent via Savannah >> https://savannah.gnu.org/ >> >
From e12afb3e216a015db5d5e7d567ee1fb18f559564 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux <[email protected]> Date: Tue, 6 Apr 2021 10:22:14 +0200 Subject: [PATCH 1/3] ltmain.in: ensure old libraries are not archived MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, adding a static archive library, aka. old library, as a dependency of a new libtool library compiled as a static archive (be it a convenience library or an installed static library) resulted in the dependency archive being added into the target archive as-is. However, linkers are usually not able to use nested archive as-is. It results in errors like these on Linux and Darwin at least: /usr/bin/ld: ./.libs/libfoo.a: member ./.libs/libfoo.a(libbar.a) in archive is not an object or /usr/bin/nm: libbar.a: file format not recognized With libfoo.a being the static libtool target and libbar.a being the nested/linked static library. Libtool has a quite close behaviour with convenience libraries, where the content (objects) of the convenience library are extracted and added back into the new target, but that´s mostly a libtool creation. The static dependencies should not be "linked" into other static libraries as there should not be linking involved, and we don´t want to potentially duplicate symbols like done for the convenience libraries. Instead, keep them in the dependency_libs of the new libtool archive created and forward them until we link a shared library or an executable. We do need to ensure they are referenced with absolute path since we can link from a different folder than the one it was referenced from. We also need to filter out the shared library case since we don't want to include the static archives in dependencies again. The test was marked XFAIL since 2010 because the fix for the nested-archive bug was incomplete. Now that ltmain.in properly forwards old library dependencies instead of archiving them, the test passes: remove the AT_XFAIL_IF and correct the foo.$OBJEXT assertion (objects from the dependency must NOT appear in the target archive). Absolute paths are forwarded as-is like above. Relative paths are transformed into absolute using pwd. The old deplibs are not appended if they have been linked into a shared library output already. --- build-aux/ltmain.in | 24 +++++++++++++++++++++--- tests/archive-in-archive.at | 8 ++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in index 70d0e111..a1d24dd2 100644 --- a/build-aux/ltmain.in +++ b/build-aux/ltmain.in @@ -5816,7 +5816,6 @@ func_mode_link () *.$libext|*.so) # An archive or an explicit shared library. func_append deplibs " $arg" - func_append old_deplibs " $arg" continue ;; @@ -6215,6 +6214,8 @@ func_mode_link () if test conv = "$pass"; then deplibs="$deplib $deplibs" continue + else + func_append old_deplibs " $deplib" fi case $linkmode in lib) @@ -7184,7 +7185,6 @@ func_mode_link () # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output - func_append objs "$old_deplibs" ;; lib) @@ -8952,7 +8952,11 @@ func_mode_link () build_libtool_libs=no ;; *) - oldobjs="$old_deplibs $non_pic_objects" + oldobjs="$non_pic_objects" + # This is not correct to add old_deplibs creating an archive + # so append them only when creating an executable or a shared + # library. + test yes != "$build_old_libs" && oldobjs="$oldobjs $old_deplibs" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience @@ -9213,6 +9217,20 @@ func_mode_link () done dlprefiles=$newdlprefiles fi + + # Forward old library dependencies only when no shared + # library is being built. When building the shared library, + # the linker uses $deplibs to link the archives into it, but + # then we don't want to add it as transitive dependency. + if test -z "$library_names"; then + for lib in $old_deplibs; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append dependency_libs " $abs" + done + fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target diff --git a/tests/archive-in-archive.at b/tests/archive-in-archive.at index d081f57d..b48579ae 100644 --- a/tests/archive-in-archive.at +++ b/tests/archive-in-archive.at @@ -24,9 +24,6 @@ AT_SETUP([static library contains static library]) AT_KEYWORDS([libtool]) -# This test passes with MS lib. -AT_XFAIL_IF([case $AR in ar-lib\ * | *[[/\\]]ar-lib\ *) false;; *) :;; esac]) - AT_DATA([foo.c], [ int foo() { return 1;} @@ -51,7 +48,10 @@ AT_CHECK([$LIBTOOL --mode=link --tag=CC --tag=disable-shared $CC $CFLAGS $LDFLAG AT_CHECK([$LIBTOOL --mode=install cp libbar.la $thisdir], [], [ignore], [ignore]) eval `$EGREP '^(old_library)=' < libbar.la` libbar=$old_library +# The old library (libfoo.a) must NOT be nested inside libbar.a. AT_CHECK([$AR -t $libbar | $GREP $libfoo],[1],[ignore],[ignore]) -AT_CHECK([$AR -t $libbar | $GREP foo.$OBJEXT],[],[ignore],[ignore]) +# Objects from libfoo must NOT be extracted into libbar.a either. +AT_CHECK([$AR -t $libbar | $GREP foo.$OBJEXT],[1],[ignore],[ignore]) +# bar's own object must still be present. AT_CHECK([$AR -t $libbar | $GREP bar.$OBJEXT],[],[ignore],[ignore]) AT_CLEANUP -- 2.53.0
From 87159d043e4f74ab3c24de630682e17c03b1a91f Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux <[email protected]> Date: Tue, 28 Apr 2026 16:11:01 +0200 Subject: [PATCH 2/3] tests: extend archive-in-archive with dependency forwarding check Verify that the old library dependency is recorded in dependency_libs of the target .la file, and that an executable linked against the target can resolve symbols from the forwarded dependency. --- tests/archive-in-archive.at | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/archive-in-archive.at b/tests/archive-in-archive.at index b48579ae..f0e6ff1f 100644 --- a/tests/archive-in-archive.at +++ b/tests/archive-in-archive.at @@ -31,7 +31,14 @@ int foo() { return 1;} AT_DATA([bar.c], [ -int bar() { return 1;} +extern int foo(); +int bar() { return foo();} +]) + +AT_DATA([main.c], +[ +extern int bar(); +int main() { return !bar();} ]) thisdir=`cd . && pwd` @@ -54,4 +61,13 @@ AT_CHECK([$AR -t $libbar | $GREP $libfoo],[1],[ignore],[ignore]) AT_CHECK([$AR -t $libbar | $GREP foo.$OBJEXT],[1],[ignore],[ignore]) # bar's own object must still be present. AT_CHECK([$AR -t $libbar | $GREP bar.$OBJEXT],[],[ignore],[ignore]) +# libfoo must be forwarded in dependency_libs of libbar.la. +AT_CHECK([$GREP 'dependency_libs=.*libfoo' libbar.la],[],[ignore],[ignore]) +# Link an executable against libbar.la; the forwarded dependency must +# allow the linker to resolve foo(). +$CC $CPPFLAGS $CFLAGS -c -o main.$OBJEXT main.c +AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC $CFLAGS $LDFLAGS \ + -o main$EXEEXT main.$OBJEXT libbar.la], + [], [ignore], [ignore]) +LT_AT_EXEC_CHECK([./main]) AT_CLEANUP -- 2.53.0
From 7cb02827c73464916a3e60f8561dfb27457d7394 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux <[email protected]> Date: Fri, 2 Apr 2021 13:14:41 +0200 Subject: [PATCH 3/3] ltmain.in: defer warn dependency to static library When linking old library to any libtool target that is not an executable, libtool warns that it might not be portable, in particular because shared libraries need PIC from the static library to be working. However, when adding an old library as dependency to a static libtool library, there is no linkage, and thus no portability issue, so there's no reason to warn. If the static libtool library is then linked to a shared library, the dependency will be forwarded and the warning will happen at this time. --- build-aux/ltmain.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build-aux/ltmain.in b/build-aux/ltmain.in index a1d24dd2..f64c0222 100644 --- a/build-aux/ltmain.in +++ b/build-aux/ltmain.in @@ -6246,7 +6246,9 @@ func_mode_link () ;; esac if $valid_a_lib; then - func_warning "Linking the shared library $output against the static library $deplib is not portable!" + if test yes != "$build_old_libs"; then + func_warning "Linking the shared library $output against the static library $deplib is not portable!" + fi deplibs="$deplib $deplibs" else func_warning "Trying to link with static lib archive $deplib." -- 2.53.0
