Noeud:Keep It Stupid Simple, Noeud « Up »:Understanding Autoconf



Keep It Stupid Simple

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

Never try to be smart with Autoconf
Many people write configure.acs 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.

The first most common problem is relying on undocumented features. You should 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, change some low level macros! This is doomed to failure. There are several reasons making maintainers try this perverse game:

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 configure. You should really 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.
adjust existing macros to different needs
Many people want to hook their code onto Autoconf macros. For instance, "when AC_PROG_CC is called I want 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: 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 configure.

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

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

The second most common problem is people trying to optimize 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), never perform tests conditionally: depend conditionally on their output!

Here is a simple example of such a broken "optimized" configure.ac:

     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
     

The following runs clearly demonstrate the point of this optimization:

     $ ./configure
     

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

     $ ./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
     

Similarly if both fprintf and sprintf are needed:

     $ ./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
     

As expected, fprintf and sprintf are both available on my GNU/Linux system.

Now, sit back, and look at this:

     $ ./configure --with-sprintf
     checking for sprintf... no
     

although sprintf 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 configure.ac:

     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
     

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

     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