Skip to content

Commit 7711edd

Browse files
authored
Merge pull request #154 from mapbox/kk/endian-detection
Harden byte order detection
2 parents af2f6e2 + 7c5d19b commit 7711edd

2 files changed

Lines changed: 73 additions & 7 deletions

File tree

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,41 @@ jobs:
112112
- uses: ./.github/actions/build
113113
- uses: ./.github/actions/ctest
114114

115+
big-endian:
116+
runs-on: ubuntu-24.04
117+
timeout-minutes: 45
118+
steps:
119+
- uses: actions/checkout@v7
120+
- name: Set up QEMU
121+
uses: docker/setup-qemu-action@v3
122+
with:
123+
platforms: s390x
124+
- name: Build and test on s390x (big-endian)
125+
run: |
126+
docker run --rm --platform linux/s390x \
127+
-v "${{ github.workspace }}:/src" \
128+
-w /src \
129+
-e DEBIAN_FRONTEND=noninteractive \
130+
debian:bookworm \
131+
bash -exc '
132+
apt-get update -qq
133+
apt-get install -y \
134+
cmake \
135+
g++ \
136+
libprotobuf-dev \
137+
make \
138+
protobuf-compiler \
139+
python3-minimal
140+
python3 -c "import sys; assert sys.byteorder == \"big\""
141+
mkdir -p build
142+
cd build
143+
cmake -LA .. \
144+
-DCMAKE_BUILD_TYPE=Debug \
145+
-DCMAKE_CXX_STANDARD=14
146+
cmake --build . --parallel 2
147+
ctest --output-on-failure --parallel 2
148+
'
149+
115150
ubuntu-latest:
116151
runs-on: ubuntu-24.04
117152
timeout-minutes: 30

include/protozero/config.hpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,48 @@ documentation.
2222
#define PROTOZERO_BIG_ENDIAN 4321
2323

2424
// Find out which byte order the machine has.
25-
#if defined(__BYTE_ORDER)
26-
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
25+
26+
// __BYTE_ORDER__ is set by GCC and Clang.
27+
#if !defined(PROTOZERO_BYTE_ORDER) && defined(__BYTE_ORDER__)
28+
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2729
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
28-
# endif
29-
# if (__BYTE_ORDER == __BIG_ENDIAN)
30+
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
3031
# define PROTOZERO_BYTE_ORDER PROTOZERO_BIG_ENDIAN
3132
# endif
32-
#else
33-
// This probably isn't a very good default, but might do until we figure
34-
// out something better.
33+
#endif // defined(__BYTE_ORDER__)
34+
35+
// On Linux, we can use endian.h.
36+
#if !defined(PROTOZERO_BYTE_ORDER) && defined(__linux__)
37+
# include <endian.h>
38+
# if defined(__BYTE_ORDER)
39+
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
40+
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
41+
# elif (__BYTE_ORDER == __BIG_ENDIAN)
42+
# define PROTOZERO_BYTE_ORDER PROTOZERO_BIG_ENDIAN
43+
# endif
44+
# endif
45+
#endif // !defined(PROTOZERO_BYTE_ORDER) && defined(__linux__)
46+
47+
// On BSD, we can use <sys/endian.h>
48+
#if !defined(PROTOZERO_BYTE_ORDER) && \
49+
(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
50+
# include <sys/endian.h>
51+
# if defined(BYTE_ORDER)
52+
# if (BYTE_ORDER == LITTLE_ENDIAN)
53+
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
54+
# elif (BYTE_ORDER == BIG_ENDIAN)
55+
# define PROTOZERO_BYTE_ORDER PROTOZERO_BIG_ENDIAN
56+
# endif
57+
# endif
58+
#endif
59+
60+
// On Windows, we assume little endian.
61+
#if !defined(PROTOZERO_BYTE_ORDER) && defined(_MSC_VER)
3562
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
63+
#endif // !defined(PROTOZERO_BYTE_ORDER) && defined(_MSC_VER)
64+
65+
#if !defined(PROTOZERO_BYTE_ORDER)
66+
# error "Could not determine byte order; define PROTOZERO_BYTE_ORDER"
3667
#endif
3768

3869
// Check whether __builtin_bswap is available

0 commit comments

Comments
 (0)