config.hpp's endian test silently falls back to little-endian
In https://github.com/PowerDNS/pdns/issues/16091 I discovered that config.hpp has an endian check using __BYTE_ORDER, but at least on GCC 15 / GNU libc platforms it doesn't work. Without including <endian.h> the macros are not defined, and config.hpp silently falls back to little endian.
Could an #include <endian.h> be added to config.hpp?
Thanks, Chris
As pointed out by @omoerbeek in https://github.com/PowerDNS/pdns/issues/16091#issuecomment-3263784377 and https://github.com/PowerDNS/pdns/issues/16091#issuecomment-3263788379 the standards-compliant thing would be:
- include endian.h
- use
BYTE_ORDER,LITTLE_ENDIAN,BIG_ENDIAN(no leading or trailing underscores)
Thanks for considering!
Unfortunately it is not that easy. endian.h is not part of the C++ standard, it isn't available on all platforms. And protozero is header-only, so there is no build-step we control where we could figure out on what platform we are. So we have to figure out what endianness we have in our own code in C++ only without resorting to any headers. If you have some code for config.hpp that doesn't need endian.h and does the right thing for your platform I'd consider merging a PR.
A workaround for you would be to #include <protozero/config.hpp> and after that set PROTOZERO_BYTE_ORDER in any way that works for you and then include the other protozero includes.
If and when we switch to C++20 which is probably a long way off, we can use the std::endian enum class which will solve this properly.
Right. While many systems have endian.h, not all. macOS is an example.
It might be that testing for the __NAME__ (with __ on both ends) variants of the macros is more robust. At least both g++ and clang++ defines those in all systems I tested without the need for includes. I do not have access to other compilers.
@joto how about using a __has_include check to detect endian.h?
__has_include was introduced in C++17, we are still at C++14.