Subject: Re: bug#8718: error when using nested conditionals

From: Bruno Haible <[email-masked]>
Date: Fri, 17 Jun 2011 12:21:38 +0200

Ralf Wildenhues wrote:
> Please note that this does have a small change in semantics, namely if
> there is code using AM_COND_IF

Thanks for the heads-up; I'll change the code to handle that as well.

> > There's no point in being _that_ safe that you check unused expressions
> > for validity. C compilers don't do it either: When I compile a C program
> >   #if 0
> >   #if syntax error ((((,$$?!
> >   #endif
> >   #endif
> > the second line yields no error and no warning, because the condition in
> > that line is ignored.
> 
> But that's not the same thing.  AM_CONDITIONAL sets variables
> <COND>_TRUE and <COND>_FALSE to either empty or '#', and at least one of
> them will always be nonempty.  If you skip this initialization code, the
> Makefile *will* be wrong.

No, the generated Makefile will be right because all uses of
<COND>_TRUE and <COND>_FALSE will be inside Makefile comments, where the
comment marker "#" comes out of the expansion of the outer conditional.

> You may just have been lucky to not notice 
> that because gnulib uses few negated conditionals
>   if !FOO
>   ...
>   endif
> 
> or
>   if FOO
>   ...
>   else !FOO
>   ...
>   endif

I don't see a problem with negation. Here's a test case:

================================ configure.ac ================================
AC_INIT([dummy], [0])
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_PROG_RANLIB
if test 4 = 5; then
  use_foo=true
  AM_CONDITIONAL([USE_VARIANT_A], [false])
else
  use_foo=false
  AM_CONDITIONAL([USE_VARIANT_B], [false])
fi
AM_CONDITIONAL([USE_FOO], [$use_foo])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
================================ Makefile.am =================================
if USE_FOO
if USE_VARIANT_A
all : test1.o
endif
endif

if USE_FOO
if !USE_VARIANT_A
all : test2.o
endif
endif

if !USE_FOO
if USE_VARIANT_B
all : test3.o
endif
endif

if !USE_FOO
if !USE_VARIANT_B
all : test4.o
endif
endif
==============================================================================

Then the generated Makefile.in contains these lines:

  @USE_FOO_TRUE@@USE_VARIANT_A_TRUE@all : test1.o

  @USE_FOO_TRUE@@USE_VARIANT_A_FALSE@all : test2.o

  @USE_FOO_FALSE@@USE_VARIANT_B_TRUE@all : test3.o

  @USE_FOO_FALSE@@USE_VARIANT_B_FALSE@all : test4.o

This means:
  - If USE_FOO evaluates to false, all uses of @USE_VARIANT_A_TRUE@
    and @USE_VARIANT_A_FALSE@ are preceded by @USE_FOO_TRUE@ which is
    replaced by "#". Thus their values don't matter.
  - Similarly, if USE_FOO evaluates to true, all uses of @USE_VARIANT_B_TRUE@
    and @USE_VARIANT_B_FALSE@ are preceded by @USE_FOO_FALSE@ which is
    replaced by "#". Thus their values don't matter.

And the generated Makefile has:

  #all : test1.o

  #all : test2.o

  #all : test3.o

  all : test4.o

Which is working perfectly fine. And even if it were

  #@USE_VARIANT_A_TRUE@all : test1.o

  #@USE_VARIANT_A_FALSE@all : test2.o

  #all : test3.o

  all : test4.o

it would be working fine.

So, there is no problem with the generated Makefiles if the checks would
be weakened check only the definedness of conditionals that are actually
used in the Makefiles.

> the safety net around them definitely is not too strict.

I disagree. It is too strict without necessity.

Bruno
-- 
In memoriam The victims of the East German uprising <http://en.wikipedia.org/wiki/Uprising_of_1953_in_East_Germany>