I am reusing some C/C++ source files part of an autotools project within a CMake project and I see many source files littered with lines like:
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for getpid()
#endif
I would understand the purpose of this construct if getpid() was optional and its call was surrounded by equivalent HAVE_UNISTD_H directives. However, without HAVE_UNISTD_H the source file does not compile, complaining that getpid() is not defined. This feels a lot more cryptic than the compiler letting me know that unistd.h was not found.
Of course, this is only an example. Other popular macros include HAVE_STDINT_H, HAVE_INTTYPES_H, etc. whose presence is mandatory to compile the source file.
Why are HAVE_* guards included at all? I feel they only bring disadvantages:
HAVE_* macros are defined.#includes mixed with #ifdefs.Most of the HAVE_xxx_h guards are remnants from an era before POSIX came along and standardized the header files. In early 90s you could easily come across a system that did have getpid(), but without a working unistd.h - the function would simply be declared in another header file, or it wouldn't be declared at all, but it would still work (as long as its return value was int-sized) due to declarations being optional in K&R and C89 C.
There were even stranger issues between the multitude of systems in use at the time. For example there were systems that shipped time.h, those that shipped sys/time.h, and those that shipped both - except that among the last category there was a subset where attempting to actually include both would result in a compilation error! Supporting a vast array of such systems, where possible without listing them all in advance, was one of the explicit design goals of Autoconf, and some of the long-irrelevant hacks are still carefully documented.
In addition to the above concerns, decoupling the header names from support for functions can come in useful when porting the code to non-POSIX systems such as windows. On such systems the posix headers might be missing or broken, and the actual function definition comes from a portability library such as gnulib.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With