I have a library project that I'm working on porting to using the autotools suite in Linux. I'm quite new to autotools (this week). I've learned the basics of its operation. I have a question about how to keep the contents of config.h
from being redefined.
I'm surprised to find that the generated config.h
file doesn't either, 1) wrap each macro in a #ifndef
or, 2) that the entire file isn't wrapped in the standard #ifndef CONFIG_H
.
As I've alluded, this code is built on Windows and Linux. Thus there are several uses of a macro, _linux
(I'm not saying that's the best name, but it's in use everywhere) to bring in elements to classes which exist in Linux only. Thus, this will happen
header.h
#ifndef HEADER1_H
#define HEADER1_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif
source.cxx
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "header.h" // oops, preprocessor gets excited because of redefs
One simple solution is I do that standard unique wrap in config.h.in
after the file is generated. However, I was wondering, is there a better way of handling this? I can't be the first to encounter this and there might even be a means of handling it in configure.ac
but being a complete neophyte in this, I don't know what to even search for.
The way I do this is indeed creating a wrapper file (which I usually call global.h
) that reads like this.
#ifndef MY_PROJECT_GLOBAL_H
#define MY_PROJECT_GLOBAL_H
#include <config.h>
/* Maybe other global definitions… */
#endif
Note that the recommended way to #include
the config.h
file is via <config.h>
not "config.h"
so it works better with VPATH
builds.
Then, all the source files in my project #include
this global.h
header as their very first #include
and don't care about config.h
. A header file should never #include
config.h
since this would lead to bad name conflicts. Actually, if you stick to this guideline, your code should also work without #include
guards in the configuration header.
Or: How to use configuration results in headers?
If your headers need to declare different things depending on the results of the configure
script, you have a number of options, none of which is perfect.
For internal headers, there is no problem. They simply rely on the macros being #define
d without #include
ing anything. This works if – as is recommended – all source files #include
(maybe indirectly as shown above) config.h
before any other header.
If the headers are to be installed publicly, this is not such a great solution. For those of your users that use Autoconf, it wouldn't be that bad, although even those would have to remember what checks to place in their configure.ac
files. For users who don't use Autoconf, it will be pretty bad. If you only have a few switches (such as Glibc's fature test macros), it is okay to ask your users to #define
them before #include
ing your headers but if you need many, this is not a real option. Not to mention that you'll expose a lot of implementation details to your users that way.
If all you need to do is branch depending on the platform you are building for, you could probe some of the pre-defined macros like __linux
or _WIN32
. There is the Boost.Predef library that aims to make these check a little more convenient by providing a higher-level abstraction. The library works with C and C++ alike but, of course, it adds an additional dependency to your project.
Finally, you could make a version of your config.h
that uses a macro prefix specific to your project. There is a contribution in the Autoconf macro archive that does exactly that for you. A minimal example could look like this.
AC_PREREQ([2.69]) AC_INIT([example-project], [1.0], [bugs@example.org]) AC_CONFIG_SRCDIR([example.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AX_PREFIX_CONFIG_H([public_config.h], [EXAMPLE_PROJECT], [config.h]) AC_PROG_CC AC_OUTPUT
Save this as configure.ac
, download ax_prefix_config_h.m4
from the Autoconf macro archive and place it in the sub-directory m4
and then run autoreconf && ./configure
. It will create the normal config.h
and in addition public_config.h
where in the latter file, all macros are prefixed with EXAMPLE_PROJECT_
. The file public_config.h
(which also has #include
guards by the way) can be installed and #include
d in your project's public header files if need be.