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

23.3 Guidelines for writing macros

There are some guidelines which should be followed when writing a macro. The criteria for a well-written macro are that it should be easy to use, well documented and, most importantly, portable. Portability is a difficult problem that requires much anticipation on the part of the macro writer. This section will discuss the design considerations for using a static Autoconf test at compile time versus a test at runtime. It will also cover some of the characteristics of a good macro including non-interactive behavior, properly formatted output and a clean interface for the user of the macro.


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

23.3.1 Non-interactive behavior

Autoconf’s generated ‘configure’ scripts are designed to be non-interactive – they should not prompt the user for input. Many users like the fact that ‘configure’ can be used as part of a automated build process. By introducing code into ‘configure’ which prompts a user for more information, you will prohibit unattended operation. Instead, you should use the AC_ARG_ENABLE macro in ‘configure.in’ to add extra options to ‘configure’ or consider runtime configuration (see section Testing system features at application runtime).


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

23.3.2 Testing system features at application runtime

When pondering how to handle a difficult portability problem or configurable option, consider whether the problem is better solved by performing tests at runtime or by providing a configuration file to customize the application. Keep in mind that the results of tests that Autoconf can perform will ultimately affect how the program will be built–and can limit the number of machines that the program can be moved to without recompiling it. Here is an example where this consideration had to be made in a real life project:

The pthreads for Win32 project has sought to provide a standards compliant implementation for the POSIX threads API. It does so by mapping the POSIX API functions into small functions which achieve the desired result using the Win32 thread API. Windows 95, Windows 98 and Windows NT have different levels of support for a system call primitive that attempts to enter a critical section without blocking. The TryEnterCriticalSection function is missing on Windows 95, is an inoperative stub on Windows 98, and works as expected on Windows NT. If this behavior was to be checked by ‘configure’ at compile time, then the resultant library would only work on the variant of Windows that it was compiled for. Because it’s more common to distribute packages for Windows in binary form, this would be an unfortunate situation. Instead, it is sometimes preferable to handle this kind of portability problem with a test, performed by your code at runtime.


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

23.3.3 Output from macros

Users who run ‘configure’ expect a certain style of output as tests are performed. As such, you should use the well-defined interface to the existing Autoconf macros for generating output. Your tests should not arbitrarily echo messages to the standard output.

Autoconf provides the following macros to output the messages for you in a consistent way (see section How to run configure and make). They are introduced here with a brief description of their purpose and are documented in more detail in Autoconf Macro Reference. Typically, a test starts by invoking AC_MSG_CHECKING to describe to the user what the test is doing and AC_MSG_RESULT is invoked to output the result of the test.

AC_MSG_CHECKING

This macro is used to notify the user that a test is commencing. It prints the text ‘checking’ followed by your message and ends with ‘...’. You should use ‘AC_MSG_RESULT’ after this macro to output the result of the test.

AC_MSG_RESULT

This macro notifies the user of a test result. In general, the result should be the word ‘yes’ or ‘no’ for boolean tests, or the actual value of the result, such as a directory or filename.

AC_MSG_ERROR

This macro emits a hard error message and aborts ‘configure’–this should be used for fatal errors.

AC_MSG_WARN

This macro emits a warning to the user and proceeds.


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

23.3.4 Naming macros

Just like functions in a C program, it’s important to choose a good name for your Autoconf macros. A well-chosen name helps to unambiguously describe the purpose of the macro. Macros in M4 are all named within a single namespace and, thus, it is necessary to follow a convention to ensure that names retain uniqueness. This reasoning goes beyond just avoiding collisions with other macros–if you happen to choose a name that is already known to M4 as a definition of any kind, your macro’s name could be rewritten by the prior definition during macro processing.

One naming convention has emerged–prefixing each macro name with the name of the package that the macro originated in or the initials of the macro’s author. Macros are usually named in a hierarchical fashion, with each part of the name separated by underscores. As you move left-to-right through each component of the name, the description becomes more detailed. There are some high-level categories of macros suggested by the Autoconf manual that you may wish to use when forming a descriptive name for your own macro. For example, if your macro tries to discover the existence of a particular C structure, you might wish to use C and STRUCT as components of its name.

C

Tests related to constructs of the C programming language.

DECL

Tests for variable declarations in header files.

FUNC

Tests for functions present in (or absent from) libraries.

HEADER

Tests for header files.

LIB

Tests for libraries.

PATH

Tests to discover absolute filenames (especially programs).

PROG

Tests to determine the base names of programs.

STRUCT

Tests for definitions of C structures in header files.

SYS

Tests for operating system features, such as restartable system calls.

TYPE

Tests for built-in or declared C data types.

VAR

Tests for C variables in libraries.

Some examples of macro names formed in this way include:

AC_PROG_CC

A test that looks for a program called cc.

AC_C_INLINE

A test that discovers if the C keyword inline is recognized.

bje_CXX_MUTABLE

A test, written by "bje", that discovers if the C++ keyword mutable is recognized.


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

23.3.5 Macro interface

When designing your macro, it is worth spending some time deciding on what your macro’s interface–the macro’s name and argument list–will be. Often, it will be possible to extract general purpose functionality into a generic macro and to write a second macro which is a client of the generic one. Like planning the prototype for a C function, this is usually a straightforward process of deciding what arguments are required by the macro to perform its function. However, there are a couple of further considerations and they are discussed below.

M4 macros refer to their arguments by number with a syntax such as $1. It is typically more difficult to read an M4 macro definition and understand what each argument’s designation is than in a C function body, where the formal argument is referred to by its name. Therefore, it’s a good idea to include a standard comment block above each macro that documents the macro and gives an indication of what each argument is for. Here is an example from the Autoconf source code:

 
# AC_CHECK_FILE(FILE, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------------------------
#
# Check for the existence of FILE.

To remain general purpose, the existing Autoconf macros follow the convention of keeping side-effects outside the definition of the macro. Here, when a user invokes ‘AC_CHECK_FILE’, they must provide shell code to implement the side effect that they want to occur if the ‘FILE’ is found or is not found. Some macros implement a basic and desirable action like defining a symbol like ‘HAVE_UNISTD_H’ if no user-defined actions are provided. In general, your macros should provide an interface which is consistent with the interfaces provided by the core Autoconf macros.

M4 macros may have variable argument lists, so it is possible to implement macros which have defaults for arguments. By testing each individual argument against the empty string with ‘ifelse’, it is possible for users to accept the default behavior for individual arguments by passing empty values:

 
AC_CHECK_FILE([/etc/passwd], [],
              [AC_MSG_ERROR([something is really wrong])])

One final point to consider when designing the interface for a macro is how to handle macros that are generic in nature and, say, wish to set a cache variable whose name is based on one of the arguments. Consider the ‘AC_CHECK_HEADER’ macro–it defines a symbol and makes an entry in the cache that reflects the result of the test it performs. ‘AC_CHECK_HEADER’ takes an argument – namely the name of a header file to look for. This macro cannot just make a cache entry with a name like ac_cv_check_header, since it would only work once; any further uses of this macro in ‘configure.in’ would cause an incorrect result to be drawn from the cache. Instead, the name of the symbol that is defined and the name of the cache variable that is set need to be computed from one of the arguments: the name of the header file being sought. What we really need is to define HAVE_UNISTD_H and set the cache variable ac_cv_header_unistd_h. This can be achieved with some sed and tr magic in the macro which transforms the filename into uppercase characters for the call to AC_DEFINE and into lowercase for the cache variable name. Unknown characters such as ‘.’ need to be transformed into underscores.

Some existing macros also allow the user to pass in the name of a cache variable name so that the macro does not need to compute a name. In general, this should be avoided, as it makes the macro harder to use and exposes details of the caching system to the user.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Ben Elliston on July 10, 2015 using texi2html 1.82.