This is the mail archive of the automake-prs@sources.redhat.com mailing list for the automake project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: automake/326: Bug with conditionally defined variables used in_SOURCES


The following reply was made to PR automake/326; it has been noted by GNATS.

From: Alexandre Duret-Lutz <duret_g@lrde.epita.fr>
To: richard@tartarus.org
Cc: automake-gnats@sources.redhat.com
Subject: Re: automake/326: Bug with conditionally defined variables used in
 _SOURCES
Date: Fri, 31 May 2002 16:02:59 +0200

 >>> "richard" == richard  <richard@tartarus.org> writes:
 
  richard> bin_PROGRAMS = targ
  richard> if ONE
  richard> SONE = one.c
  richard> endif
 
  richard> if TWO
  richard> STWO = 
  richard> else
  richard> STWO = two.c
  richard> endif
 
  richard> if THREE
  richard> STHREE = 
  richard> else
  richard> STHREE = three.c
  richard> endif
 
  richard> targ_SOURCES = $(SONE) $(STWO) $(STHREE)
 
 I think there is twos bug here.  
 
 1. &define_objects_from_sources reuse objects variables
    between conditions.  E.g. Automake generates $(am__object_2) for STWO
    in the TWO_TRUE condition, and it reuses this same variable
    name for STWO in the TWO_FALSE condition.  (This isn't as
    harmless as it seems, see below.)
 
 2. the recent change to select objects variable based on their
    content only is condition insensitive.  This means that
    since am__object_2 was defined as empty (no objects for STWO
    in condition TWO_TRUE), it will be reused for STHREE in condition
    THREE_TRUE.
 
 The conjunction of 1. and 2. means that am__objects_2 is latter
 reused for STHREE in condition THREE_FALSE.
 
 Actually, fixing 2. is enough to fix the above test case.  It's
 also easy: just use the curent condition to generate the key in
 &subobjvar.  Then a different object variable ($am__objects_3)
 will be generated for STHREE in condition THREE_TRUE (because
 even if it's empty like $am__objects_2, it's not defined in the
 same condition), and will be reused for STHREE in THREE_FALSE,
 yielding the output you expected:
 
 @ONE_TRUE@am__objects_1 = one.$(OBJEXT)
 @TWO_TRUE@am__objects_2 =
 @TWO_FALSE@am__objects_2 = two.$(OBJEXT)
 @THREE_TRUE@am__objects_3 =
 @THREE_FALSE@am__objects_3 = three.$(OBJEXT)
 
 However, if you augment this test case with:
 
 if THREE
   STHREE2 = 
 else
   STHREE2 = three2.c
 endif
 
 Then `am__objects_3' will be reused for STHREE2 in THREE_TRUE,
 and as a consequence of 1., it will be used in THREE_FALSE to,
 yielding:
 
 @THREE_TRUE@am__objects_3 =
 @THREE_FALSE@am__objects_3 = three2.$(OBJEXT)
 
 and these definition will override the one output for STHREE.
 
 
 Changing &subobjname another time, so that it generate object
 variable names unique for each source variable (STHREE or
 STHREE2) in not enough.  It would work with all the examples
 presented so far, but not with something like this:
 
 bin_PROGRAMS = a b
 if THREE
   STHREE = 
 else
   STHREE = three.c
 endif
 a_SOURCES = $(STHREE)
 b_SOURCES = $(STHREE)
 b_CFLAGS = -fmumble
 
 
 So what I suggest is to generate different object variable names
 for each conditions:
 
 @ONE_TRUE@am__objects_1 = one.$(OBJEXT)
 @TWO_TRUE@am__objects_2 =
 @TWO_FALSE@am__objects_3 = two.$(OBJEXT)
 @THREE_TRUE@am__objects_4 =
 @THREE_FALSE@am__objects_5 = three.$(OBJEXT)
 @THREE_TRUE@am__objects_4 =
 @THREE_FALSE@am__objects_6 = three2.$(OBJEXT)
 
 It sounds a little akward.  What do you think?
 
 
 PS: This is for CVS HEAD (on branch-1-6 replace $FGREP with fgrep).
 
 2002-05-31  Alexandre Duret-Lutz  <duret_g@epita.fr>
 
 	Fix for PR/326:
 	* automake.in (define_objects_from_sources): Define a different
 	variable for each condition.  Return the list of variables defined.
 	(subobjname): Take a $cond argument and use it in the key.
 	* tests/cond22.test: New file.
 	* tests/Makefile.am (TESTS): New file.
 	Reported by Richard Boulton.
 
 Index: automake.in
 ===================================================================
 RCS file: /cvs/automake/automake/automake.in,v
 retrieving revision 1.1299
 diff -u -r1.1299 automake.in
 --- automake.in	20 May 2002 20:42:01 -0000	1.1299
 +++ automake.in	31 May 2002 14:01:13 -0000
 @@ -604,8 +604,10 @@
  # 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.
 +# This keeps track of all variables defined by subobjname.  Each key
 +# has the form `COND: CONTENT' where CONTENT is the variable content
 +# and COND is the condition of definition.  The value associated to
 +# the key is the variable name.
  my %subobjvar = ();
  
  # This hash records helper variables used to implement '+=' in conditionals.
 @@ -2134,7 +2136,7 @@
      return @result;
  }
  
 -# $BOOL
 +# ($LINKER, @OBJVARS)
  # define_objects_from_sources ($VAR, $OBJVAR, $NODEFINE, $ONE_FILE,
  #                              $OBJ, $PARENT, $TOPPARENT)
  # ---------------------------------------------------------------------
 @@ -2153,7 +2155,8 @@
  #
  # 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.
 +#    @OBJVARS lists the variables that hold the objects for $VAR, all
 +#      conditions combined.
  #
  # %linkers_used, %vars_scanned, @substfroms and @substtos should be cleared
  # before use:
 @@ -2174,6 +2177,7 @@
      $vars_scanned{$var} = 1;
  
      my $needlinker = "";
 +    my @objvars = ();
      foreach my $cond (variable_conditions ($var))
      {
  	my @result;
 @@ -2201,12 +2205,12 @@
  		push @substfroms, $from;
  		push @substtos, $to;
  
 -		my ($temp, $varname)
 +		my ($temp, @varnames)
  		    = define_objects_from_sources ($subvar, undef,
  						   $nodefine, $one_file,
  						   $obj, $var, $topparent);
  
 -		push (@result, '$('. $varname . ')');
 +		push (@result, map { "\$($_)" } @varnames);
  		$needlinker ||= $temp;
  
  		pop @substfroms;
 @@ -2230,21 +2234,25 @@
  	}
  
  	# Find an name for the variable, unless imposed.
 -        $objvar = subobjname (@result) unless defined $objvar;
 +	my $cond_objvar =
 +	    defined $objvar ? $objvar : subobjname ($cond, @result);
  	# Define _OBJECTS conditionally.
 -	define_pretty_variable ($objvar, $cond, (@result))
 -	    unless $nodefine;
 +	unless ($nodefine)
 +	{
 +	    define_pretty_variable ($cond_objvar, $cond, @result);
 +	    push @objvars, $cond_objvar;
 +	}
      }
  
      delete $vars_scanned{$var};
 -    return ($needlinker, $objvar);
 +    return ($needlinker, @objvars);
  }
  
  
  # $VARNAME
 -# subobjname (@OBJECTS)
 -# ---------------------
 -# Return a name for an object variable that holds @OBJECTS.
 +# subobjname ($COND, @OBJECTS)
 +# ----------------------------
 +# Return a name for an object variable that holds @OBJECTS for condition $COND.
  #
  # If we already have an object variable containing @OBJECTS, reuse it.
  # This way, we avoid combinatorial explosion of the generated
 @@ -2274,9 +2282,13 @@
  #
  # This setup can be the case of a testsuite containing lots (>100) of
  # small C programs, all testing the same set of source files.
 -sub subobjname (@)
 +#
 +# In addition to being unique to each content, the variable name must
 +# also be unique for condition $COND.
 +sub subobjname ($@)
  {
 -    my $key = "@_";
 +    my $key = shift;
 +    $key .= ": @_";
  
      return $subobjvar{$key} if exists $subobjvar{$key};
  
 Index: tests/Makefile.am
 ===================================================================
 RCS file: /cvs/automake/automake/tests/Makefile.am,v
 retrieving revision 1.400
 diff -u -r1.400 Makefile.am
 --- tests/Makefile.am	24 May 2002 10:36:18 -0000	1.400
 +++ tests/Makefile.am	31 May 2002 14:01:13 -0000
 @@ -83,6 +83,7 @@
  cond19.test \
  cond20.test \
  cond21.test \
 +cond22.test \
  condd.test \
  condincl.test \
  condincl2.test \
 Index: tests/cond22.test
 ===================================================================
 RCS file: tests/cond22.test
 diff -N tests/cond22.test
 --- /dev/null	1 Jan 1970 00:00:00 -0000
 +++ tests/cond22.test	31 May 2002 14:01:13 -0000
 @@ -0,0 +1,55 @@
 +#! /bin/sh
 +
 +# Regression test for bug when sources listed in conditional.
 +# Report from Richard Boulton.  PR/326.
 +
 +. $srcdir/defs || exit 1
 +
 +set -e
 +
 +cat >> configure.in << 'END'
 +AC_PROG_CC
 +AM_CONDITIONAL(ONE, true)
 +AM_CONDITIONAL(TWO, false)
 +AM_CONDITIONAL(THREE, false)
 +AC_OUTPUT
 +END
 +
 +cat > Makefile.am << 'END'
 +bin_PROGRAMS = targ
 +
 +if ONE
 +SONE = one.c
 +endif
 +
 +if TWO
 +STWO =
 +else
 +STWO = two.c
 +endif
 +
 +if THREE
 +STHREE =
 +else
 +STHREE = three.c
 +endif
 +
 +if THREE
 +STHREE2 =
 +else
 +STHREE2 = three2.c
 +endif
 +
 +targ_SOURCES = $(SONE) $(STWO) $(STHREE) $(STHREE2)
 +
 +echo:
 +	echo BEG: $(targ_OBJECTS) :END;
 +END
 +
 +$ACLOCAL
 +$AUTOCONF
 +$AUTOMAKE
 +./configure
 +OBJEXT=oo $MAKE -e echo > output
 +cat output
 +$FGREP 'BEG: one.oo two.oo three.oo three2.oo :END' output
 
 -- 
 Alexandre Duret-Lutz
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]