Back: Naming macros
Forward: Implementation specifics
 
FastBack: Implementation specifics
Up: Guidelines for writing macros
FastForward: Implementation specifics
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

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.



This document was generated by Gary V. Vaughan on February, 8 2006 using texi2html