bison-patches
[Top][All Lists]
Advanced

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

What is AC_CHECK_FUNCS_ONCE?


From: Akim Demaille
Subject: What is AC_CHECK_FUNCS_ONCE?
Date: Sat, 29 Mar 2003 14:50:18 +0100
User-agent: Gnus/5.090016 (Oort Gnus v0.16) Emacs/21.2 (gnu/linux)

Bison no longer compiled properly under Debian (!).  This is because
of some bad Autoconf assumptions.  This is also because of some macro
named AC_CHECK_FUNCS_ONCE which is not an Autoconf macro, and
therefore should not be named AC_.  The m4_pattern_forbid macro was
introduced so that other prefixes can be used with the same benefits.

The patch consists in:

Index: ChangeLog
from  Akim Demaille  <address@hidden>

        * m4/error.m4: Do not put under dynamic conditions some code which
        expansion is under static control.

Index: m4/error.m4
===================================================================
RCS file: /cvsroot/bison/bison/m4/error.m4,v
retrieving revision 1.4
diff -u -u -r1.4 error.m4
--- m4/error.m4 12 Mar 2003 23:08:11 -0000 1.4
+++ m4/error.m4 29 Mar 2003 13:42:51 -0000
@@ -1,12 +1,10 @@
-#serial 5
+#serial 6
 
 AC_DEFUN([gl_ERROR],
 [
   AC_FUNC_ERROR_AT_LINE
   dnl Note: AC_FUNC_ERROR_AT_LINE does AC_LIBSOURCES([error.h, error.c]).
-  if test $ac_cv_lib_error_at_line = no; then
-    jm_PREREQ_ERROR
-  fi
+  jm_PREREQ_ERROR
 ])
 
 # Prerequisites of lib/error.c.



Without this patch, because of AC_CHECK_FUNCS_ONCE, the correct
invocation to AC_CHECK_FUNCS and DECLS for strerror (and others I
guess) are simply skipped.  I would like to warn the authors of this
_ONCE stuff.  Playing with REQUIRE is an extremely dangerous game to
play, you ought to know all the rules to avoid pitfalls.  I include
below a piece of documentation I had written for a still born book.

----------------------------------------------------------------------
@node Understanding Autoconf
@section Understanding Autoconf

Teaching to the reader the long road to Autoconf guruness is way beyond
the scope of this book.  Exploiting the full power of Autoconf is,
unfortunately, reserved to the few people who are ready to spend hours
tracking portability issues, as mastering Autoconf stands for mastering
portability issues.

Nevertheless, we feel you ought to be revealed a few secrets about
Autoconf.


@menu
* Keep It Stupid Simple::
@end menu

@node Keep It Stupid Simple
@subsection Keep It Stupid Simple

It is unfortunate that the most important rule is still a secret today:

@center Never try to be smart with Autoconf

Many people write @file{configure.ac}s that are rejected by different
versions of Autoconf, or will be rejected in the future.  The Autoconf
maintainers often receive complaints about such problems, but they are
really introduced by the users themselves.

@sp 1

The first most common problem is relying on undocumented features.  You
should @strong{never} do that.  If it is undocumented, it is private, and
likely to be changed in the future.  The most frequent reason to rely on
undocumented feature is to save some typing: you have to address a task,
and notice some internal macro performs a job close to your needs.
Don't use it: either you copy and adjust it to your very needs ---under
a different name of course---, or you ask to the maintainers to make a
public version of this macro.

The worst case is with people who want to rely on very low level
details, or even in some cases, @emph{change} some low level macros!
This is doomed to failure.  There are several reasons making maintainers
try this perverse game:

@table @asis
@item bypass the official interface
Autoconf follows the GNU Coding Standards, which some people sometimes
find painful ---for instance because they want options that do not fall
into the GNU standard set of options for @command{configure}.  You
should rely stick to these standards, experience has proved that they
cover all the needs, possibly in an admittedly convoluted way.  And if
they don't, then ask for changes in the GNU Coding Standards: Autoconf
will follow.

@item adjust existing macros to different needs
Many people want to hook their code onto Autoconf macros.  For instance,
``when @code{AC_PROG_CC} is called I want @code{MY_PROG_CC_HOOK} to be
invoked''.  You cannot imagine the complex tissue of interdependencies
that already exists in Autoconf!  Checking for a compiler for instance,
requires relying on many different preliminary initializations and
checks.  The following figures should give you an idea of this amount of
work: @code{AC_PROG_CC} alone produces more than 20Kb of code, almost
900 lines of shell script!  And this code is not contiguous: it goes
into three different sections of @command{configure}.

Don't try to hook your macros: just invoke them.  Sure, your change is
not longer ``invisible'', the user must call it explicitly, but at least
it will be robust.
@end table

If you see no option to address your need, ask the Autoconf maintainers:
either the know the right way to do it, or they will provide you with a
new macro in the official Autoconf.

@sp 1

The second most common problem is trying to optimize
@command{configure}.  For instance they skip long series of tests needed
only for some features the user did not chose.  This exposes you to
extremely nasty, stealthy, vicious bugs.  Unless you know exactly what
you do (I am here referring to people who have an exact knowledge of
Autoconf), @emph{never perform tests conditionally: depend conditionally
on their output!}

Here is a simple example of such an broken ``optimized''
@file{configure.ac}:

@example
AC_INIT

AC_ARG_WITH([fprintf])
if test "x$with_fprintf" = xyes; then
  AC_CHECK_FUNCS(fprintf)
fi

AC_ARG_WITH([sprintf])
if test "x$with_sprintf" = xyes; then
  AC_CHECK_FUNCS(sprintf)
fi
@end example

@noindent
The following runs clearly demonstrate the point of this optimization:

@example
$ @kbd{./configure}
@end example

@noindent
as nothing was needed, nothing was checked for.  If using @code{fprintf}
is requested, then of course, we need a C compiler to check for its
existence, and then check for it:

@example
$ @kbd{./configure --with-fprintf}
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for executable suffix...
checking for object suffix... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for fprintf... yes
@end example

@noindent
Similarly if both @code{fprintf} and @code{sprintf} are needed:

@example
$ @kbd{./configure --with-fprintf --with-sprintf}
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for executable suffix...
checking for object suffix... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for fprintf... yes
checking for sprintf... yes
@end example

@noindent
As expected, @code{fprintf} and @code{sprintf} are both available on my
GNU/Linux system.

Now, sit back, and look at this:

@example
$ @kbd{./configure --with-sprintf}
checking for sprintf... no
@end example

@noindent
although @code{sprintf} @emph{is} present!

What happened is that Autoconf knows that checking for a function
requires a compiler for the current language (here, C), so it actually
expands something similar to the following @file{configure.ac}:

@example
AC_INIT

AC_ARG_WITH([fprintf])
if test "x$with_fprintf" = xyes; then
  AC_PROG_CC
  AC_CHECK_FUNCS(fprintf)
fi

AC_ARG_WITH([sprintf])
if test "x$with_sprintf" = xyes; then
  AC_CHECK_FUNCS(sprintf)
fi
@end example

@noindent
As a consequence, if @code{fprintf} is not requested,
@command{configure} will not look for a C compiler, and all the
following tests are broken.  Never run tests conditionally: depend
conditionally on the @emph{results} of the tests:

@example
AC_INIT

AC_ARG_WITH([fprintf])
AC_CHECK_FUNCS(fprintf)
if test "x$with_fprintf" = xyes; then
  # Depend on the presence/absence of fprintf here.
fi

AC_ARG_WITH([sprintf])
AC_CHECK_FUNCS(sprintf)
if test "x$with_sprintf" = xyes; then
  # Depend on the presence/absence of sprintf here.
fi
@end example




reply via email to

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