From 555fd59f09202f4f744bf7f22fa3be2e351fb8d5 Mon Sep 17 00:00:00 2001
From: Sergey Kosukhin <sergey.kosukhin@mpimet.mpg.de>
Date: Fri, 14 Feb 2025 08:59:24 +0000
Subject: [PATCH] Detect the endianness with CMake
 (icon-libraries/libfortran-support!111)

## What is the bug

The endianness detection in `src/util_hash.c` produces a false result on macOS with GCC 13 or later. For whatever reason, [`#include <sys/param.h>`](https://gitlab.dkrz.de/icon-libraries/libfortran-support/-/blob/316d3dc6edb6ef0f4f1b9adaf9f3cb27a7bb831a/src/util_hash.c#L49) does not define the `__DARWIN_BYTE_ORDER` and `__DARWIN_LITTLE_ENDIAN` macros when [`#define _POSIX_C_SOURCE 200112L`](https://gitlab.dkrz.de/icon-libraries/libfortran-support/-/blob/316d3dc6edb6ef0f4f1b9adaf9f3cb27a7bb831a/src/util_hash.c#L45). And that leads to the wrong values of the `HASH_LITTLE_ENDIAN` and `HASH_BIG_ENDIAN` macros. See also https://gitlab.dkrz.de/icon/icon-mpim/-/merge_requests/684#note_300951.

## How do you fix it

The endianness detection is delegated to CMake.

Approved-by: Yen-Chen Chen <yen-chen.chen@tum.de>
Merged-by: Yen-Chen Chen <yen-chen.chen@tum.de>
Changelog: bugfix
---
 src/CMakeLists.txt |  3 +++
 src/config.h.in    |  2 ++
 src/util_hash.c    | 52 +++++-----------------------------------------
 src/util_hash.h    |  1 +
 4 files changed, 11 insertions(+), 47 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3162cb3..aecab81 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,6 +15,9 @@ check_include_files("link.h" HAVE_LINK_H)
 check_include_files("unwind.h" HAVE_UNWIND_H)
 check_include_files("sys/resource.h" HAVE_GETRUSAGE)
 
+include(TestBigEndian)
+test_big_endian(HAVE_BIG_ENDIAN)
+
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
                ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 
diff --git a/src/config.h.in b/src/config.h.in
index 07b9d54..0334621 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -16,3 +16,5 @@
 #cmakedefine HAVE_UNWIND_H @HAVE_UNWIND_H@
 
 #cmakedefine HAVE_GETRUSAGE @HAVE_GETRUSAGE@
+
+#cmakedefine HAVE_BIG_ENDIAN @HAVE_BIG_ENDIAN@
diff --git a/src/util_hash.c b/src/util_hash.c
index a70cbb0..f68b3f2 100644
--- a/src/util_hash.c
+++ b/src/util_hash.c
@@ -42,63 +42,21 @@
  * -------------------------------------------------------------------------------
  */
 
-#define _POSIX_C_SOURCE 200112L
+#include "config.h"
 
-#include <stdint.h> /* defines uint32_t etc */
-
-#include <sys/param.h> /* attempt to define endianness */
-
-#if (defined(__APPLE__) && defined(__MACH__))
-
-#if (defined(__DARWIN_BYTE_ORDER) \
-     && (__DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN))
-#define HASH_LITTLE_ENDIAN 1
-#define HASH_BIG_ENDIAN 0
-#else
-#define HASH_LITTLE_ENDIAN 0
-#define HASH_BIG_ENDIAN 1
-#endif
+#include "util_hash.h"
 
-#elif defined(_AIX)
+#include <stddef.h>
+#include <stdint.h>
 
-#if (defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN))
-#define HASH_LITTLE_ENDIAN 1
-#define HASH_BIG_ENDIAN 0
-#else
+#ifdef HAVE_BIG_ENDIAN
 #define HASH_LITTLE_ENDIAN 0
 #define HASH_BIG_ENDIAN 1
-#endif
-
-#elif defined(__linux)
-
-#include <endian.h>
-
-#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN))
-#define HASH_LITTLE_ENDIAN 1
-#define HASH_BIG_ENDIAN 0
 #else
-#define HASH_LITTLE_ENDIAN 0
-#define HASH_BIG_ENDIAN 1
-#endif
-
-#elif defined(_SX)
-
-#define HASH_LITTLE_ENDIAN 0
-#define HASH_BIG_ENDIAN 1
-
-#elif defined(__NEC__)
-
 #define HASH_LITTLE_ENDIAN 1
 #define HASH_BIG_ENDIAN 0
-
-#else
-
-#error "Couldn't determine endianness."
-
 #endif
 
-#include "util_hash.h"
-
 #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
 
 /*
diff --git a/src/util_hash.h b/src/util_hash.h
index 154c930..9499d60 100644
--- a/src/util_hash.h
+++ b/src/util_hash.h
@@ -12,6 +12,7 @@
 #ifndef UTIL_HASH_H
 #define UTIL_HASH_H
 
+#include <stddef.h>
 #include <stdint.h>
 
 #ifdef __cplusplus
-- 
GitLab