From 55e7bd4edb5641d5ce0c8ca7d8773d1e933d7807 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 24 Apr 2022 12:57:44 +0200 Subject: [PATCH] Document and detect issue with conditional checks --- README.md | 72 +++++++++++++++++++ .../autoconf/checks/HAVE_BIGENDIAN.h | 4 ++ .../autoconf/checks/HAVE_CLOCK_GETTIME.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_DLOPEN.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_EVENTFD.h | 4 ++ .../autoconf/checks/HAVE_EXPLICIT_BZERO.h | 4 ++ .../autoconf/checks/HAVE_EXPLICIT_MEMSET.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_FUTIMENS.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_FUTIMES.h | 4 ++ .../autoconf/checks/HAVE_GETAUXVAL.h | 4 ++ .../autoconf/checks/HAVE_GETENTROPY.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_INOTIFY.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_LINKAT.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_POLL.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_POLLTS.h | 4 ++ .../autoconf/checks/HAVE_POSIX_FALLOCATE.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_PPOLL.h | 4 ++ .../autoconf/checks/HAVE_RENAMEAT2.h | 4 ++ .../libbuild2/autoconf/checks/HAVE_STATX.h | 4 ++ .../autoconf/checks/HAVE_THREADSAFE_CLOEXEC.h | 4 ++ .../autoconf/checks/WORDS_BIGENDIAN.h | 4 ++ 21 files changed, 152 insertions(+) diff --git a/README.md b/README.md index e329457..db68301 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,45 @@ h{config}: in{config} } ``` +Note that an implementation of a check may depend on another check. As a +result, substitutions should not be conditional at the preprocessor level +(unless all the checks are part of the same condition). Nor should the +results of checks be adjusted until after the last check. For example: + +``` +#ifndef _WIN32 +# cmakedefine HAVE_EXPLICIT_BZERO // Condition substitution. +#endif + +#cmakedefine HAVE_EXPLICIT_MEMSET // Shares implementation with BZERO. + +#cmakedefine BYTE_ORDER + +#if BYTE_ORDER == LITTLE_ENDIAN +# undef BYTE_ORDER // Adjusting the result. +#endif + +#cmakedefine WORDS_BIGENDIAN // Based on BYTE_ORDER. +``` + +Below is the correct way to achieve the above semantics: + +``` +#cmakedefine HAVE_EXPLICIT_BZERO +#cmakedefine HAVE_EXPLICIT_MEMSET + +#cmakedefine BYTE_ORDER +#cmakedefine WORDS_BIGENDIAN + +#ifdef _WIN32 +# undef HAVE_EXPLICIT_BZERO +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +# undef BYTE_ORDER +#endif +``` + The built-in checks can be prefixed in order to avoid clashes with similarly named macros in other headers. This is an especially good idea if the resulting header is public. To enable this, we specify the prefix with @@ -177,6 +216,39 @@ functionality to avoid clashes across files. However, this does not help unprefixable names and, as a result, such checks should be implemented in ways that deal with duplication (for example, include guards). +The duplicate suppression is incompatible with conditional (at the +preprocessor level) checks, for example, assuming both `HAVE_EXPLICIT_*` +checks are based on `BUILD2_AUTOCONF_LIBC_VERSION`: + +``` +#ifndef _WIN32 +# undef HAVE_EXPLICIT_BZERO +#endif + +#undef HAVE_EXPLICIT_MEMSET +``` + +In this example, the `autoconf` module will omit the second copy of the +`BUILD2_AUTOCONF_LIBC_VERSION` check as part of the `HAVE_EXPLICIT_MEMSET` +substitution because it was already inserted as part of the +`HAVE_EXPLICIT_BZERO` substitution. But the first copy will not be +preprocessed on Windows. + +While there is no bulletproof way to detect such situations (because the +unconditional check could be `BUILD2_AUTOCONF_LIBC_VERSION` itself), it is a +good idea for checks that are based on other checks to verify that the base +macros are in fact defined, for example: + +``` +// HAVE_EXPLICIT_BZERO : BUILD2_AUTOCONF_LIBC_VERSION + +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + +... +``` + [module-in]: https://build2.org/build2/doc/build2-build-system-manual.xhtml#module-in [proj-config]: https://build2.org/build2/doc/build2-build-system-manual.xhtml#proj-config [checks]: https://github.com/build2/libbuild2-autoconf/tree/master/libbuild2-autoconf/libbuild2/autoconf/checks/ diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_BIGENDIAN.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_BIGENDIAN.h index 87c27b0..6a9bc82 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_BIGENDIAN.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_BIGENDIAN.h @@ -1,5 +1,9 @@ // HAVE_BIGENDIAN : BYTE_ORDER +#ifndef BYTE_ORDER +# error BYTE_ORDER appears to be conditionally included +#endif + #undef HAVE_BIGENDIAN #if BYTE_ORDER == BIG_ENDIAN diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_CLOCK_GETTIME.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_CLOCK_GETTIME.h index 9241ae1..5b732a9 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_CLOCK_GETTIME.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_CLOCK_GETTIME.h @@ -1,5 +1,9 @@ // HAVE_CLOCK_GETTIME : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_CLOCK_GETTIME /* Since Linux 2.6/glibc 2.2 (based on glibc commit history), FreeBSD 3.0, diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_DLOPEN.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_DLOPEN.h index 9635be8..d30ad23 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_DLOPEN.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_DLOPEN.h @@ -1,5 +1,9 @@ // HAVE_DLOPEN : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_DLOPEN /* Since Linux/glibc 2.0 and all versions of other supported UNIXes. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EVENTFD.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EVENTFD.h index 20a8a78..ce55df6 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EVENTFD.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EVENTFD.h @@ -1,5 +1,9 @@ // HAVE_EVENTFD : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_EVENTFD /* Since Linux/glibc 2.8, FreeBSD 13. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_BZERO.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_BZERO.h index e97eb81..dad5275 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_BZERO.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_BZERO.h @@ -1,5 +1,9 @@ // HAVE_EXPLICIT_BZERO : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_EXPLICIT_BZERO /* Since FreeBSD 11, OpenBSD 5.5, and glibc 2.25. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_MEMSET.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_MEMSET.h index cd6e1ec..a8e8fba 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_MEMSET.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_EXPLICIT_MEMSET.h @@ -1,5 +1,9 @@ // HAVE_EXPLICIT_MEMSET : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_EXPLICIT_MEMSET /* Since NetBSD 7.0.0. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMENS.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMENS.h index 71c186a..9fd3c35 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMENS.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMENS.h @@ -1,5 +1,9 @@ // HAVE_FUTIMENS : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_FUTIMENS /* Since Linux/glibc 2.6, FreeBSD 10.3, OpenBSD 5.0, NetBSD 6.0, Mac OS 10.6 diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMES.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMES.h index 278d647..b5b4579 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMES.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_FUTIMES.h @@ -1,5 +1,9 @@ // HAVE_FUTIMES : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_FUTIMES /* Since Linux/glibc 2.3, FreeBSD 3.x, OpenBSD 1.2 (but the `OpenBSD` macro diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETAUXVAL.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETAUXVAL.h index f675e63..6fe4ecb 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETAUXVAL.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETAUXVAL.h @@ -1,5 +1,9 @@ // HAVE_GETAUXVAL : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_GETAUXVAL /* Since glibc 2.16. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETENTROPY.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETENTROPY.h index 0b5598d..592c174 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETENTROPY.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_GETENTROPY.h @@ -1,5 +1,9 @@ // HAVE_GETENTROPY : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_GETENTROPY /* Since Linux/glibc 2.25, OpenBSD 5.6, FreeBSD 12, and Mac OS 12. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_INOTIFY.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_INOTIFY.h index 40cd376..5e3cb63 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_INOTIFY.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_INOTIFY.h @@ -1,5 +1,9 @@ // HAVE_INOTIFY : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_INOTIFY /* Since Linux 2.6.3/glibc 2.4. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_LINKAT.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_LINKAT.h index 32fd7a6..47e3136 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_LINKAT.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_LINKAT.h @@ -1,5 +1,9 @@ // HAVE_LINKAT : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_LINKAT /* Since Linux 2.6.16/glibc 2.4, FreeBSD 8.0, OpenBSD 5.0, NetBSD 7.0 (it was diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLL.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLL.h index 92510f1..0426e53 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLL.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLL.h @@ -1,5 +1,9 @@ // HAVE_POLL : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_POLL /* Since Linux 2.1.23/glibc (all versions; emulated using select() on older diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLLTS.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLLTS.h index d2eab95..7b0d766 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLLTS.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POLLTS.h @@ -1,5 +1,9 @@ // HAVE_POLLTS : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_POLLTS /* Since NetBSD 3.0. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POSIX_FALLOCATE.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POSIX_FALLOCATE.h index cad894a..69e6de8 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POSIX_FALLOCATE.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_POSIX_FALLOCATE.h @@ -1,5 +1,9 @@ // HAVE_POSIX_FALLOCATE : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_POSIX_FALLOCATE /* Since Linux/glibc 2.2, FreeBSD 9.0 diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_PPOLL.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_PPOLL.h index 55de0a8..40c7d3a 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_PPOLL.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_PPOLL.h @@ -1,5 +1,9 @@ // HAVE_PPOLL : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_PPOLL /* Since Linux 2.6.16/glibc 2.4, FreeBSD 11, OpenBSD 5.4. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_RENAMEAT2.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_RENAMEAT2.h index cac436e..3b5b555 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_RENAMEAT2.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_RENAMEAT2.h @@ -1,5 +1,9 @@ // HAVE_RENAMEAT2 : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_RENAMEAT2 // Since Linux 3.15/glibc 2.28. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_STATX.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_STATX.h index e148a34..438b70a 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_STATX.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_STATX.h @@ -1,5 +1,9 @@ // HAVE_STATX : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_STATX /* Since Linux 4.11/glibc 2.28. diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_THREADSAFE_CLOEXEC.h b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_THREADSAFE_CLOEXEC.h index 33b0609..5428454 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_THREADSAFE_CLOEXEC.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/HAVE_THREADSAFE_CLOEXEC.h @@ -1,5 +1,9 @@ // HAVE_THREADSAFE_CLOEXEC : BUILD2_AUTOCONF_LIBC_VERSION +#ifndef BUILD2_AUTOCONF_LIBC_VERSION +# error BUILD2_AUTOCONF_LIBC_VERSION appears to be conditionally included +#endif + #undef HAVE_THREADSAFE_CLOEXEC /* Define if file descriptor-creating functions taking a *_CLOEXEC flag are diff --git a/libbuild2-autoconf/libbuild2/autoconf/checks/WORDS_BIGENDIAN.h b/libbuild2-autoconf/libbuild2/autoconf/checks/WORDS_BIGENDIAN.h index caa21ae..c89dd01 100644 --- a/libbuild2-autoconf/libbuild2/autoconf/checks/WORDS_BIGENDIAN.h +++ b/libbuild2-autoconf/libbuild2/autoconf/checks/WORDS_BIGENDIAN.h @@ -1,5 +1,9 @@ // WORDS_BIGENDIAN : BYTE_ORDER +#ifndef BYTE_ORDER +# error BYTE_ORDER appears to be conditionally included +#endif + #undef WORDS_BIGENDIAN #if BYTE_ORDER == BIG_ENDIAN