This is the mail archive of the
automake-prs@sources.redhat.com
mailing list for the automake project.
Re: automake/326: Bug with conditionally defined variables used in_SOURCES
- From: Alexandre Duret-Lutz <duret_g at lrde dot epita dot fr>
- To: tromey at redhat dot com
- Cc: automake-prs at sources dot redhat dot com,
- Date: 31 May 2002 14:11:01 -0000
- Subject: Re: automake/326: Bug with conditionally defined variables used in_SOURCES
- Reply-to: Alexandre Duret-Lutz <duret_g at lrde dot epita dot fr>
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