autoconf: Expanded Before Required

1 
1 20.8 Expanded Before Required
1 =============================
1 
1 Older versions of Autoconf silently built files with incorrect ordering
1 between dependent macros if an outer macro first expanded, then later
1 indirectly required, an inner macro.  Starting with Autoconf 2.64, this
1 situation no longer generates out-of-order code, but results in
1 duplicate output and a syntax warning:
1 
1      $ cat configure.ac
1      =>AC_DEFUN([TESTA], [[echo in A
1      =>if test -n "$SEEN_A" ; then echo duplicate ; fi
1      =>SEEN_A=:]])
1      =>AC_DEFUN([TESTB], [AC_REQUIRE([TESTA])[echo in B
1      =>if test -z "$SEEN_A" ; then echo bug ; fi]])
1      =>AC_DEFUN([TESTC], [AC_REQUIRE([TESTB])[echo in C]])
1      =>AC_DEFUN([OUTER], [[echo in OUTER]
1      =>TESTA
1      =>TESTC])
1      =>AC_INIT
1      =>OUTER
1      =>AC_OUTPUT
1      $ autoconf
1      =>configure.ac:11: warning: AC_REQUIRE:
1      => `TESTA' was expanded before it was required
1      =>configure.ac:4: TESTB is expanded from...
1      =>configure.ac:6: TESTC is expanded from...
1      =>configure.ac:7: OUTER is expanded from...
1      =>configure.ac:11: the top level
1 
1 To avoid this warning, decide what purpose the macro in question serves.
1 If it only needs to be expanded once (for example, if it provides
1 initialization text used by later macros), then the simplest fix is to
11 change the macro to be declared with `AC_DEFUN_ONCE' (⇒One-Shot
 Macros), although this only works in Autoconf 2.64 and newer.  A more
1 portable fix is to change all instances of direct calls to instead go
1 through `AC_REQUIRE' (⇒Prerequisite Macros).  If, instead, the
1 macro is parameterized by arguments or by the current definition of
1 other macros in the m4 environment, then the macro should always be
1 directly expanded instead of required.
1 
1    For another case study, consider this example trimmed down from an
1 actual package.  Originally, the package contained shell code and
1 multiple macro invocations at the top level of `configure.ac':
1 
1      AC_DEFUN([FOO], [AC_COMPILE_IFELSE([...])])
1      foobar=
1      AC_PROG_CC
1      FOO
1 
1 but that was getting complex, so the author wanted to offload some of
1 the text into a new macro in another file included via `aclocal.m4'.
1 The nai"ve approach merely wraps the text in a new macro:
1 
1      AC_DEFUN([FOO], [AC_COMPILE_IFELSE([...])])
1      AC_DEFUN([BAR], [
1      foobar=
1      AC_PROG_CC
1      FOO
1      ])
1      BAR
1 
1 With older versions of Autoconf, the setting of `foobar=' occurs before
1 the single compiler check, as the author intended.  But with Autoconf
1 2.64, this issues the "expanded before it was required" warning for
1 `AC_PROG_CC', and outputs two copies of the compiler check, one before
1 `foobar=', and one after.  To understand why this is happening,
1 remember that the use of `AC_COMPILE_IFELSE' includes a call to
1 `AC_REQUIRE([AC_PROG_CC])' under the hood.  According to the documented
1 semantics of `AC_REQUIRE', this means that `AC_PROG_CC' _must_ occur
1 before the body of the outermost `AC_DEFUN', which in this case is
1 `BAR', thus preceding the use of `foobar='.  The older versions of
1 Autoconf were broken with regards to the rules of `AC_REQUIRE', which
1 explains why the code changed from one over to two copies of
1 `AC_PROG_CC' when upgrading autoconf.  In other words, the author was
1 unknowingly relying on a bug exploit to get the desired results, and
1 that exploit broke once the bug was fixed.
1 
1    So, what recourse does the author have, to restore their intended
1 semantics of setting `foobar=' prior to a single compiler check,
1 regardless of whether Autoconf 2.63 or 2.64 is used?  One idea is to
1 remember that only `AC_DEFUN' is impacted by `AC_REQUIRE'; there is
1 always the possibility of using the lower-level `m4_define':
1 
1      AC_DEFUN([FOO], [AC_COMPILE_IFELSE([...])])
1      m4_define([BAR], [
1      foobar=
1      AC_PROG_CC
1      FOO
1      ])
1      BAR
1 
1 This works great if everything is in the same file.  However, it does
1 not help in the case where the author wants to have `aclocal' find the
1 definition of `BAR' from its own file, since `aclocal' requires the use
1 of `AC_DEFUN'.  In this case, a better fix is to recognize that if
1 `BAR' also uses `AC_REQUIRE', then there will no longer be direct
1 expansion prior to a subsequent require.  Then, by creating yet another
1 helper macro, the author can once again guarantee a single invocation of
1 `AC_PROG_CC', which will still occur after `foobar='.  The author can
1 also use `AC_BEFORE' to make sure no other macro appearing before `BAR'
1 has triggered an unwanted expansion of `AC_PROG_CC'.
1 
1      AC_DEFUN([FOO], [AC_COMPILE_IFELSE([...])])
1      AC_DEFUN([BEFORE_CC], [
1      foobar=
1      ])
1      AC_DEFUN([BAR], [
1      AC_BEFORE([$0], [AC_PROG_CC])dnl
1      AC_REQUIRE([BEFORE_CC])dnl
1      AC_REQUIRE([AC_PROG_CC])dnl
1      FOO
1      ])
1      BAR
1