bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gnulib-tool: Fix link errors with a particular set of modules on min


From: Bruno Haible
Subject: Re: gnulib-tool: Fix link errors with a particular set of modules on mingw
Date: Sat, 07 Nov 2020 21:19:15 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-193-generic; KDE/5.18.0; x86_64; ; )

Hi Simon,

> OATH Toolkit uses version-etc but not version-etc-fsf.  The test for
> version-etc pulls in version-etc-fsf into libtests.  Removing the final
> ../../gl/libgnu.la (reverting the effects of your patch) from the
> command line fixes the above link error.
> 
> Gnulib-tool says:
> 
>   if $use_libtests; then
>     # All test programs need to be linked with libtests.a.
>     # It needs to be passed to the linker before ${libname}.${libext}, since
>     # the tests-related modules depend on the main modules.
>     # It also needs to be passed to the linker after ${libname}.${libext}
>     # because the latter might contain incomplete modules (such as the 'error'
>     # module whose dependency to 'progname' is voluntarily omitted).

I see. The omitted dependency 'error' -> 'progname' caused a lot of trouble,
until it was finally eliminated by Pino Toscano in 2016. But for the omitted
dependency 'version-etc' -> 'version-etc-fsf' it's the same thing.

> The comment explains why libtests has to be BEFORE and AFTER libgnu.la
> but not why libgnu.la has to be AFTER libtests.  Your patch introduced
> this -- could the comment be improved explaining the reason?

To me, that's a normal consequence of how linkers work, when you have
a random set of object files in two .a file. If
    a.o needs b.o, b.o needs c.o, c.o needs d.o,
and
    x.a contains a.o and c.o,
    y.a contains b.o and d.o,
then you need to link with
    x.a y.a x.a y.a
until you get all dependencies. And the need of repetitions is potentially
unbounded, if you have a very long chain of dependencies and they are not
well distributed among the .a files. The latter can happen with gnulib
  - because of omitted dependencies (like mentioned above),
  - because of --avoid options passed to gnulib-tool,
  - because of tests modules which enable some C macros in config.h which have
    side effects on the main modules.

> What is the solution here?  Adding yet another occurance of libtests.a
> after the second libgnu.la?  That also fixes it for me.

Thanks for the confirmation that this works. I'm pushing this:


2020-11-07  Bruno Haible  <bruno@clisp.org>

        gnulib-tool: Fix link error with 'version-etc' (regression 2020-05-29).
        Reported by Simon Josefsson in
        <https://lists.gnu.org/archive/html/bug-gnulib/2020-11/msg00032.html>.
        * gnulib-tool (func_emit_tests_Makefile_am): Add libtests.a to
        LDADD a third time, after the second occurrence of ../lib/libgnu.a.
        * pygnulib/GLEmiter.py (tests_Makefile_am): Likewise.

diff --git a/gnulib-tool b/gnulib-tool
index 1ce9c30..8b7e305 100755
--- a/gnulib-tool
+++ b/gnulib-tool
@@ -4170,11 +4170,12 @@ func_emit_tests_Makefile_am ()
     # It needs to be passed to the linker before ${libname}.${libext}, since
     # the tests-related modules depend on the main modules.
     # It also needs to be passed to the linker after ${libname}.${libext}
-    # because the latter might contain incomplete modules (such as the 'error'
-    # module whose dependency to 'progname' is voluntarily omitted).
+    # because the latter might contain incomplete modules (such as the
+    # 'version-etc' module whose dependency to 'version-etc-fsf' is voluntarily
+    # omitted).
     # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, it does
     # not matter.
-    echo "LDADD = libtests.a 
${testsbase_inverse}/${sourcebase-lib}/${libname}.${libext} libtests.a 
${testsbase_inverse}/${sourcebase-lib}/${libname}.${libext} 
\$(LIBTESTS_LIBDEPS)"
+    echo "LDADD = libtests.a 
${testsbase_inverse}/${sourcebase-lib}/${libname}.${libext} libtests.a 
${testsbase_inverse}/${sourcebase-lib}/${libname}.${libext} libtests.a 
\$(LIBTESTS_LIBDEPS)"
   else
     echo "LDADD = ${testsbase_inverse}/${sourcebase-lib}/${libname}.${libext}"
   fi
diff --git a/pygnulib/GLEmiter.py b/pygnulib/GLEmiter.py
index 441d295..107f88c 100644
--- a/pygnulib/GLEmiter.py
+++ b/pygnulib/GLEmiter.py
@@ -1125,14 +1125,15 @@ AC_DEFUN([%V1%_LIBSOURCES], [
 
         if libtests:
             # All test programs need to be linked with libtests.a.
-            # It needs to be passed to the linker before ${libname}.${libext}, 
since
-            # the tests-related modules depend on the main modules.
+            # It needs to be passed to the linker before ${libname}.${libext},
+            # since the tests-related modules depend on the main modules.
             # It also needs to be passed to the linker after 
${libname}.${libext}
             # because the latter might contain incomplete modules (such as the
-            # 'error' module whose dependency to 'progname' is voluntarily 
omitted).
-            # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, 
it does
-            # not matter.
-            emit += 'LDADD = libtests.a %s/%s/%s.%s libtests.a %s/%s/%s.%s 
$(LIBTESTS_LIBDEPS)\n\n' % \
+            # 'version-etc' module whose dependency to 'version-etc-fsf' is
+            # voluntarily omitted).
+            # The LIBTESTS_LIBDEPS can be passed to the linker once or twice, 
it
+            # does not matter.
+            emit += 'LDADD = libtests.a %s/%s/%s.%s libtests.a %s/%s/%s.%s 
libtests.a $(LIBTESTS_LIBDEPS)\n\n' % \
                 (testsbase_inverse, sourcebase, libname, libext,
                  testsbase_inverse, sourcebase, libname, libext)
         else:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]