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.#include
s mixed with #ifdef
s.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