Dear Recipient,

This is to inform you that the bug that you reported, bug#60508, has been resolved. The patch is attached for your convenience. Thank you for reporting.

--
With Valediction,
Kamila Szewczyk (https://iczelia.net)

From c64b7e696a9f7abf9be1ed11f83255ec16aefaa1 Mon Sep 17 00:00:00 2001
From: Kamila Szewczyk <[email protected]>
Date: Mon, 19 Oct 2026 00:42:45 +0200
Subject: [PATCH] automake: fix order-dependent object dependencies
 (bug#60508).

* bin/automake.in (handle_link_dependencies): Generate dependencies after all target object lists are defined. (handle_lib_objects): Keep replacement-object handling separate.
* t/ar-dependencies.sh: Add regression coverage.
* t/list-of-tests.mk: Register it.
* NEWS: Mention the fix.
---
 NEWS                 |  4 +++
 bin/automake.in      | 81 ++++++++++++++++++++++++++++----------------
 t/ar-dependencies.sh | 73 +++++++++++++++++++++++++++++++++++++++
 t/list-of-tests.mk   |  1 +
 4 files changed, 129 insertions(+), 30 deletions(-)
 create mode 100644 t/ar-dependencies.sh

diff --git a/NEWS b/NEWS
index a3731365b..afe4e3d13 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,10 @@ New in 1.20 (????-??-??):
 
 * Bugs fixed
 
+  - Dependencies on another target's objects in LIBADD or LDADD are now
+    tracked regardless of the order in which targets are processed.
+    (bug#60508)
+
   - distcheck now detects symbolic links left in the installation tree
     after uninstall, including dangling links.
 
diff --git a/bin/automake.in b/bin/automake.in
index 783469353..8c9f6e53e 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -99,6 +99,7 @@ sub handle_java ();
 sub handle_languages ();
 sub handle_libraries ();
 sub handle_libtool ();
+sub handle_link_dependencies ();
 sub handle_ltlibraries ();
 sub handle_makefiles_serial ();
 sub handle_man_pages ();
@@ -2277,17 +2278,15 @@ sub handle_source_transform
 }
 
 
-# handle_lib_objects ($XNAME, $VAR)
-# ---------------------------------
+# handle_lib_objects ($VAR)
+# -------------------------
 # Special-case ALLOCA and LIBOBJS substitutions in _LDADD or _LIBADD variables.
-# Also, generate _DEPENDENCIES variable if appropriate.
 # Arguments are:
-#   transformed name of object being built, or empty string if no object
 #   name of _LDADD/_LIBADD-type variable to examine
 # Returns 1 if LIBOBJS seen, 0 otherwise.
 sub handle_lib_objects
 {
-  my ($xname, $varname) = @_;
+  my ($varname) = @_;
 
   my $var = var ($varname);
   prog_error "'$varname' undefined"
@@ -2299,11 +2298,8 @@ sub handle_lib_objects
   my $seen_libobjs = 0;
   my $flagvar = 0;
 
-  transform_variable_recursively
-    ($varname, $xname . '_DEPENDENCIES', 'am__DEPENDENCIES',
-     ! $xname, INTERNAL,
-     # Transformation function, run on each filename.
-     sub {
+  $var->traverse_recursively
+    (sub {
        my ($subvar, $val, $cond, $full_cond) = @_;
 
        if ($val =~ /^-/)
@@ -2329,36 +2325,61 @@ sub handle_lib_objects
 	     }
 	   return ();
 	 }
-       elsif ($val !~ /^\@.*\@$/)
-	 {
-	   # Assume we have a file of some sort, and output it into the
-	   # dependency variable.  Autoconf substitutions are not output;
-	   # rarely is a new dependency substituted into e.g. foo_LDADD
-	   # -- but bad things (e.g. -lX11) are routinely substituted.
-	   # Note that LIBOBJS and ALLOCA are exceptions to this rule,
-	   # and handled specially below.
-	   return $val;
-	 }
        elsif ($val =~ /^\@(LT)?LIBOBJS\@$/)
 	 {
 	   handle_LIBOBJS ($subvar, $cond, $1);
 	   $seen_libobjs = 1;
-	   return $val;
+	   return ();
 	 }
        elsif ($val =~ /^\@(LT)?ALLOCA\@$/)
 	 {
 	   handle_ALLOCA ($subvar, $cond, $1);
-	   return $val;
+	   return ();
 	 }
        else
 	 {
 	   return ();
 	 }
-     });
+     }, undef);
 
   return $seen_libobjs;
 }
 
+# Generate link dependencies after all target _OBJECTS variables have been
+# defined, so references to other targets do not depend on processing order.
+sub handle_link_dependencies ()
+{
+  foreach my $primary (['LIBADD', @liblist, @ltliblist],
+                      ['LDADD', @proglist])
+    {
+      my ($suffix, @targets) = @$primary;
+      foreach my $pair (@targets)
+        {
+          my $xname = canonicalize ($pair->[1]);
+          my $varname = $xname . '_' . $suffix;
+          my $def = rvar ($varname)->def (TRUE);
+          if ($def && $def->owner == VAR_AUTOMAKE)
+            {
+              # Libraries default to empty LIBADD; programs to LDADD.
+              next if $suffix eq 'LIBADD' || ! var ('LDADD');
+              $varname = 'LDADD';
+            }
+          transform_variable_recursively
+            ($varname, $xname . '_DEPENDENCIES',
+             'am__DEPENDENCIES', 0, INTERNAL,
+             sub {
+               my ($subvar, $val) = @_;
+               # Omit linker flags and configure substitutions, except
+               # for the object lists handled by handle_lib_objects.
+               return () if $val =~ /^-/;
+               return () if $val =~ /^\@.*\@$/
+                            && $val !~ /^\@(LT)?(LIBOBJS|ALLOCA)\@$/;
+               return $val;
+             });
+        }
+    }
+}
+
 # handle_LIBOBJS_or_ALLOCA ($VAR, $BASE)
 # --------------------------------------
 # Definitions common to LIBOBJS and ALLOCA.
@@ -2603,7 +2624,7 @@ sub handle_programs ()
   $must_handle_compiled_objects = 1;
 
   my $seen_global_libobjs =
-    var ('LDADD') && handle_lib_objects ('', 'LDADD');
+    var ('LDADD') && handle_lib_objects ('LDADD');
 
   foreach my $pair (@proglist)
     {
@@ -2627,18 +2648,17 @@ sub handle_programs ()
 
       if (var ($xname . "_LDADD"))
 	{
-	  $seen_libobjs = handle_lib_objects ($xname, $xname . '_LDADD');
+	  $seen_libobjs = handle_lib_objects ($xname . '_LDADD');
 	}
       else
 	{
 	  # User didn't define prog_LDADD override.  So do it.
 	  define_variable ($xname . '_LDADD', '$(LDADD)', $where);
 
-	  # This does a bit too much work.  But we need it to
-	  # generate _DEPENDENCIES when appropriate.
+	  # Check the default LDADD for replacement objects.
 	  if (var ('LDADD'))
 	    {
-	      $seen_libobjs = handle_lib_objects ($xname, 'LDADD');
+	      $seen_libobjs = handle_lib_objects ('LDADD');
 	    }
 	}
 
@@ -2743,7 +2763,7 @@ sub handle_libraries ()
       # libraries.
       if (var ($xlib . '_LIBADD'))
 	{
-	  if (handle_lib_objects ($xlib, $xlib . '_LIBADD'))
+	  if (handle_lib_objects ($xlib . '_LIBADD'))
 	    {
 	      $seen_libobjs = 1;
 	    }
@@ -2947,7 +2967,7 @@ sub handle_ltlibraries ()
       # libraries.
       if (var ($xlib . '_LIBADD'))
 	{
-	  if (handle_lib_objects ($xlib, $xlib . '_LIBADD'))
+	  if (handle_lib_objects ($xlib . '_LIBADD'))
 	    {
 	      $seen_libobjs = 1;
 	    }
@@ -8136,6 +8156,7 @@ sub generate_makefile
   handle_libraries;
   handle_ltlibraries;
   handle_programs;
+  handle_link_dependencies;
   handle_scripts;
 
   handle_silent;
diff --git a/t/ar-dependencies.sh b/t/ar-dependencies.sh
new file mode 100644
index 000000000..f57b9bfd3
--- /dev/null
+++ b/t/ar-dependencies.sh
@@ -0,0 +1,73 @@
+#! /bin/sh
+# Copyright (C) 2023-2026 Free Software Foundation, Inc.
+#
+# 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, 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 <https://www.gnu.org/licenses/>.
+
+# Object dependencies must not depend on library ordering (bug#60508).
+
+. test-init.sh
+
+cat >> configure.ac << 'END'
+AC_PROG_CC
+AC_SUBST([OTHER_LIBS])
+AM_PROG_AR
+AC_PROG_RANLIB
+AM_CONDITIONAL([COND], [test x = y])
+END
+
+cat > Makefile.am << 'END'
+noinst_LIBRARIES =
+
+libmMID_a_SOURCES = source.c
+if COND
+libmMID_a_SOURCES += extra.c
+endif
+noinst_LIBRARIES += libmMID.a
+
+libaFIRST_a_SOURCES =
+libaFIRST_a_LIBADD = $(common_objects)
+common_objects = $(libmMID_a_OBJECTS)
+noinst_LIBRARIES += libaFIRST.a
+
+libzLAST_a_SOURCES =
+libzLAST_a_LIBADD = $(libmMID_a_OBJECTS)
+noinst_LIBRARIES += libzLAST.a
+
+noinst_PROGRAMS = aFIRST mMID zLAST
+mMID_SOURCES = main.c
+aFIRST_SOURCES =
+aFIRST_LDADD = $(mMID_OBJECTS) -lm @OTHER_LIBS@
+zLAST_SOURCES =
+zLAST_LDADD = $(mMID_OBJECTS)
+
+noinst_LIBRARIES += liboverride.a
+liboverride_a_SOURCES =
+liboverride_a_LIBADD = $(libmMID_a_OBJECTS)
+liboverride_a_DEPENDENCIES = explicit
+END
+
+: > ar-lib
+
+$ACLOCAL
+$AUTOMAKE
+
+# Make sure DEPENDENCIES is setup correctly.
+grep '_a_DEPENDENCIES =' Makefile.in
+grep '^libzLAST_a_DEPENDENCIES = $(libmMID_a_OBJECTS)' Makefile.in
+grep '^libaFIRST_a_DEPENDENCIES = $(common_objects)$' Makefile.in
+grep '^aFIRST_DEPENDENCIES = $(mMID_OBJECTS)$' Makefile.in
+grep '^zLAST_DEPENDENCIES = $(mMID_OBJECTS)$' Makefile.in
+grep '^liboverride_a_DEPENDENCIES = explicit$' Makefile.in
+
+:
diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk
index ee10b67e5..33edac37d 100644
--- a/t/list-of-tests.mk
+++ b/t/list-of-tests.mk
@@ -152,6 +152,7 @@ t/amopts-location.sh \
 t/amopts-variable-expansion.sh \
 t/amsubst.sh \
 t/ansi2knr-no-more.sh \
+t/ar-dependencies.sh \
 t/ar-lib.sh \
 t/ar-lib2.sh \
 t/ar-lib3.sh \
-- 
2.53.0

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to