Subject: bug#27781: LIBOBJS should depend on LIBOBJDIR

From: Michael Haubenwallner <[email-masked]>
Date: Thu, 24 Aug 2017 16:23:00 +0200

On 08/24/2017 11:35 AM, Mathieu Lirzin wrote:
> Nick Bowler <[email-masked]> writes:
>> On 8/23/17, Mathieu Lirzin <[email-masked]> wrote:
>>> Michael Haubenwallner <[email-masked]> writes:
>>>> Another thought about the final "$(LIBOBJS): .../.dirstamp" Makefile
>>>> line: If I remember correctly, there have been (non-GNU) make
>>>> implementations thatchoke on this rule when LIBOBJS is an empty
>>>> variable: Am I wrong here, or is GNU make required anyway these days?
>>>
>>> GNU make is not required for current Automake version.  I didn't find
>>> any reference of this issue with empty variable target in Autoconf
>>> "Portable Make programming" section [1] but if it is actually the case
>>> then it would be nice to find a solution for that.
>>
>> POSIX requires that target rules specify at least one target.  At least
>> dmake will fail to parse the makefile if it contains an target rule with
>> no targets:
>>
>>   % cat >Makefile <<'EOF'
>> FOO =
>> dummy: ;
>> $(FOO): ;
>> EOF
>>   % dmake
>>   dmake:  Makefile:  line 3:  Error: -- Missing targets or attributes in rule
>>
>> If the target list is a macro which can reasonably be empty then one
>> solution is to add a bogus target name that won't be used anywhere
>> else, along the lines of:
>>
>>   gobbledegook $(FOO): ;
> 
> Instead of this dummy target, I would rather prefer adding the dirstamp
> dependency for each explicit object file separately.  this should be computed
> from the '%libsources' variable.  However after a quick look in the code, it
> seems that this variable is not properly populated by the
> 'scan_autoconf_traces' subroutine.  It only contains the files that are
> explicitely defined by scanning the AC_LIBSOURCE macro and not by AC_LIBOBJ or
> AC_LIBSOURCES in 'configure.ac'.
> 
> Michael: Are you interested in looking into this?
> 

Here's an attempt to use the explicit AC_LIBSOURCE values to depend on the
LIBOBJDIR dirstamp. IMHO, tracing AC_LIBOBJ would not provide additional
information over AC_LIBSOURCE, as AC_LIBOBJ by itself uses AC_LIBSOURCE.

But then there is _AC_LIBOBJS_NORMALIZE, adding $U to {,LT}LIBOBJS values
(seems referring to "Automake's ANSI2KNR"): What is this about?

/haubi/
>From 4465bb9e31c12a8f59c199c61aaef17966e1ffc4 Mon Sep 17 00:00:00 2001
From: Michael Haubenwallner <[email-masked]>
Date: Wed, 16 Aug 2017 18:16:12 +0200
Subject: [PATCH] automake: Depend on LIBOBJDIR for LIBOBJS.

This change fixes automake bug#27781.

* bin/automake.in: Add Makefile dependency on LIBOBJDIR/dirstamp for
each LIBOBJS/ALLOCA source file found.
---
 bin/automake.in | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/bin/automake.in b/bin/automake.in
index 9c4cb86..66619d2 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -2129,13 +2129,14 @@ sub handle_lib_objects
   return $seen_libobjs;
 }
 
-# handle_LIBOBJS_or_ALLOCA ($VAR)
-# -------------------------------
+# handle_LIBOBJS_or_ALLOCA ($VAR, $BASE)
+# --------------------------------------
 # Definitions common to LIBOBJS and ALLOCA.
 # VAR should be one of LIBOBJS, LTLIBOBJS, ALLOCA, or LTALLOCA.
+# BASE should be one base file name from AC_LIBSOURCE, or alloca.
 sub handle_LIBOBJS_or_ALLOCA
 {
-  my ($var) = @_;
+  my ($var, $base) = @_;
   my $dir = '';
 
   # If LIBOBJS files must be built in another directory we have
@@ -2153,10 +2154,13 @@ sub handle_LIBOBJS_or_ALLOCA
       $dir = backname ($relative_dir) . "/$dir"
         if $relative_dir ne '.';
       define_variable ('LIBOBJDIR', "$dir", INTERNAL);
-      $clean_files{"\$($var)"} = MOSTLY_CLEAN;
-      # If LTLIBOBJS is used, we must also clear LIBOBJS (which might
-      # be created by libtool as a side-effect of creating LTLIBOBJS).
-      $clean_files{"\$($var)"} = MOSTLY_CLEAN if $var =~ s/^LT//;
+      if ($dir && !defined $clean_files{"$dir$base.\$(OBJEXT)"}) {
+	my $dirstamp = require_build_directory ($dir);
+	$output_rules .= "$dir$base.\$(OBJEXT): $dirstamp\n";
+	$output_rules .= "$dir$base.lo: $dirstamp\n" if $var =~ /^LT/;
+      }
+      $clean_files{"$dir$base.\$(OBJEXT)"} = MOSTLY_CLEAN;
+      $clean_files{"$dir$base.lo"} = MOSTLY_CLEAN if $var =~ /^LT/;
     }
 
   return $dir;
@@ -2171,14 +2175,14 @@ sub handle_LIBOBJS
   $var->requires_variables ("\@${lt}LIBOBJS\@ used", $lt . 'LIBOBJS')
     if ! keys %libsources;
 
-  my $dir = handle_LIBOBJS_or_ALLOCA "${lt}LIBOBJS";
-
   foreach my $iter (keys %libsources)
     {
-      if ($iter =~ /\.[cly]$/)
+      my $dir = '';
+      if ($iter =~ /^(.*)(\.[cly])$/)
 	{
-	  saw_extension ($&);
+	  saw_extension ($2);
 	  saw_extension ('.c');
+	  $dir = handle_LIBOBJS_or_ALLOCA ("${lt}LIBOBJS", $1);
 	}
 
       if ($iter =~ /\.h$/)
@@ -2206,7 +2210,7 @@ sub handle_ALLOCA
   my ($var, $cond, $lt) = @_;
   my $myobjext = $lt ? 'lo' : 'o';
   $lt ||= '';
-  my $dir = handle_LIBOBJS_or_ALLOCA "${lt}ALLOCA";
+  my $dir = handle_LIBOBJS_or_ALLOCA ("${lt}ALLOCA", "alloca");
 
   $dir eq '' and $dir = './';
   $var->requires_variables ("\@${lt}ALLOCA\@ used", $lt . 'ALLOCA');
-- 
2.10.2