config: Check order and endianess even when cross-compiling

This commit is contained in:
ZyX
2015-08-15 17:41:28 +03:00
parent b249529676
commit d1830e1433
2 changed files with 41 additions and 18 deletions

View File

@@ -3,6 +3,7 @@ include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CheckCSourceRuns)
include(CheckCSourceCompiles)
check_type_size("int" SIZEOF_INT)
check_type_size("long" SIZEOF_LONG)
@@ -75,31 +76,50 @@ endif()
set(SI "#include <stdint.h>\n")
set(MS "int main(int argc,char**argv)\n{\n uint64_t i=0x0102030405060708ULL;")
set(ME "}")
check_c_source_runs("
${SI}
${MS}
char *s = (char *) &i;
return (
s[0] == 0x01
&& s[1] == 0x02
&& s[2] == 0x03
&& s[3] == 0x04
&& s[4] == 0x05
&& s[5] == 0x06
&& s[6] == 0x07
&& s[7] == 0x08) ? 0 : 1;
${ME}"
ORDER_BIG_ENDIAN)
check_c_source_runs("
check_c_source_compiles("
#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
${SI}
#include <endian.h>
#ifndef be64toh
# error No be64toh macros
#endif
${MS}
uint64_t j = be64toh(i);
return (j == 0); // Must not be zero
return (j == 0); // j must not be zero
${ME}"
HAVE_BE64TOH)
HAVE_BE64TOH_MACROS)
if(NOT "${HAVE_BE64TOH_MACROS}")
check_function_exists(be64toh HAVE_BE64TOH_FUNC)
endif()
if("${HAVE_BE64TOH_MACROS}" OR "${HAVE_BE64TOH_FUNC}")
set(HAVE_BE64TOH 1)
endif()
if (NOT "${HAVE_BE64TOH}")
if (NOT "${CMAKE_CROSSCOMPILING}")
# It is safe to make ORDER_BIG_ENDIAN not defined if
# - HAVE_BE64TOH is true. In this case be64toh will be used unconditionally in
# any case and ORDER_BIG_ENDIAN will not be examined.
# - CMAKE_CROSSCOMPILING *and* HAVE_BE64TOH are both false. In this case
# be64toh function which uses cycle and arithmetic operations is used which
# will work regardless of endianess. Function is sub-optimal though.
check_c_source_runs("
${SI}
${MS}
char *s = (char *) &i;
return (
s[0] == 0x01
&& s[1] == 0x02
&& s[2] == 0x03
&& s[3] == 0x04
&& s[4] == 0x05
&& s[5] == 0x06
&& s[6] == 0x07
&& s[7] == 0x08) ? 0 : 1;
${ME}"
ORDER_BIG_ENDIAN)
endif()
endif()
# generate configuration header and update include directories
configure_file (

View File

@@ -3141,6 +3141,9 @@ static inline uint64_t be64toh(uint64_t big_endian_64_bits)
#ifdef ORDER_BIG_ENDIAN
return big_endian_64_bits;
#else
// It may appear that when !defined(ORDER_BIG_ENDIAN) actual order is big
// endian. This variant is suboptimal, but it works regardless of actual
// order.
uint8_t *buf = (uint8_t *) &big_endian_64_bits;
uint64_t ret = 0;
for (size_t i = 8; i; i--) {