Fix PR automake/315:
authorAlexandre Duret-Lutz <adl@gnu.org>
Wed, 24 Apr 2002 07:36:00 +0000 (07:36 +0000)
committerAlexandre Duret-Lutz <adl@gnu.org>
Wed, 24 Apr 2002 07:36:00 +0000 (07:36 +0000)
* automake.in (subobjname): Rewrite to generate variable name
unique for each content.
(%substnums): Remove.
(%subobjvar): New hash.
(initialize_per_input): Clear %subobjvar.
(define_objects_from_sources): Return the name of the variable
defined, in addition to the linker.  Call subobjname only once
the content of the variable to define is known.
(handle_source_transform): Adjust call to define_objects_from_sources.
* tests/specflags8.test: Mention PR 315.
* tests/subobjname.test: New file.
* tests/Makefile.am (XFAIL_TESTS): Remove specflags8.test.
(TESTS): Add subobjname.test.

ChangeLog
THANKS
automake.in
tests/Makefile.am
tests/Makefile.in
tests/specflags8.test
tests/subobjname.test [new file with mode: 0755]

index 2ba160f..a82fe45 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2002-04-24  Alexandre Duret-Lutz  <duret_g@epita.fr>
+
+       Fix PR automake/315:
+       * automake.in (subobjname): Rewrite to generate variable name
+       unique for each content.
+       (%substnums): Remove.
+       (%subobjvar): New hash.
+       (initialize_per_input): Clear %subobjvar.
+       (define_objects_from_sources): Return the name of the variable
+       defined, in addition to the linker.  Call subobjname only once
+       the content of the variable to define is known.
+       (handle_source_transform): Adjust call to define_objects_from_sources.
+       * tests/specflags8.test: Mention PR 315.
+       * tests/subobjname.test: New file.
+       * tests/Makefile.am (XFAIL_TESTS): Remove specflags8.test.
+       (TESTS): Add subobjname.test.
+
 2002-04-23  Alexandre Duret-Lutz  <duret_g@epita.fr>
 
        * m4/depout.m4 (_AM_OUTPUT_DEPENDENCY_COMMANDS): Grep
diff --git a/THANKS b/THANKS
index 49edf61..c5032c7 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -58,6 +58,7 @@ Gord Matzigkeit               gord@gnu.ai.mit.edu
 Gordon Sadler          gbsadler1@lcisp.com
 Greg A. Woods          woods@most.weird.com
 Guido Draheim          guidod@gmx.de
+Gustavo Carneiro       gjc@inescporto.pt
 H.J. Lu                        hjl@lucon.org
 Harlan Stenn           Harlan.Stenn@pfcs.com
 Henrik Frystyk Nielsen frystyk@w3.org
index d8a73e3..930d582 100755 (executable)
@@ -599,16 +599,14 @@ my @substfroms;
 # force.
 my @substtos;
 
-# Associates a variable name, together with a list of substitutions to be
-# performed on it, with a number.  Used to provide unique names for generated
-# variables.
-my %substnums = ();
-
 # If a file name appears as a key in this hash, then it has already
 # been checked for.  This variable is local to the "require file"
 # functions.
 my %require_file_found = ();
 
+# This keeps track of all variables defined by subobjname.
+# The key is the variable _content_, and the value is the variable name.
+my %subobjvar = ();
 
 ## --------------------------------- ##
 ## Forward subroutine declarations.  ##
@@ -746,6 +744,8 @@ sub initialize_per_input ()
     %libtool_clean_directories = ('.' => 1);
 
     %require_file_found = ();
+
+    %subobjvar = ();
 }
 
 
@@ -2135,15 +2135,18 @@ sub handle_single_transform_list ($$$$@)
 #
 # Arguments are:
 #   $VAR is the name of the _SOURCES variable
-#   $OBJVAR is the name of the _OBJECTS
+#   $OBJVAR is the name of the _OBJECTS variable if known (otherwise
+#     it will be generated and returned).
 #   $NODEFINE is a boolean: if true, $OBJVAR will not be defined (but
-#   work done to determine the linker will be).
+#     work done to determine the linker will be).
 #   $ONE_FILE is the canonical (transformed) name of object to build
 #   $OBJ is the object extension (ie either `.o' or `.lo').
 #   $PARENT is the variable in which $VAR is used, or $VAR if not applicable.
 #   $TOPPARENT is the _SOURCES variable being processed.
 #
-# Result is a boolean, true if a linker is needed to deal with the objects.
+# Result is a pair ($LINKER, $OBJVAR):
+#    $LINKER is a boolean, true if a linker is needed to deal with the objects,
+#    $OBJVAR is the name of the variable defined to hold the objects.
 #
 # %linkers_used, %vars_scanned, @substfroms and @substtos should be cleared
 # before use:
@@ -2191,12 +2194,12 @@ sub define_objects_from_sources ($$$$$$$)
                push @substfroms, $from;
                push @substtos, $to;
 
-               my $subobjvar = subobjname ($subvar);
-               push (@result, '$('. $subobjvar . ')');
+               my ($temp, $varname)
+                   = define_objects_from_sources ($subvar, undef,
+                                                  $nodefine, $one_file,
+                                                  $obj, $var, $topparent);
 
-               my $temp = define_objects_from_sources ($subvar, $subobjvar,
-                                                       $nodefine, $one_file,
-                                                       $obj, $var, $topparent);
+               push (@result, '$('. $varname . ')');
                $needlinker ||= $temp;
 
                pop @substfroms;
@@ -2219,53 +2222,62 @@ sub define_objects_from_sources ($$$$$$$)
            }
        }
 
+       # Find an name for the variable, unless imposed.
+        $objvar = subobjname (@result) unless defined $objvar;
        # Define _OBJECTS conditionally.
        define_pretty_variable ($objvar, $cond, (@result))
-               unless $nodefine;
+           unless $nodefine;
     }
 
     delete $vars_scanned{$var};
-    return $needlinker;
+    return ($needlinker, $objvar);
 }
 
 
-# $OBJNAME
-# subobjname ($VARNAME)
+# $VARNAME
+# subobjname (@OBJECTS)
 # ---------------------
-# Return a name for an object variable.
+# Return a name for an object variable that holds @OBJECTS.
 #
-# Arguments are:
-#   $VARNAME is the name of the variable the object variable is being
-#   generated from.
+# If we already have an object variable containing @OBJECTS, reuse it.
+# This way, we avoid combinatorial explosion of the generated
+# variables.  Especially, in a Makefile such as:
 #
-# This function also looks at @substfroms and @substtos to determine any
-# substitutions to be performed on the object variable.
+# | if FOO1
+# | A1=1
+# | endif
+# |
+# | if FOO2
+# | A2=2
+# | endif
+# |
+# | ...
+# |
+# | if FOON
+# | AN=N
+# | endif
+# |
+# | B=$(A1) $(A2) ... $(AN)
+# |
+# | c_SOURCES=$(B)
+# | d_SOURCES=$(B)
 #
-# The name returned is unique for the combination of $varname and
-# substitutions to be performed.
-sub subobjname ($)
+# The generated c_OBJECTS and d_OBJECTS will share the same variable
+# definitions.
+#
+# This setup can be the case of a testsuite containing lots (>100) of
+# small C programs, all testing the same set of source files.
+my $subobjnamenum = 0;
+sub subobjname (@)
 {
-    my ($varname) = @_;
-    my $key = $varname;
-    my $substnum=$#substfroms;
-    while ($substnum >= 0)
-    {
-       if (defined $substfroms[$substnum] &&
-           ($substfroms[$substnum] || $substtos[$substnum]))
-       {
-           $key .= ":" . $substfroms[$substnum] . "=" . $substtos[$substnum];
-       }
-       $substnum -= 1;
-    }
+    my $key = "@_";
 
-    my $num = $substnums{$key};
-    if (! $num)
-    {
-       $num = keys(%substnums) + 1;
-       $substnums{$key} = $num;
-    }
+    return $subobjvar{$key} if exists $subobjvar{$key};
 
-    return "am__objects_$num";
+    ++$subobjnamenum;
+    my $name = "am__objects_${subobjnamenum}";
+    $subobjvar{$key} = $name;
+    return $name;
 }
 
 
@@ -2318,10 +2330,11 @@ sub handle_source_transform
        @substfroms = ();
        @substtos = ();
        %vars_scanned = ();
-       my $temp = define_objects_from_sources ($var,
-                                               $xpfx . $one_file . '_OBJECTS',
-                                               $prefix =~ /EXTRA_/,
-                                               $one_file, $obj, $var, $var);
+       my ($temp, $objvar) =
+           define_objects_from_sources ($var,
+                                        $xpfx . $one_file . '_OBJECTS',
+                                        $prefix =~ /EXTRA_/,
+                                        $one_file, $obj, $var, $var);
        $needlinker ||= $temp;
     }
     if ($needlinker)
index e9a8ba4..4f8c4b8 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 
-XFAIL_TESTS = condd.test subdir5.test auxdir2.test cond17.test specflags8.test
+XFAIL_TESTS = condd.test subdir5.test auxdir2.test cond17.test
 
 TESTS =        \
 acinclude.test \
@@ -320,6 +320,7 @@ subobj6.test \
 subobj7.test \
 subobj8.test \
 subobj9.test \
+subobjname.test \
 subst.test \
 substref.test \
 substtarg.test \
index 280033f..51062fd 100644 (file)
@@ -84,7 +84,7 @@ sharedstatedir = @sharedstatedir@
 sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 
-XFAIL_TESTS = condd.test subdir5.test auxdir2.test cond17.test specflags8.test
+XFAIL_TESTS = condd.test subdir5.test auxdir2.test cond17.test
 
 TESTS = \
 acinclude.test \
@@ -404,6 +404,7 @@ subobj6.test \
 subobj7.test \
 subobj8.test \
 subobj9.test \
+subobjname.test \
 subst.test \
 substref.test \
 substtarg.test \
index e3d2dd9..6401667 100755 (executable)
@@ -2,6 +2,7 @@
 
 # Like the ctags/etags example from the manual,
 # with one extra indirection in the sources.
+# PR 315.
 
 . $srcdir/defs || exit 1
 
diff --git a/tests/subobjname.test b/tests/subobjname.test
new file mode 100755 (executable)
index 0000000..1f94a94
--- /dev/null
@@ -0,0 +1,58 @@
+#! /bin/sh
+
+# Make sure we reuse variables whenever possible, to limit
+# combinational explosion.  (This test is named after the &subobjname
+# sub in Automake).
+
+. $srcdir/defs || exit 1
+
+set -e
+
+cat >> configure.in << 'END'
+AC_PROG_CC
+AM_CONDITIONAL([FOO1], [some test])
+AM_CONDITIONAL([FOO2], [some test])
+AM_CONDITIONAL([FOO3], [some test])
+AC_OUTPUT
+END
+
+cat > Makefile.am << 'END'
+noinst_PROGRAMS = c d
+
+if FOO1
+A1=a1.c
+endif
+
+if FOO2
+A2=a2.c
+endif
+
+if FOO3
+A3=a3.c
+endif
+
+B=$(A1) $(A2) $(A3)
+
+c_SOURCES=$(B)
+d_SOURCES=$(B)
+END
+
+$ACLOCAL
+$AUTOMAKE -a
+
+# Sanity check: make sure am_c_OBJECTS and am_d_OBJECTS are used
+# in the Makefile.  (This is an internal detail, so better make
+# sure we update this test if the naming changes in the future.)
+grep '^am_c_OBJECTS = ' Makefile.in
+grep '^am_d_OBJECTS = ' Makefile.in
+
+# Now the actual test.  Are both values equal?
+cobj=`sed -n '/^am_c_OBJECTS = / {
+               s/.* = \(.*\)$/\1/
+               p
+              }' Makefile.in`
+dobj=`sed -n '/^am_d_OBJECTS = / {
+               s/^.* = \(.*\)$/\1/
+               p
+              }' Makefile.in`
+test "$cobj" = "$dobj"