on December 17, 2009 at 01:14 PM
I keep running in to issues with how folks use config.h, so I thought I'd clear up any confusion folks have. For those who haven't been following along at home, the autotools (i.e. autoconf and autoheader in this case) generate a file called config.h which contains a bunch of defines to help control the build based on what things exist or don't exist on your system. There are two main rules for this file that lots of folks get wrong:
- config.h should ALWAYS be the first thing included by EVERY non-header C/C++ file in your project.
- config.h should NEVER NEVER NEVER NEVER NEVER NEVER be installed.
For the first point, you must ensure that config.h is included first, because it sets behaviors. It must be included before any system headers because it may contain things that control the behavior of the system headers. It must be included before any local headers because it's going to define things like HAVE_SYS_STAT_H which will let you know if it's safe to include sys/stat.h (it is, by the way - it exists everywhere you care about - but that's not the point here) There is nothing, and I do mean NOTHING to be gained by including it anywhere else, in any other order, or in fact, even about putting any extra effort into thinking about where it might be cool to include config.h. The ONLY thing you will accomplish is making your software more fragile.
For the second point, it must never be installed because it unconditionally sets a bunch of defines based on the state of the machine where configure was run. That state has nothing to do with the state of the machine where your headers are installed, so the settings found in config.h are at best coincidentally correct, and at worst out-right lies. In addition, it's probably not just you using autotools for your project. autoconf and automake are, for better or for worse, pretty much the most common build system out there. So if your are shipping a config.h and your shipped headers are including it, and someone is trying to use autotools in their project which consumes your code... FAIL. Symbols will collide and all manner of pain will ensue.
*NOTE* Renaming config.h to something else does not mitigate this. The problem is the common non-prefixed name of config.h defines... like PACKAGE or VERSION.
Now, you might respond that your public headers need defines from config.h to operate properly. There are two answers to this. One is that you need to redesign your public headers, as they are unclean. (and nobody likes dirty headers) Two is that, for your project, if every non-header file includes config.h before they include anything else, then the defines will be quite happily present in scope when any of your headers are read. Be warned though - don't count on this too heavily in your public headers ... because then you'll be counting on someone out there having run the same set of autoconf checks you did. (Yes. Proper public headers are tricky)Don't forget that many OS features have defined and standard feature check macros you can test without having to do an autoconf test for the feature.
In short though - just include config.h FIRST in all of your implementation files and NEVER under ANY circumstances install it, and you'll be golden.