autoconf config.h prefixing


A little while back in the OpenPA project we realized that we had a problem with the way that autoconf works by default. Normally in your configure.in (or configure.ac) you specify a config.h file via the AC_CONFIG_HEADER macro that will contain the results of any AC_DEFINE macro invocations. Then your .c files include this file and will compile different code based on the definitions in your config.h. This is all well and fine as long as your project either results in an executable or your project results in a library with minimal platform-dependence in the header files.

Unfortunately this doesn’t work so well when the vast majority of your project is header files full of very platform-dependent inline functions. The problem you have is that you need to install the config.h that you generated containing all of the platform-specific information when the project is installed. This is a problem for two reasons:

  1. You potentially pollute the preprocessor include paths if you pick the typical name, “config.h”. This is really a minor issue since this name is easily selectable at AC_CONFIG_HEADER time.
  2. You definitely pollute the preprocessor macro namespace with all of the AC_DEFINE definitions. For example, if you invoke AC_CHECK_SIZEOF([int]) in your configure.in then you’ll end up with a definition for SIZEOF_INT in your configuration header. This of course would then potentially conflict with a similar definition in any project that includes your project’s config.h. That particular macro may not be a problem because both projects will probably determine the same value and the preprocessor will ignore multiple identical definitions of the same macro. However, some of the predefined macros will give you trouble like VERSION or PACKAGE_NAME which are practically guaranteed to be different from package to package.

The fix is to use the AX_PREFIX_CONFIG macro. At AC_OUTPUT time this macro makes a copy of your config.h and performs two transformations on it before outputting it to a different header file. The first transformation is that all preprocessor macro definitions are prepended with a prefix of your choosing. So in OpenPA a macro like SIZEOF_FOO becomes OPA_SIZEOF_FOO. The second transformation is that rather than unconditionally defining these macros they are converted to a form like:

#ifndef OPA_SIZEOF_FOO
#define OPA_SIZEOF_FOO 4
#endif

This avoids an error from the preprocessor in case it is not standards compliant about macro redefinition or if there is still an accidental namespace conflict for some reason after the prefixing step. You can see how we used the macro here in the source.