bug-autoconf
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: divert()/m4_divert() broken in autoconf-2.64+


From: Eric Blake
Subject: Re: divert()/m4_divert() broken in autoconf-2.64+
Date: Tue, 24 Nov 2009 21:46:19 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Mike Frysinger <vapier <at> gentoo.org> writes:

> ok, let's try this example then.  same as before ... things break starting 
> with autoconf-2.64.

As they should.  Don't play with fire without taking precautions against burns.

> 
> $ cat configure.in
> AC_INIT
> AC_PROG_CC

Outputs prelimiary text in BODY (aka 1000).

> m4_divert(600)

Changes to 600.

> AC_CHECK_FUNC(socket)

Includes AC_REQUIRE([AC_PROG_CC]), and AC_REQUIRE plays with diversions under 
the hood.  To avoid outputting the text for AC_PROG_CC twice, autoconf 
recognizes that AC_PROG_CC was already expanded, so it does not output a cc 
check in 600.  The end result?  The socket check in 600 has no chance of 
succeeding because it occurs in the script prior to the cc checkin in 1000:

600
check for socket
1000
check for cc

About the only case where m4_divert is useful is if you:
a) maintain a stack of current diversions (for this task, 
m4_divert_push/m4_divert_pop is much friendlier than raw m4_divert; and 
m4_divert_text is friendlier still)
b) don't call any autoconf macros while you are in your special diversion (in 
other words, operate under the assumption that an arbitrary autoconf macro may 
require a particular current diversion and/or use m4_divert under the hood, so 
until you return the diversion stack to its original state, those autoconf 
macros will misbehave).  The assumption that an autoconf macro may play with 
diversions under the hood is surprisingly reliable, because anything that uses 
AC_REQUIRE falls into that category.

Yes, it might be possible to rewrite the AC_REQUIRE mechanism from scratch to 
track not only whether a macro was expanded, but also into which diversion.  If 
I were to attempt that, then I could turn this toy example into another 
manifestation of the expanded-before-required warning, where the resulting 
script looks like:

600
check for cc
check for socket
1000
check for cc

along with a warning that check for cc was expanded before it was required.  
But why go to that effort, especially given how many _years_ the AC_REQUIRE 
mechanism silently allowed the expand-before-require bug that was finally 
diagnosed by my rewrite of AC_REQUIRE for autoconf 2.64?  You are using 
m4_divert to an unnamed diversion, so you are violating the constraints 
recommended by the manual.  Until someone can show me a real configure.ac that 
NEEDS to use m4_divert, with no other way of using documented autoconf 
paradigms to acheive its goal, then I don't see the need to make this toy 
example work at the expense of bloating autoconf for normal users.

> inserting a m4_divert() before the AC_INIT (and with different relative 
> numbers) doesnt seem to make a difference

That's because AC_INIT sets its own diversion number anyway, overriding your 
attempts at changing the diversion before starting autoconf's processing.  
Again, proof that you should assume that an arbitrary autoconf macro is likely 
to play with diversions under the hood, so you must restore diversions back to 
a consistent state before using an autoconf macro.

There are very few reasons to use m4_divert and friends outside of autoconf; 
and in general, when someone has pointed out such a reason, I've been 
questioning whether it really implies that we would be better off exposing a 
public autoconf API that hides the diversion magic under the hood to achieve 
the same use case with less user confusion.

But for the record, here's a GOOD example of how a user can apply m4_divert 
(and why I still feel okay about documenting m4_divert and friends in the first 
place, even if they are tricky to use):

http://git.savannah.gnu.org/cgit/gnulib.git/tree/m4/getopt.m4

Track how the gl_getopt_required variable is used.  If the user calls 
gl_FUNC_GETOPT_POSIX, then it is assigned the value POSIX in diversion DEFAULTS 
(10 - okay, so it goofed in that DEFAULTS is not a documented diversion name).  
It does so using m4_divert_text rather than raw m4_divert, and uses a name 
rather than a number.  If the user calls gl_FUNC_GETOPT_GNU, then it is 
assigned the value GNU in diversion INIT_PREPARE (300 - again an undocumented 
diversion name).  Then both macros proceed to (eventually) require the 
expansion of gl_GETOPT_CHECK_HEADERS in diversion BODY (1000).  That macro can 
then depend on the current definition of $gl_getopt_required - it is guaranteed 
to be either GNU or POSIX based on the earlier diversions.  If you only called 
one of the two interfaces, then the definition is obvious.  But if you called 
both macros, _in either order_, then gl_getopt_required will be GNU (that is, 
requesting the GNU interface has precedence over the POSIX interface, since the 
gnu extensions to getopt are indeed a superset of posix, but the configure 
writer no longer has to double check whether they called macros in the correct 
order).  And since neither use of m4_divert_text calls any autoconf macro, but 
only outputs shell code that is syntactically valid, then autoconf macros don't 
get confused by the temporary diversion changes.

Maybe I should document the diversion names of DEFAULTS and INIT_PREPARE; I'm a 
bit undecided on that one.  But I don't want to document the values associated 
with named diversions, so that we are free to change the underlying value at a 
later date (maybe INIT_PREPARE will move to 350 if we add a new named diversion 
that needs to be at 300); as long as you go through named interfaces rather 
than raw numbers, then we can make such changes under the hood without breaking 
compatibility with your configure.ac.

-- 
Eric Blake







reply via email to

[Prev in Thread] Current Thread [Next in Thread]