[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6. Writing Tests

If the existing feature tests don't do something you need, you have to write new ones. These macros are the building blocks. They provide ways for other macros to check whether various kinds of features are available and report the results.

This chapter contains some suggestions and some of the reasons why the existing tests are written the way they are. You can also learn a lot about how to write Autoconf tests by looking at the existing ones. If something goes wrong in one or more of the Autoconf tests, this information can help you understand the assumptions behind them, which might help you figure out how to best solve the problem.

These macros check the output of the compiler system of the current language (see section 6.1 Language Choice). They do not cache the results of their tests for future use (see section 7.3 Caching Results), because they don't know enough about the information they are checking for to generate a cache variable name. They also do not print any messages, for the same reason. The checks for particular kinds of features call these macros and do cache their results and print messages about what they're checking for.

When you write a feature test that could be applicable to more than one software package, the best thing to do is encapsulate it in a new macro. See section 9. Writing Autoconf Macros, for how to do that.

6.1 Language Choice  Selecting which language to use for testing
6.2 Writing Test Programs  Forging source files for compilers
6.3 Running the Preprocessor  Detecting preprocessor symbols
6.4 Running the Compiler  Detecting language or header features
6.5 Running the Linker  Detecting library features
6.6 Checking Run Time Behavior  Testing for run-time features
6.7 Systemology  A zoology of operating systems
6.8 Multiple Cases  Tests for several possible values


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.1 Language Choice

Autoconf-generated configure scripts check for the C compiler and its features by default. Packages that use other programming languages (maybe more than one, e.g., C and C++) need to test features of the compilers for the respective languages. The following macros determine which programming language is used in the subsequent tests in `configure.ac'.

Macro: AC_LANG (language)
Do compilation tests using the compiler, preprocessor, and file extensions for the specified language.

Supported languages are:

`C'
Do compilation tests using CC and CPP and use extension `.c' for test programs.

`C++'
Do compilation tests using CXX and CXXCPP and use extension `.C' for test programs.

`Fortran 77'
Do compilation tests using F77 and use extension `.f' for test programs.

Macro: AC_LANG_PUSH (language)
Remember the current language (as set by AC_LANG) on a stack, and then select the language. Use this macro and AC_LANG_POP in macros that need to temporarily switch to a particular language.

Macro: AC_LANG_POP ([language])
Select the language that is saved on the top of the stack, as set by AC_LANG_PUSH, and remove it from the stack.

If given, language specifies the language we just quit. It is a good idea to specify it when it's known (which should be the case...), since Autoconf will detect inconsistencies.

 
AC_LANG_PUSH(Fortran 77)
# Perform some tests on Fortran 77.
# ...
AC_LANG_POP(Fortran 77)

Macro: AC_REQUIRE_CPP
Ensure that whichever preprocessor would currently be used for tests has been found. Calls AC_REQUIRE (see section 9.4.1 Prerequisite Macros) with an argument of either AC_PROG_CPP or AC_PROG_CXXCPP, depending on which language is current.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2 Writing Test Programs

Autoconf tests follow is common scheme: feeding some program with some input, and most of the time, feeding a compiler with some source file. This section is dedicated to these source samples.

6.2.1 Guidelines for Test Programs  General rules for writing test programs
6.2.2 Test Functions  Avoiding pitfalls in test programs
6.2.3 Generating Sources  Source program boilerplate


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2.1 Guidelines for Test Programs

The most important rule to follow when writing testing samples is:

Look for realism.

This motto means that testing samples must be written with the same strictness as real programs are written. In particular, you should avoid "shortcuts" and simplifications.

Don't just play with the preprocessor if you want to prepare a compilation. For instance, using cpp to check if a header is functional might let your configure accept a header which will cause some compiler error. Do not hesitate checking header with other headers included before, especially required headers.

Make sure the symbols you use are properly defined, i.e., refrain for simply declaring a function yourself instead of including the proper header.

Test programs should not write anything to the standard output. They should return 0 if the test succeeds, nonzero otherwise, so that success can be distinguished easily from a core dump or other failure; segmentation violations and other failures produce a nonzero exit status. Test programs should exit, not return, from main, because on some systems (old Suns, at least) the argument to return in main is ignored.

Test programs can use #if or #ifdef to check the values of preprocessor macros defined by tests that have already run. For example, if you call AC_HEADER_STDC, then later on in `configure.ac' you can have a test program that includes an ANSI C header file conditionally:

 
#if STDC_HEADERS
# include <stdlib.h>
#endif

If a test program needs to use or create a data file, give it a name that starts with `conftest', such as `conftest.data'. The configure script cleans up by running `rm -rf conftest*' after running test programs and if the script is interrupted.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2.2 Test Functions

Function declarations in test programs should have a prototype conditionalized for C++. In practice, though, test programs rarely need functions that take arguments.

 
#ifdef __cplusplus
foo (int i)
#else
foo (i) int i;
#endif

Functions that test programs declare should also be conditionalized for C++, which requires `extern "C"' prototypes. Make sure to not include any header files containing clashing prototypes.

 
#ifdef __cplusplus
extern "C" void *malloc (size_t);
#else
void *malloc ();
#endif

If a test program calls a function with invalid parameters (just to see whether it exists), organize the program to ensure that it never invokes that function. You can do this by calling it in another function that is never invoked. You can't do it by putting it after a call to exit, because GCC version 2 knows that exit never returns and optimizes out any code that follows it in the same block.

If you include any header files, be sure to call the functions relevant to them with the correct number of arguments, even if they are just 0, to avoid compilation errors due to prototypes. GCC version 2 has internal prototypes for several functions that it automatically inlines; for example, memcpy. To avoid errors when checking for them, either pass them the correct number of arguments or redeclare them with a different return type (such as char).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.2.3 Generating Sources

Autoconf provides a set of macros that can be used to generate test source files. They are written to be language generic, i.e., they actually depend on the current language (see section 6.1 Language Choice) to "format" the output properly.

Macro: AC_LANG_CONFTEST (source)
Save the source text in the current test source file: `conftest.extension' where the extension depends on the current language.

Note that the source is evaluated exactly once, like regular Autoconf macro arguments, and therefore (i) you may pass a macro invocation, (ii) if not, be sure to double quote if needed.

Macro: AC_LANG_SOURCE (source)
Expands into the source, with proper definition of the current location (e.g., `#line 1234 "configure"' in C), and definition of all the AC_DEFINE performed so far.

For instance executing (observe the double quotation!):

 
AC_INIT(Autoconf Documentation, 2.57, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_LANG_CONFTEST(
   [AC_LANG_SOURCE([[const char hw[] = "Hello, World\n";]])])
gcc -E -dD conftest.c -o -

results in:

 
# 1 "conftest.c"
# 1169 "configure"

# 1 "confdefs.h" 1

#define PACKAGE_NAME "Autoconf Documentation"
#define PACKAGE_TARNAME "autoconf-documentation"
#define PACKAGE_VERSION "2.57"
#define PACKAGE_STRING "Autoconf Documentation 2.57"
#define PACKAGE_BUGREPORT "bug-autoconf@gnu.org"
#define HELLO_WORLD "Hello, World\n"
# 1170 "configure" 2

const char hw[] = "Hello, World\n";

Macro: AC_LANG_PROGRAM (prologue, body)
Expands into a source file which consists of the prologue, and then body as body of the main function (e.g., main in C). Since it uses AC_LANG_SOURCE, the feature of the latter are available.

For instance:

 
AC_INIT(Autoconf Documentation, 2.57, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_LANG_CONFTEST(
[AC_LANG_PROGRAM([[const char hw[] = "Hello, World\n";]],
                 [[fputs (hw, stdout);]])])
gcc -E -dD conftest.c -o -

results in:

 
# 1 "conftest.c"
# 1169 "configure"

# 1 "confdefs.h" 1

#define PACKAGE_NAME "Autoconf Documentation"
#define PACKAGE_TARNAME "autoconf-documentation"
#define PACKAGE_VERSION "2.57"
#define PACKAGE_STRING "Autoconf Documentation 2.57"
#define PACKAGE_BUGREPORT "bug-autoconf@gnu.org"
#define HELLO_WORLD "Hello, World\n"
# 1170 "configure" 2

const char hw[] = "Hello, World\n";
int
main ()
{
fputs (hw, stdout);
  ;
  return 0;
}

Macro: AC_LANG_CALL (prologue, function)
Expands into a source file which consists of the prologue, and then a call to the function as body of the main function (e.g., main in C). Since it uses AC_LANG_PROGRAMS, the feature of the latter are available.

This function will probably be replaced in the feature by a version which would enable specifying the arguments. The use of this macro is not encouraged, as it violates strongly the typing system.

Macro: AC_LANG_FUNC_LINK_TRY (function)
Expands into a source file which consists of a pseudo use of the function as body of the main function (e.g., main in C): a simple (function pointer) assignment. Since it uses AC_LANG_PROGRAMS, the feature of the latter are available.

As AC_LANG_CALL, this macro is documented only for completeness. It is considered to be severely broken, and in the future will be removed in favor of actual function calls (with properly typed arguments).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.3 Running the Preprocessor

Sometimes one might need to run the preprocessor on some source file. Usually it is a bad idea, as you typically need to compile your project, not merely run the preprocessor on it; therefore you certainly want to run the compiler, not the preprocessor. Resist to the temptation of following the easiest path.

Nevertheless, if you need to run the preprocessor, then use AC_PREPROC_IFELSE.

Macro: AC_PREPROC_IFELSE (input, [action-if-true], [action-if-false])
Run the preprocessor of the current language (see section 6.1 Language Choice) on the input, run the shell commands action-if-true on success, action-if-false otherwise. The input can be made by AC_LANG_PROGRAM and friends.

This macro uses CPPFLAGS, but not CFLAGS, because `-g', `-O', etc. are not valid options to many C preprocessors.

It is customary to report unexpected failures with AC_MSG_FAILURE.

For instance:

 
AC_INIT(Autoconf Documentation, 2.57, bug-autoconf@gnu.org)
AC_DEFINE([HELLO_WORLD], ["Hello, World\n"])
AC_PREPROC_IFELSE(
   [AC_LANG_PROGRAM([[const char hw[] = "Hello, World\n";]],
                    [[fputs (hw, stdout);]])],
   [AC_MSG_RESULT([OK])],
   [AC_MSG_FAILURE([unexpected preprocessor failure])])

results in:

 
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 suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking how to run the C preprocessor... gcc -E
OK

The macro AC_TRY_CPP (see section 15.4 Obsolete Macros) used to play the role of AC_PREPROC_IFELSE, but double quotes its argument, making it impossible to use it to ellaborate sources. You are encouraged to get rid of your old use of the macro AC_TRY_CPP in favor of AC_PREPROC_IFELSE, but, in the first place, are you sure you need to run the preprocessor and not the compiler?

Macro: AC_EGREP_HEADER (pattern, header-file, action-if-found, [action-if-not-found])
If the output of running the preprocessor on the system header file header-file matches the extended regular expression pattern, execute shell commands action-if-found, otherwise execute action-if-not-found.

Macro: AC_EGREP_CPP (pattern, program, [action-if-found], [action-if-not-found])
program is the text of a C or C++ program, on which shell variable, back quote, and backslash substitutions are performed. If the output of running the preprocessor on program matches the extended regular expression pattern, execute shell commands action-if-found, otherwise execute action-if-not-found.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4 Running the Compiler

To check for a syntax feature of the (C, C++, or Fortran 77) compiler, such as whether it recognizes a certain keyword, or simply to try some library feature, use AC_COMPILE_IFELSE to try to compile a small program that uses that feature.

Macro: AC_COMPILE_IFELSE (input, [action-if-found], [action-if-not-found])
Run the compiler of the current language (see section 6.1 Language Choice) on the input, run the shell commands action-if-true on success, action-if-false otherwise. The input can be made by AC_LANG_PROGRAM and friends.

This macro uses CFLAGS or CXXFLAGS if either C or C++ is the currently selected language, as well as CPPFLAGS, when compiling. If Fortran 77 is the currently selected language then FFLAGS will be used when compiling.

It is customary to report unexpected failures with AC_MSG_FAILURE. This macro does not try to link; use AC_LINK_IFELSE if you need to do that (see section 6.5 Running the Linker).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.5 Running the Linker

To check for a library, a function, or a global variable, Autoconf configure scripts try to compile and link a small program that uses it. This is unlike Metaconfig, which by default uses nm or ar on the C library to try to figure out which functions are available. Trying to link with the function is usually a more reliable approach because it avoids dealing with the variations in the options and output formats of nm and ar and in the location of the standard libraries. It also allows configuring for cross-compilation or checking a function's run-time behavior if needed. On the other hand, it can be slower than scanning the libraries once, but accuracy is more important than speed.

AC_LINK_IFELSE is used to compile test programs to test for functions and global variables. It is also used by AC_CHECK_LIB to check for libraries (see section 5.4 Library Files), by adding the library being checked for to LIBS temporarily and trying to link a small program.

Macro: AC_LINK_IFELSE (input, [action-if-found], [action-if-not-found])
Run the compiler and the linker of the current language (see section 6.1 Language Choice) on the input, run the shell commands action-if-true on success, action-if-false otherwise. The input can be made by AC_LANG_PROGRAM and friends.

This macro uses CFLAGS or CXXFLAGS if either C or C++ is the currently selected language, as well as CPPFLAGS, when compiling. If Fortran 77 is the currently selected language then FFLAGS will be used when compiling.

It is customary to report unexpected failures with AC_MSG_FAILURE. This macro does not try to execute the program; use AC_RUN_IFELSE if you need to do that (see section 6.6 Checking Run Time Behavior).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.6 Checking Run Time Behavior

Sometimes you need to find out how a system performs at run time, such as whether a given function has a certain capability or bug. If you can, make such checks when your program runs instead of when it is configured. You can check for things like the machine's endianness when your program initializes itself.

If you really need to test for a run-time behavior while configuring, you can write a test program to determine the result, and compile and run it using AC_RUN_IFELSE. Avoid running test programs if possible, because this prevents people from configuring your package for cross-compiling.

Macro: AC_RUN_IFELSE (input, [action-if-found], [action-if-not-found], [action-if-cross-compiling])
If program compiles and links successfully and returns an exit status of 0 when executed, run shell commands action-if-true. Otherwise, run shell commands action-if-false.

The input can be made by AC_LANG_PROGRAM and friends. This macro uses CFLAGS or CXXFLAGS, CPPFLAGS, LDFLAGS, and LIBS

If the compiler being used does not produce executables that run on the system where configure is being run, then the test program is not run. If the optional shell commands action-if-cross-compiling are given, they are run instead. Otherwise, configure prints an error message and exits.

In the action-if-false section, the exit status of the program is available in the shell variable `$?', but be very careful to limit yourself to positive values smaller than 127; bigger values should be saved into a file by the program. Note also that you have simply no guarantee that this exit status is issued by the program, or by the failure of its compilation. In other words, use this feature if sadist only, it was reestablished because the Autoconf maintainers grew tired of receiving "bug reports".

It is customary to report unexpected failures with AC_MSG_FAILURE.

Try to provide a pessimistic default value to use when cross-compiling makes run-time tests impossible. You do this by passing the optional last argument to AC_RUN_IFELSE. autoconf prints a warning message when creating configure each time it encounters a call to AC_RUN_IFELSE with no action-if-cross-compiling argument given. You may ignore the warning, though users will not be able to configure your package for cross-compiling. A few of the macros distributed with Autoconf produce this warning message.

To configure for cross-compiling you can also choose a value for those parameters based on the canonical system name (see section 11. Manual Configuration). Alternatively, set up a test results cache file with the correct values for the host system (see section 7.3 Caching Results).

To provide a default for calls of AC_RUN_IFELSE that are embedded in other macros, including a few of the ones that come with Autoconf, you can test whether the shell variable cross_compiling is set to `yes', and then use an alternate method to get the results instead of calling the macros.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.7 Systemology

This section aims at presenting some systems and pointers to documentation. It may help you addressing particular problems reported by users.

The Rosetta Stone for Unix contains a lot of interesting crossed information on various Unices.

Darwin
Darwin is also known as Mac OS X. Beware that the file system can be case-preserving, but case insensitive. This can cause nasty problems, since for instance the installation attempt for a package having an `INSTALL' file can result in `make install' report that nothing was to be done!

That's all dependent on whether the file system is a UFS (case sensitive) or HFS+ (case preserving). By default Apple wants you to install the OS on HFS+. Unfortunately, there are some pieces of software which really need to be built on UFS. We may want to rebuild Darwin to have both UFS and HFS+ available (and put the /local/build tree on the UFS).

QNX 4.25
QNX is a realtime operating system running on Intel architecture meant to be scalable from the small embedded systems to the hundred processor super-computer. It claims to be POSIX certified. More information is available on the QNX home page, including the QNX man pages.

Tru64
The documentation of several versions of Tru64 is available in different formats.

Unix version 7
Documentation is available in the V7 Manual.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.8 Multiple Cases

Some operations are accomplished in several possible ways, depending on the UNIX variant. Checking for them essentially requires a "case statement". Autoconf does not directly provide one; however, it is easy to simulate by using a shell variable to keep track of whether a way to perform the operation has been found yet.

Here is an example that uses the shell variable fstype to keep track of whether the remaining cases need to be checked.

 
AC_MSG_CHECKING([how to get file system type])
fstype=no
# The order of these tests is important.
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statvfs.h>
#include <sys/fstyp.h>]])],
                  [AC_DEFINE(FSTYPE_STATVFS) fstype=SVR4])
if test $fstype = no; then
  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statfs.h>
#include <sys/fstyp.h>]])],
                  [AC_DEFINE(FSTYPE_USG_STATFS) fstype=SVR3])
fi
if test $fstype = no; then
  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/statfs.h>
#include <sys/vmount.h>]])]),
                  [AC_DEFINE(FSTYPE_AIX_STATFS) fstype=AIX])
fi
# (more cases omitted here)
AC_MSG_RESULT([$fstype])


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Jeff Bailey on December, 24 2002 using texi2html