]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
Improve AC_REQUIRE documentation.
authorEric Blake <ebb9@byu.net>
Sat, 17 Jan 2009 16:36:02 +0000 (09:36 -0700)
committerEric Blake <ebb9@byu.net>
Mon, 19 Jan 2009 14:09:57 +0000 (07:09 -0700)
* doc/autoconf.texi (Macro Definitions) <AC_DEFUN>: Add @defmac,
and mention interaction with AC_REQUIRE.
(Prerequisite Macros) <AC_REQUIRE>: Give more detail on user
ordering constraint bug, and how to fix it.
* tests/m4sugar.at (m4@&t@_require: nested): New test.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
doc/autoconf.texi
tests/m4sugar.at

index 120a70ca853c18c5126dedb6c7db5ec2025b3d84..7029b84c538982b4ed2286fe2ac6e3cafeb920be 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-01-19  Eric Blake  <ebb9@byu.net>
 
+       Improve AC_REQUIRE documentation.
+       * doc/autoconf.texi (Macro Definitions) <AC_DEFUN>: Add @defmac,
+       and mention interaction with AC_REQUIRE.
+       (Prerequisite Macros) <AC_REQUIRE>: Give more detail on user
+       ordering constraint bug, and how to fix it.
+       * tests/m4sugar.at (m4@&t@_require: nested): New test.
+
        Speed up m4_require.
        * lib/m4sugar/m4sugar.m4 (_m4_divert_dump): Change semantics to
        always be defined, as either empty or a number.
index 9a17308b13540e396662eecf2e3629d15283f528..69d5085dff0c40fa3f33845a7cb28d6a759e4919 100644 (file)
@@ -183,7 +183,8 @@ a package for creating scripts to configure source code packages using
 templates and an M4 macro package.
 
 Copyright @copyright{} 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
+Foundation, Inc.
 
 @quotation
 Permission is granted to copy, distribute and/or modify this document
@@ -12800,12 +12801,15 @@ Here are some instructions and guidelines for writing Autoconf macros.
 @node Macro Definitions
 @section Macro Definitions
 
+@defmac AC_DEFUN (@var{name}, @ovar{body})
 @acindex{DEFUN}
 Autoconf macros are defined using the @code{AC_DEFUN} macro, which is
-similar to the M4 builtin @code{m4_define} macro.  In addition to
+similar to the M4 builtin @code{m4_define} macro; this creates a macro
+named @var{name} and with @var{body} as its expansion.  In addition to
 defining a macro, @code{AC_DEFUN} adds to it some code that is used to
-constrain the order in which macros are called (@pxref{Prerequisite
-Macros}).
+constrain the order in which macros are called, while avoiding redundant
+output (@pxref{Prerequisite Macros}).
+@end defmac
 
 An Autoconf macro definition looks like this:
 
@@ -12817,6 +12821,16 @@ You can refer to any arguments passed to the macro as @samp{$1},
 @samp{$2}, etc.  @xref{Definitions, , How to define new macros, m4.info,
 @acronym{GNU} M4}, for more complete information on writing M4 macros.
 
+Most macros fall in one of two general categories.  The first category
+includes macros which take arguments, in order to generate output
+parameterized by those arguments.  Macros in this category are designed
+to be directly expanded, often multiple times, and should not be used as
+the argument to @code{AC_REQUIRE}.  The other category includes macros
+which are shorthand for a fixed block of text, and therefore do not take
+arguments.  For this category of macros, directly expanding the macro
+multiple times results in redundant output, so it is more common to use
+the macro as the argument to @code{AC_REQUIRE}.
+
 Be sure to properly quote both the @var{macro-body} @emph{and} the
 @var{macro-name} to avoid any problems if the macro happens to have
 been previously defined.
@@ -13030,7 +13044,8 @@ square brackets.  @var{macro-name} must have been defined using
 that it has been called.
 
 @code{AC_REQUIRE} must be used inside a macro defined by @code{AC_DEFUN}; it
-must not be called from the top level.
+must not be called from the top level.  Also, it does not make sense to
+require a macro that takes parameters.
 @end defmac
 
 @code{AC_REQUIRE} is often misunderstood.  It really implements
@@ -13103,9 +13118,75 @@ SOME_CHECK
 @end group
 @end example
 
+However, this implementation can lead to another class of problems.
+Since dependencies are hoisted prior to the outermost @code{AC_DEFUN}
+body, but only if they have not been previously seen, it is still
+possible to encounter out-of-order expansion.  Given this example:
+
+@example
+AC_DEFUN([A], [[in A]])
+AC_DEFUN([B], [AC_REQUIRE([A])[in B]])
+AC_DEFUN([C], [AC_REQUIRE([B])[in C]])
+AC_DEFUN([OUTER], [[in OUTER]
+A
+C])
+OUTER
+@end example
+
+@noindent
+observe that the expansion of @code{B} occurred prior to the expansion
+of @code{OUTER}, but because the requirement for @code{B} was not
+encountered until after @code{A} had already been directly expanded,
+there was no reason to hoist @code{A}.  Or, put another way, the fact
+that @code{B} was hoisted but not @code{A} means that @code{B} occurs
+before its prerequisite:
+
+@example
+in B
+in OUTER
+in A
+in C
+@end example
+
+The bug is not in Autoconf, but in the macro definitions.  If you ever
+pass a particular macro name to @code{AC_REQUIRE}, then you are implying
+that the macro only needs to be expanded once.  But to enforce this, all
+uses of that macro should be through @code{AC_REQUIRE}; directly
+expanding the macro defeats the point of using @code{AC_REQUIRE} to
+eliminate redundant expansion.  In the example, this rule of thumb was
+violated because @code{B} requires @code{A} while @code{OUTER} directly
+expands it.  One way of fixing the bug is to factor @code{A} into two
+macros, the portion designed for direct and repeated use (here, named
+@code{A}), and the portion designed for one-shot output and used only
+inside @code{AC_REQUIRE} (here, named @code{A_PREREQ}).  Then, by fixing
+all clients to use the correct macro according to their needs:
+
+@example
+AC_DEFUN([A], [AC_REQUIRE([A_PREREQ])[in A]])
+AC_DEFUN([A_PREREQ], [[in A_PREREQ]])
+AC_DEFUN([B], [AC_REQUIRE([A_PREREQ])[in B]])
+AC_DEFUN([C], [AC_REQUIRE([B])[in C]])
+AC_DEFUN([OUTER], [[in OUTER]
+A
+C])
+OUTER
+@end example
+
+@noindent
+the resulting output will then obey all dependency rules:
+
+@example
+in A_PREREQ
+in B
+in OUTER
+in A
+in C
+@end example
+
 The helper macros @code{AS_IF} and @code{AS_CASE} may be used to
 enforce expansion of required macros outside of shell conditional
-constructs.  You are furthermore encouraged to put all @code{AC_REQUIRE} calls
+constructs.  You are furthermore encouraged, although not required, to
+put all @code{AC_REQUIRE} calls
 at the beginning of a macro.  You can use @code{dnl} to avoid the empty
 lines they leave.
 
index 0d90ca2b5f494f04f4f9b385d327e2882a4b78e3..e822ffb53a7a64216e78b7e445af6d797b1369e2 100644 (file)
@@ -2,8 +2,8 @@
 
 AT_BANNER([M4sugar.])
 
-# Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007, 2008 Free Software
-# Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009 Free
+# Software Foundation, Inc.
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -379,6 +379,7 @@ AT_CLEANUP
 ## --------------------------- ##
 
 AT_SETUP([m4@&t@_require: error message])
+AT_KEYWORDS([m4@&t@_require])
 
 AT_DATA_M4SUGAR([script.4s],
 [[m4_defun([foo], [FOO])
@@ -398,6 +399,7 @@ AT_CLEANUP
 ## ----------------------------------- ##
 
 AT_SETUP([m4@&t@_require: circular dependencies])
+AT_KEYWORDS([m4@&t@_require])
 
 AT_DATA_M4SUGAR([script.4s],
 [[m4_defun([foo], [m4_require([bar])])
@@ -427,6 +429,7 @@ AT_CLEANUP
 ## ---------------------- ##
 
 AT_SETUP([m4@&t@_require: one-shot initialization])
+AT_KEYWORDS([m4@&t@_require])
 AT_KEYWORDS([m4@&t@_defun_init m4@&t@_copy])
 
 AT_CHECK_M4SUGAR_TEXT([[
@@ -455,6 +458,107 @@ hello, again
 AT_CLEANUP
 
 
+## -------------------- ##
+## m4_require: nested.  ##
+## -------------------- ##
+
+AT_SETUP([m4@&t@_require: nested])
+AT_KEYWORDS([m4@&t@_require m4@&t@_defun])
+
+dnl From the m4sugar.m4 discourse: Require chains, top level
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_defun([a], [[a]])dnl aka TEST2a
+m4_defun([b], [[b]m4_require([a])])dnl aka TEST3
+m4_defun([c], [[c]m4_require([b])])dnl aka TEST2b
+m4_defun([d], [[d]m4_require([a])m4_require([c])])dnl aka TEST1
+pre
+d
+d
+post
+]],
+[[pre
+a
+b
+c
+d
+d
+post
+]])
+
+dnl From the m4sugar.m4 discourse: Require chains, nested
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_defun([a], [[a]])dnl aka TEST2a
+m4_defun([b], [[b]m4_require([a])])dnl aka TEST3
+m4_defun([c], [[c]m4_require([b])])dnl aka TEST2b
+m4_defun([d], [[d]m4_require([a])m4_require([c])])dnl aka TEST1
+m4_defun([wrap],
+[pre
+d
+d
+post])dnl
+wrap
+]],
+[[a
+b
+c
+pre
+d
+d
+post
+]])
+
+dnl Direct invocation, top level
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_defun([a], [[a]])dnl
+m4_defun([b], [[b]m4_require([a])])dnl
+m4_defun([c], [[c]m4_require([b])])dnl
+pre
+a
+c
+a
+c
+post
+]],
+[[pre
+a
+b
+c
+a
+c
+post
+]])
+
+dnl Direct invocation, nested.  This is an example of expansion before
+dnl requirement, such that b occurs before its prerequisite a.  This
+dnl indicates a bug in the macros (but not in autoconf), so we should
+dnl be emitting a warning.
+AT_CHECK_M4SUGAR_TEXT([[dnl
+m4_defun([a], [[a]])dnl
+m4_defun([b], [[b]m4_require([a])])dnl
+m4_defun([c], [[c]m4_require([b])])dnl
+m4_defun([outer],
+[pre
+a
+c
+a
+c
+post])dnl
+outer
+]],
+[[b
+pre
+a
+c
+a
+c
+post
+]], [stderr])
+AT_XFAIL_IF([:])
+AT_CHECK([test -s stderr])
+
+AT_CLEANUP
+
+
 ## --------- ##
 ## m4_cond.  ##
 ## --------- ##