On 5/18/24 4:46 AM, Bruno Haible wrote: >> I see. What is the correct solution here? > > See the idioms used by, say, arpa_inet.in.h. > >> Or something like this: >> >> #if @HAVE_ENDIAN_H@ >> # @INCLUDE_NEXT@ @NEXT_ENDIAN_H@ >> #endif > > This is part of it. But there's more details needed.
Can you check the attached patch? I think that it should work or at least be in the correct direction... On my system in a testdir with all modules I don't get the error, so it is a bit hard to test. :( I've split the configure checks into one checking for uint16_t, etc. and the other checking for macros/function definitions. The reason for this is that glibc defines macros/functions properly, so we just need the stdint.h types. I assume this might occur on other systems but that is just a guess. For other platforms the configure checks might fail because function-like macros are used. In that case we can include endian.h from the system and #undef the macros before our own definition. Also, double checking that I understand the #include_next idioms would be appreciated. Feel free to push this patch if it is okay. I don't want this module to mess with your CI jobs. Collin
From 670b8be73f4b79d4a6993dafcd12ae81721a85b6 Mon Sep 17 00:00:00 2001 From: Collin Funk <collin.fu...@gmail.com> Date: Sat, 18 May 2024 06:36:55 -0700 Subject: [PATCH] endian: Make sure system headers can be included. Reported by Bruno Haible in <https://lists.gnu.org/archive/html/bug-gnulib/2024-05/msg00290.html>. * lib/endian.in.h (be16toh, be32toh, be64toh, htobe16, htobe32, htobe64) (le16toh, le32toh, le64toh, htole16, htole32, htole64): Don't define functions if the system has working versions. * m4/endian_h.m4 (gl_ENDIAN_H): Separate checks for stdint types and proper macro/function definitions. * modules/endian (Depends-on): Add include_next. Update module dependency conditions. (Makefile.am): Perform sed replacements on the header substitute. --- ChangeLog | 14 ++++++++++ lib/endian.in.h | 46 +++++++++++++++++++++++++++++--- m4/endian_h.m4 | 70 +++++++++++++++++++++++++++++++++++-------------- modules/endian | 15 ++++++++--- 4 files changed, 120 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 29adf56ab7..90953430be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2024-05-18 Collin Funk <collin.fu...@gmail.com> + + endian: Make sure system headers can be included. + Reported by Bruno Haible in + <https://lists.gnu.org/archive/html/bug-gnulib/2024-05/msg00290.html>. + * lib/endian.in.h (be16toh, be32toh, be64toh, htobe16, htobe32, htobe64) + (le16toh, le32toh, le64toh, htole16, htole32, htole64): Don't define + functions if the system has working versions. + * m4/endian_h.m4 (gl_ENDIAN_H): Separate checks for stdint types and + proper macro/function definitions. + * modules/endian (Depends-on): Add include_next. Update module + dependency conditions. + (Makefile.am): Perform sed replacements on the header substitute. + 2024-05-18 Bruno Haible <br...@clisp.org> endian tests: Verify that it can be used from C++. diff --git a/lib/endian.in.h b/lib/endian.in.h index 5d755fd7cf..65473201ea 100644 --- a/lib/endian.in.h +++ b/lib/endian.in.h @@ -17,8 +17,30 @@ /* Written by Collin Funk. */ -#ifndef _GL_ENDIAN_H -#define _GL_ENDIAN_H 1 +#ifndef _@GUARD_PREFIX@_ENDIAN_H + +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ + +#if @HAVE_ENDIAN_H@ + +/* The include_next requires a split double-inclusion guard. */ +# @INCLUDE_NEXT@ @NEXT_ENDIAN_H@ + +#endif + + +/* glibc defines all macros and functions but is missing types from + stdint.h. */ +#if @ENDIAN_H_JUST_MISSING_STDINT@ +# include <stdint.h> +#else + +/* Others platforms. */ +#ifndef _@GUARD_PREFIX@_ENDIAN_H +#define _@GUARD_PREFIX@_ENDIAN_H 1 /* This file uses _GL_INLINE, WORDS_BIGENDIAN. */ #if !_GL_CONFIG_H_INCLUDED @@ -47,6 +69,22 @@ _GL_INLINE_HEADER_BEGIN # define BYTE_ORDER LITTLE_ENDIAN #endif +/* Make sure function-like macros get undefined. */ +#if @HAVE_ENDIAN_H@ +# undef be16toh +# undef be32toh +# undef be64toh +# undef htobe16 +# undef htobe32 +# undef htobe64 +# undef le16toh +# undef le32toh +# undef le64toh +# undef htole16 +# undef htole32 +# undef htole64 +#endif + #ifdef __cplusplus extern "C" { #endif @@ -193,4 +231,6 @@ htole64 (uint64_t x) _GL_INLINE_HEADER_END -#endif /* _GL_ENDIAN_H */ +#endif /* _@GUARD_PREFIX@_ENDIAN_H */ +#endif /* _@GUARD_PREFIX@_ENDIAN_H */ +#endif /* @ENDIAN_H_JUST_MISSING_STDINT@ */ diff --git a/m4/endian_h.m4 b/m4/endian_h.m4 index ec0d111ae3..29dab603e3 100644 --- a/m4/endian_h.m4 +++ b/m4/endian_h.m4 @@ -1,5 +1,5 @@ # endian_h.m4 -# serial 1 +# serial 2 dnl Copyright 2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,8 +12,25 @@ AC_DEFUN_ONCE([gl_ENDIAN_H] AC_REQUIRE([gl_BIGENDIAN]) AC_CHECK_HEADERS_ONCE([endian.h]) + gl_CHECK_NEXT_HEADERS([endian.h]) if test $ac_cv_header_endian_h = yes; then - AC_CACHE_CHECK([if endian.h conforms to POSIX], + HAVE_ENDIAN_H=1 + dnl Check if endian.h defines uint16_t, uint32_t, and uint64_t. + AC_CACHE_CHECK([if endian.h defines stdint types], + [gl_cv_header_endian_h_stdint_types], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <endian.h> + ]], + [[uint16_t t1 = 0; + uint32_t t2 = 0; + uint64_t t3 = 0; + return !(t1 + t2 + t3); + ]])], + [gl_cv_header_endian_h_stdint_types=yes], + [gl_cv_header_endian_h_stdint_types=no]) + ]) + AC_CACHE_CHECK([if endian.h defines functions and macros], [gl_cv_header_working_endian_h], [gl_cv_header_working_endian_h=no AC_COMPILE_IFELSE( @@ -29,29 +46,25 @@ AC_DEFUN_ONCE([gl_ENDIAN_H] # error "Byte order not defined." #endif -/* Check for uint16_t, uint32_t, uint64_t along with - byte order conversion functions that accept floating-point - arguments. */ - /* Big endian to host. */ -uint16_t value16_1 = be16toh (0.0); -uint32_t value32_1 = be32toh (0.0); -uint64_t value64_1 = be64toh (0.0); +int value16_1 = be16toh (0.0); +int value32_1 = be32toh (0.0); +int value64_1 = be64toh (0.0); /* Host to big endian. */ -uint16_t value16_2 = htobe16 (0.0); -uint32_t value32_2 = htobe32 (0.0); -uint64_t value64_2 = htobe64 (0.0); +int value16_2 = htobe16 (0.0); +int value32_2 = htobe32 (0.0); +int value64_2 = htobe64 (0.0); /* Little endian to host. */ -uint16_t value16_3 = le16toh (0.0); -uint32_t value32_3 = le32toh (0.0); -uint64_t value64_3 = le64toh (0.0); +int value16_3 = le16toh (0.0); +int value32_3 = le32toh (0.0); +int value64_3 = le64toh (0.0); /* Host to little endian. */ -uint16_t value16_4 = htole16 (0.0); -uint32_t value32_4 = htole32 (0.0); -uint64_t value64_4 = htole64 (0.0); +int value16_4 = htole16 (0.0); +int value32_4 = htole32 (0.0); +int value64_4 = htole64 (0.0); /* Make sure the variables get used. */ return !(value16_1 + value32_1 + value64_1 @@ -62,10 +75,29 @@ AC_DEFUN_ONCE([gl_ENDIAN_H] [gl_cv_header_working_endian_h=yes], [gl_cv_header_working_endian_h=no]) ]) + else + HAVE_ENDIAN_H=0 fi - if test $gl_cv_header_working_endian_h = yes; then + + dnl Check if endian.h should be generated. + if test $gl_cv_header_endian_h_stdint_types = yes \ + && test $gl_cv_header_working_endian_h = yes; then GL_GENERATE_ENDIAN_H=false else GL_GENERATE_ENDIAN_H=true fi + + dnl Check if endian.h works but is missing types from stdint.h. + if test $GL_GENERATE_ENDIAN_H; then + if test $gl_cv_header_working_endian_h = yes; then + ENDIAN_H_JUST_MISSING_STDINT=1 + else + ENDIAN_H_JUST_MISSING_STDINT=0 + fi + else + ENDIAN_H_JUST_MISSING_STDINT=0 + fi + + AC_SUBST([HAVE_ENDIAN_H]) + AC_SUBST([ENDIAN_H_JUST_MISSING_STDINT]) ]) diff --git a/modules/endian b/modules/endian index 9da2d2d19c..203163efe1 100644 --- a/modules/endian +++ b/modules/endian @@ -8,8 +8,9 @@ m4/endian_h.m4 Depends-on: gen-header -extern-inline [$GL_GENERATE_ENDIAN_H] -byteswap [$GL_GENERATE_ENDIAN_H] +include_next +extern-inline [$GL_GENERATE_ENDIAN_H && test $ENDIAN_H_JUST_MISSING_STDINT = 0] +byteswap [$GL_GENERATE_ENDIAN_H && test $ENDIAN_H_JUST_MISSING_STDINT = 0] stdint [$GL_GENERATE_ENDIAN_H] configure.ac: @@ -25,7 +26,15 @@ BUILT_SOURCES += $(ENDIAN_H) if GL_GENERATE_ENDIAN_H endian.h: endian.in.h $(top_builddir)/config.status @NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%' - $(gl_V_at)$(SED_HEADER_TO_AT_t) $(srcdir)/endian.in.h + $(gl_V_at)$(SED_HEADER_STDOUT) \ + -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \ + -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ + -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ + -e 's|@''HAVE_ENDIAN_H''@|$(HAVE_ENDIAN_H)|g' \ + -e 's|@''NEXT_ENDIAN_H''@|$(NEXT_ENDIAN_H)|g' \ + -e 's|@''ENDIAN_H_JUST_MISSING_STDINT''@|$(ENDIAN_H_JUST_MISSING_STDINT)|g' \ + $(srcdir)/endian.in.h > $@-t $(AM_V_at)mv $@-t $@ lib_SOURCES += endian.c else -- 2.45.1