From a9fe2d1ea1c3b5d03ae85729cf5eb895f7fc33a4 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:03:50 -0700 Subject: [PATCH 1/9] fix: render the README as the long description on PyPI The bitproto package had no `readme`, so the PyPI project page showed no description. setuptools rejects a path outside the project dir (`../README.md`), so symlink compiler/README.md -> ../README.md and set `readme = "README.md"`; the README body is embedded into the package METADATA (text/markdown) at build time. Also make the data-encoding image an absolute raw.githubusercontent URL so it renders on PyPI (relative paths break there) while still working on GitHub. Co-Authored-By: Claude Opus 4.8 --- README.md | 2 +- compiler/README.md | 1 + compiler/pyproject.toml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 120000 compiler/README.md diff --git a/README.md b/README.md index ee31187..105f895 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ of 4 bytes after encoding. This image shows the layout of data fields in the encoded bytes buffer: -![](docs/_static/images/data-encoding-sample.png) +![](https://raw.githubusercontent.com/hit9/bitproto/master/docs/_static/images/data-encoding-sample.png) ## Code Example diff --git a/compiler/README.md b/compiler/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/compiler/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/compiler/pyproject.toml b/compiler/pyproject.toml index 2a50fd0..5925e2d 100644 --- a/compiler/pyproject.toml +++ b/compiler/pyproject.toml @@ -6,6 +6,7 @@ build-backend = "setuptools.build_meta" name = "bitproto" version = "1.3.0" description = "bit level data interchange format." +readme = "README.md" authors = [ {name = "Chao Wang", email = "hit9@icloud.com"}, ] From 0092c1158ea73a3ad86910a09d4177d9babdc649 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:05:40 -0700 Subject: [PATCH 2/9] fix: extend BP_BIG_ENDIAN auto-detection to TI ARM CGT in the C library PR #84 added __BIG_ENDIAN__ detection to the optimization-mode generated code, but missed the same macro in the standard-mode C library (lib/c/bitproto.c), which only recognised GCC/Clang's __BYTE_ORDER__. So on TI ARM CGT big-endian targets (--be32, e.g. TMS570) non-optimization mode still fell through to the little-endian path, producing incorrect encode/decode results for multi-byte fields. Mirror the codegen detection here so both modes behave consistently: #if !defined(BP_BIG_ENDIAN) && ( (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__)) Co-Authored-By: Claude Opus 4.8 --- lib/c/bitproto.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/c/bitproto.c b/lib/c/bitproto.c index b92d01f..1ffbde5 100644 --- a/lib/c/bitproto.c +++ b/lib/c/bitproto.c @@ -8,8 +8,11 @@ // big-endian host the in-memory byte order of an integer is reversed relative // to the wire, so the byte-copy fast paths below need an endian-neutral // fallback. Users may force this by predefining BP_BIG_ENDIAN. -#if !defined(BP_BIG_ENDIAN) && defined(__BYTE_ORDER__) && \ - (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +// __BYTE_ORDER__ / __ORDER_BIG_ENDIAN__ covers GCC/Clang. +// __BIG_ENDIAN__ covers TI ARM CGT (--be32) and some other toolchains. +#if !defined(BP_BIG_ENDIAN) && ( \ + (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__BIG_ENDIAN__)) #define BP_BIG_ENDIAN 1 #endif From 48d168ce259898e0fd2d3e5034d45359fa05ed3a Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:06:13 -0700 Subject: [PATCH 3/9] release: 1.3.1 - TI ARM CGT big-endian auto-detection fix (codegen PR #84 + C library). - Render the README as the PyPI long description. Co-Authored-By: Claude Opus 4.8 --- changes.rst | 14 ++++++++++++++ compiler/bitproto/__init__.py | 2 +- compiler/pyproject.toml | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/changes.rst b/changes.rst index 0294844..62678ff 100644 --- a/changes.rst +++ b/changes.rst @@ -1,5 +1,19 @@ .. currentmodule:: bitproto +Version 1.3.1 +------------- + +.. _version-1.3.1: + +- Bugfix: Extend ``BP_BIG_ENDIAN`` auto-detection to recognise ``__BIG_ENDIAN__`` + in addition to ``__BYTE_ORDER__``, covering the TI ARM CGT compiler (``--be32`` + on big-endian targets such as the TMS570). This applies to both the + optimization-mode generated code and the standard-mode C library; previously + these targets fell through to the little-endian path and produced incorrect + results for multi-byte fields. PR #84. +- Packaging: Show the project README as the long description on the PyPI project + page for the ``bitproto`` package. + Version 1.3.0 ------------- diff --git a/compiler/bitproto/__init__.py b/compiler/bitproto/__init__.py index b6b61e5..581b4fb 100644 --- a/compiler/bitproto/__init__.py +++ b/compiler/bitproto/__init__.py @@ -8,5 +8,5 @@ """ -__version__ = "1.3.0" +__version__ = "1.3.1" __description__ = "bit level data interchange format." diff --git a/compiler/pyproject.toml b/compiler/pyproject.toml index 5925e2d..a2187a7 100644 --- a/compiler/pyproject.toml +++ b/compiler/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "bitproto" -version = "1.3.0" +version = "1.3.1" description = "bit level data interchange format." readme = "README.md" authors = [ From 242997cfe9252891e0fee7c46cdf8754627a0ee7 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:18:54 -0700 Subject: [PATCH 4/9] feat: also auto-detect IAR big-endian (__LITTLE_ENDIAN__ == 0) Broaden BP_BIG_ENDIAN auto-detection to cover IAR, which always defines __LITTLE_ENDIAN__ (1 for little, 0 for big), in addition to GCC/Clang (__BYTE_ORDER__) and TI ARM CGT (__BIG_ENDIAN__). The check uses "== 0" rather than "defined()" so GCC/Clang (which define __LITTLE_ENDIAN__ to 1 on little-endian) are not falsely detected as big-endian. Applied to both the standard-mode C library (lib/c/bitproto.c) and the optimization-mode codegen (renderer_c.py); regenerated the opt-mode examples. Documented the full detection set (GCC/Clang, TI CGT, IAR) in docs/endianness.rst, updated the 1.3.1 changelog entry, and synced the zh translation catalogs. Co-Authored-By: Claude Opus 4.8 --- changes.rst | 12 +- .../bitproto/renderer/impls/c/renderer_c.py | 4 +- docs/endianness.rst | 15 ++- docs/locales/zh/LC_MESSAGES/changelog.po | 117 +++++++++++------- docs/locales/zh/LC_MESSAGES/endianness.po | 86 +++++++------ example/C-optimization-mode/example_bp.c | 6 +- example/CPP-optimization-mode/example_bp.c | 6 +- lib/c/bitproto.c | 6 +- 8 files changed, 149 insertions(+), 103 deletions(-) diff --git a/changes.rst b/changes.rst index 62678ff..cf7e5d7 100644 --- a/changes.rst +++ b/changes.rst @@ -5,12 +5,12 @@ Version 1.3.1 .. _version-1.3.1: -- Bugfix: Extend ``BP_BIG_ENDIAN`` auto-detection to recognise ``__BIG_ENDIAN__`` - in addition to ``__BYTE_ORDER__``, covering the TI ARM CGT compiler (``--be32`` - on big-endian targets such as the TMS570). This applies to both the - optimization-mode generated code and the standard-mode C library; previously - these targets fell through to the little-endian path and produced incorrect - results for multi-byte fields. PR #84. +- Bugfix: Broaden ``BP_BIG_ENDIAN`` auto-detection beyond GCC/Clang's + ``__BYTE_ORDER__`` to also cover the TI ARM CGT (``__BIG_ENDIAN__``, e.g. + ``--be32`` on the TMS570) and IAR (``__LITTLE_ENDIAN__ == 0``) compilers, in + both the optimization-mode generated code and the standard-mode C library. + Previously these big-endian targets fell through to the little-endian path and + produced incorrect results for multi-byte fields. PR #84. - Packaging: Show the project README as the long description on the PyPI project page for the ``bitproto`` package. diff --git a/compiler/bitproto/renderer/impls/c/renderer_c.py b/compiler/bitproto/renderer/impls/c/renderer_c.py index 9ef2f9a..797e452 100644 --- a/compiler/bitproto/renderer/impls/c/renderer_c.py +++ b/compiler/bitproto/renderer/impls/c/renderer_c.py @@ -413,11 +413,13 @@ def render(self) -> None: # the user defining BP_BIG_ENDIAN; still overridable via -D. # __BYTE_ORDER__ / __ORDER_BIG_ENDIAN__ covers GCC/Clang. # __BIG_ENDIAN__ covers TI ARM CGT (--be32) and some other toolchains. + # __LITTLE_ENDIAN__ == 0 covers IAR (which always defines it). self.push("#if !defined(BP_BIG_ENDIAN) && (\\") self.push( " (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \\" ) - self.push(" defined(__BIG_ENDIAN__))") + self.push(" defined(__BIG_ENDIAN__) || \\") + self.push(" (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0)))") self.push("#define BP_BIG_ENDIAN 1") self.push("#endif") # is only needed for memset in the big-endian path. diff --git a/docs/endianness.rst b/docs/endianness.rst index b35bea8..cca3d35 100644 --- a/docs/endianness.rst +++ b/docs/endianness.rst @@ -47,10 +47,11 @@ about C. C standard mode --------------- -The C library (``lib/c/bitproto.c``) detects a big-endian host automatically via -``__BYTE_ORDER__`` and selects an endian-neutral code path. You may also force it -by defining ``BP_BIG_ENDIAN`` when compiling the library, for toolchains that do -not define ``__BYTE_ORDER__``: +The C library (``lib/c/bitproto.c``) detects a big-endian host automatically +(via ``__BYTE_ORDER__`` for GCC/Clang, ``__BIG_ENDIAN__`` for the TI ARM CGT +compiler, and ``__LITTLE_ENDIAN__ == 0`` for IAR) and selects an endian-neutral +code path. You may also force it by defining ``BP_BIG_ENDIAN`` when compiling +the library, for toolchains that expose none of these macros: .. sourcecode:: bash @@ -77,8 +78,10 @@ emits two equivalent code paths guarded by a preprocessor macro: // portable bit-shift path (big-endian hosts) #endif -A big-endian host is auto-detected via ``__BYTE_ORDER__``; you may also force the -big-endian path by defining ``BP_BIG_ENDIAN`` when compiling the generated code. +A big-endian host is auto-detected (via ``__BYTE_ORDER__`` for GCC/Clang, +``__BIG_ENDIAN__`` for the TI ARM CGT compiler, and ``__LITTLE_ENDIAN__ == 0`` +for IAR); you may also force the big-endian path by defining ``BP_BIG_ENDIAN`` +when compiling the generated code. The little-endian path is identical to earlier bitproto releases, so there is no performance change on little-endian targets — only the generated source is a little larger. diff --git a/docs/locales/zh/LC_MESSAGES/changelog.po b/docs/locales/zh/LC_MESSAGES/changelog.po index 6990af8..b9d3dfc 100644 --- a/docs/locales/zh/LC_MESSAGES/changelog.po +++ b/docs/locales/zh/LC_MESSAGES/changelog.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: bitproto 0.4.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-06-19 01:28-0700\n" +"POT-Creation-Date: 2026-06-19 06:16-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,16 +17,38 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.18.0\n" -#: ../../changelog.rst:2 76d5d3603c404178ae5b7c007ad11007 +#: ../../changelog.rst:2 cd8c857bf57e4272af61da204650e3d8 msgid "Changelog" msgstr "版本历史" -#: ../../../changes.rst:4 21ceda6cb0ef42a98dcbc98ccfb9241d -#, fuzzy +#: ../../../changes.rst:4 46489425970d43d0a350ee1f11c1b635 +msgid "Version 1.3.1" +msgstr "Version 1.3.1" + +#: ../../../changes.rst:8 3f93ccdf7ae840e5bb2142eb56985f65 +msgid "" +"Bugfix: Broaden ``BP_BIG_ENDIAN`` auto-detection beyond GCC/Clang's " +"``__BYTE_ORDER__`` to also cover the TI ARM CGT (``__BIG_ENDIAN__``, e.g. " +"``--be32`` on the TMS570) and IAR (``__LITTLE_ENDIAN__ == 0``) compilers, in" +" both the optimization-mode generated code and the standard-mode C library. " +"Previously these big-endian targets fell through to the little-endian path " +"and produced incorrect results for multi-byte fields. PR #84." +msgstr "" +"修复:将 ``BP_BIG_ENDIAN`` 的自动检测从 GCC/Clang 的 ``__BYTE_ORDER__`` 扩展到同时覆盖 TI ARM " +"CGT(``__BIG_ENDIAN__``,例如 TMS570 的 ``--be32``)和 IAR(``__LITTLE_ENDIAN__ == " +"0``)编译器,优化模式生成的代码和标准模式 C 运行库均已覆盖。此前这些大端序目标会退化到小端序路径,导致多字节字段编解码结果错误。PR #84。" + +#: ../../../changes.rst:14 122facc12bdc458b988f2a35b596b187 +msgid "" +"Packaging: Show the project README as the long description on the PyPI " +"project page for the ``bitproto`` package." +msgstr "打包:在 ``bitproto`` 包的 PyPI 项目页面上以 README 作为长描述展示。" + +#: ../../../changes.rst:18 c7b8df781e2e46d4b88e2f8b4fca025f msgid "Version 1.3.0" -msgstr "Version 1.1.2" +msgstr "Version 1.3.0" -#: ../../../changes.rst:8 67b139acd1c14750b76eb78d59628835 +#: ../../../changes.rst:22 3a40146dd1d54c6aac3aeef4a33b8502 msgid "" "Feature: Big-endian host support. bitproto's wire format is little-endian on" " every platform; the C library (standard mode) and the C optimization-mode " @@ -36,7 +58,7 @@ msgstr "" "新特性:支持大端序主机。bitproto 的编码格式在所有平台上都是小端序;现在 C 运行库(标准模式)以及 C " "优化模式生成的代码在为大端序主机编译时也能产生正确的输出。Python 和 Go 本来就与字节序无关,不受影响。" -#: ../../../changes.rst:12 9eff75eba59548dda5b36bd7771b0973 +#: ../../../changes.rst:26 8e67f040e0cc4ab081366f8e235235f5 msgid "" "Feature: New compiler option ``--endian`` (``both`` | ``little`` | ``big``) " "controlling the host byte order targeted by optimization-mode C/C++ code. " @@ -51,165 +73,174 @@ msgstr "" "区分并自动检测主机(可通过定义 ``BP_BIG_ENDIAN`` 覆盖);``little`` " "只保留原有的、更小更快的字节指针代码(不支持大端序);``big`` 只生成可移植的那份路径。" -#: ../../../changes.rst:18 abc52528f16c4b7c81153ab7c2240866 +#: ../../../changes.rst:32 d4ffa215a28c423785e31ebe89b9e488 msgid "" "The little-endian generated code is unchanged from previous releases, so " "there is no performance regression on the common little-endian target." msgstr "小端序下生成的代码与之前的版本完全相同,因此在常见的小端序目标上没有任何性能回退。" -#: ../../../changes.rst:22 22529ec400cf407abacf99ac626d435b +#: ../../../changes.rst:36 6ddbbbf6da50462a83c270387c8eda50 #, fuzzy msgid "Version 1.2.2" msgstr "Version 1.1.2" -#: ../../../changes.rst:26 ../../../changes.rst:35 -#: 95eba896850f414e89ebb84b70d40c3c e25d49c311624576abd66476d2d553d6 +#: ../../../changes.rst:40 ../../../changes.rst:49 +#: 3512db0d5ec34780a1e398ecad71d500 82cf5379274c437299ae1542f4d0f54e msgid "Warning: May break some existing projects's generated names:" msgstr "" -#: ../../../changes.rst:28 fe2017ebb9f447f8bddfeaeb8e987c0a +#: ../../../changes.rst:42 789b55dc62af47d19e748c7a8c8ce939 msgid "Improve `snake_case` function. #74, #75" msgstr "" -#: ../../../changes.rst:31 ba8f42bbecf644b29baad003f4b766df +#: ../../../changes.rst:45 7df8a2bb11024bdea47c49cdb92876de #, fuzzy msgid "Version 1.2.1" msgstr "Version 1.1.2" -#: ../../../changes.rst:37 b0189e46434948b8b61eed17372426b6 +#: ../../../changes.rst:51 68673a5e52694713b8e25dcc5d5f0c8f msgid "Bugfix: `pascal_case` formatter. ISSUE #68, PR #69." msgstr "" -#: ../../../changes.rst:38 5ecfae5bd6fb4920b9c61479c9b71be6 +#: ../../../changes.rst:52 70fccc4f50d6491eac97106714a8c06f msgid "" "Bugfix: Fixed naming style of generated code such as IntegerConstant (style " "lookup supports inheritance). ISSUE #70 PR #70" msgstr "" -#: ../../../changes.rst:42 600da5f679ad4b60907b5a12d9dc661a +#: ../../../changes.rst:56 058d39fcf7d04536837d905972e1cdd0 #, fuzzy msgid "Version 1.2.0" msgstr "Version 1.1.2" -#: ../../../changes.rst:46 80ff49dbfa30413fa75ceaf145ec6a3b +#: ../../../changes.rst:60 879df25dcc7a4adbb6a131a669028eb7 msgid "Feature: Add a simple language-server, tested on neovim and vscode." msgstr "" -#: ../../../changes.rst:47 c16cae5e4b5a413f890924aae18b10f1 +#: ../../../changes.rst:61 27036d8837c7444299443c7eb36b1350 msgid "" "Editor: Upgrade vscode extenions to support the ``bitproto-language-" "server``." msgstr "" -#: ../../../changes.rst:50 d760bd22453742f9a43c8144660042af +#: ../../../changes.rst:64 22430b5dd93646ca98b0bcefa63d559a msgid "Version 1.1.2" msgstr "Version 1.1.2" -#: ../../../changes.rst:54 26ac073c24044181a22c1d41b56d25df +#: ../../../changes.rst:68 4c6aaa50d6f64d988da201a842d018e4 msgid "Feature: Allow using constants as option values. ISSUE #61, PR #63" msgstr "" -#: ../../../changes.rst:57 b0046c32c229421392f8d3c2badbb7d7 +#: ../../../changes.rst:71 626d2ac5783b402fb60b7f7becf79c23 msgid "Version 1.1.1" msgstr "" -#: ../../../changes.rst:61 12f263a55eda445a9b3c92bf86a4c3de +#: ../../../changes.rst:75 94ae9ab794da4a6cb48bd87c672eb5d7 msgid "" "Fix bug: enum importing other bitproto's field name generation bug. #53 #52" msgstr "" -#: ../../../changes.rst:62 52d66b4337644fd18beae488ad3255e2 +#: ../../../changes.rst:76 f7d4ba6610dd46a1961237a2454515f3 msgid "" "Fix bug: import statements of bitprotos should be placed ahead of other " "declarations. #53" msgstr "" -#: ../../../changes.rst:65 22cb18322ba44cbca1d0d06797f7b798 +#: ../../../changes.rst:79 89aa0dedc2d6470c97e1d8bd230b6966 msgid "Version 1.1.0" msgstr "" -#: ../../../changes.rst:69 c46626dc5a5d4c2ba9a836831a7821ae +#: ../../../changes.rst:83 80d82251a84b4d319e9f65c36a26e176 msgid "" "Performance improvements for C bitprotolib, 40~60us improvement per call on " "stm32. PR #48." msgstr "" -#: ../../../changes.rst:70 4ddf229304cb447085af86c7cb1500d0 +#: ../../../changes.rst:84 d4da75bd735347548b198c1aca4a2344 msgid "" "Fix Python nested message ``__post_init___`` function code generation. PR " "#48, commit 73f4b01." msgstr "" -#: ../../../changes.rst:73 3f89d51d88b843489a296cead4dfea86 +#: ../../../changes.rst:87 d0e0754fcb174c5495a88d2835042b6e msgid "Version 1.0.1" msgstr "" -#: ../../../changes.rst:77 dc8ee87e18ef422f9906a8d85f1e93df +#: ../../../changes.rst:91 275856414146490ca6b9cbd67e4092e7 msgid "Add support for Python 3.11" msgstr "" -#: ../../../changes.rst:80 256f5b5a0e7e41299e71e29f5be6aa8b +#: ../../../changes.rst:94 032a234a56034236b4e826efb705ad78 msgid "Version 1.0.0" msgstr "" -#: ../../../changes.rst:84 1b006c1612a549fb8b1c2054fea6294d +#: ../../../changes.rst:98 71516cf0b39541c1bf44e63f751b6b30 msgid "First fully release version" msgstr "第一次发布 1.0 版本" -#: ../../../changes.rst:89 123c8b04025f4014a2a6ea3601292901 +#: ../../../changes.rst:103 9d5b1413fd8b4e858ed3ec16896b67d6 msgid "Version 0.4.6" msgstr "" -#: ../../../changes.rst:91 32d4097cc1bb42a284d013b0d6bf0f2c +#: ../../../changes.rst:105 d788f267914f42dc985449400b3afea4 msgid "Support signed integers with arbitrary bits, e.g. int24 PR#45." msgstr "支持任意比特数目的有符号整数类型 例如 int24, 见 PR#45" -#: ../../../changes.rst:96 cd1d51ee9e3c4b708cd9a9fd31ffd497 +#: ../../../changes.rst:110 939038b304f4446abcb4ab546454dcdc msgid "Version 0.4.5" msgstr "" -#: ../../../changes.rst:98 dc88283855f843a495bab4f3c9ad415d +#: ../../../changes.rst:112 9489bdeb03ca4e7bb8abaa5d6e6a9c21 msgid "" "Use Python IntEnum for enum generation (respecting backward compatibility) " "PR#41." msgstr "" -#: ../../../changes.rst:103 ebed9fb7d14142d591662da7185c23d2 +#: ../../../changes.rst:117 181db1787bcb41c09aafdb29f74e20bd msgid "Version 0.4.4" msgstr "" -#: ../../../changes.rst:105 f3413287976c47e2b9de95e528c6a72e +#: ../../../changes.rst:119 6017dcf0a12d4c1f9b0537b111c88b9f msgid "Minor fix compiler setup.py path issue." msgstr "" -#: ../../../changes.rst:110 3746a5e757ac41b582f2d6d9f91f5379 +#: ../../../changes.rst:124 f0e39859572c41968d2a399697a70a6c msgid "Version 0.4.2" msgstr "" -#: ../../../changes.rst:112 2cc45826f9304b42b0e5899dfdb17f23 +#: ../../../changes.rst:126 960bf3e0d9f14de59adf6fe07c4a06f8 msgid "Allow using ``type`` as message field name, fixes issue #39." msgstr "" -#: ../../../changes.rst:117 26969591f7454f34be89e5998982923a +#: ../../../changes.rst:131 43df1fb36dfd4e4bb23a3743724e1e68 msgid "Version 0.4.0" msgstr "" -#: ../../../changes.rst:119 eb895e1c963342f489630f6dc2fd642b +#: ../../../changes.rst:133 8b20158f4cf1497a80c3c502b38bc56c msgid "" "Add support for ``message`` and ``enum`` extensiblity for protocol forward " "compatibility." msgstr "" -#: ../../../changes.rst:120 a557134b8d8148a9ae61364d595e6d61 +#: ../../../changes.rst:134 bb329536263f4cb8b0210925946554fe msgid "Cut down the code size of generated language-specific files." msgstr "" -#: ../../../changes.rst:121 bc8f1b17164e4cd58c6b434cb68f6099 +#: ../../../changes.rst:135 b527f338e5274618b465f2dc9bf1b414 msgid "Refactor the bitproto compiler." msgstr "" -#: ../../../changes.rst:122 147604be81434646a2a96ffdfc87e87f +#: ../../../changes.rst:136 a6a89b7d729a439bb25705c3dadbfc0a msgid "" "Refactor the bitproto serialization mechanism, using language-specific " "libraries instead of pure compiler-generated files." msgstr "" + +#~ msgid "" +#~ "Bugfix: Extend ``BP_BIG_ENDIAN`` auto-detection to recognise " +#~ "``__BIG_ENDIAN__`` in addition to ``__BYTE_ORDER__``, covering the TI ARM " +#~ "CGT compiler (``--be32`` on big-endian targets such as the TMS570). This " +#~ "applies to both the optimization-mode generated code and the standard-mode C" +#~ " library; previously these targets fell through to the little-endian path " +#~ "and produced incorrect results for multi-byte fields. PR #84." +#~ msgstr "" diff --git a/docs/locales/zh/LC_MESSAGES/endianness.po b/docs/locales/zh/LC_MESSAGES/endianness.po index a627b9a..5684cfe 100644 --- a/docs/locales/zh/LC_MESSAGES/endianness.po +++ b/docs/locales/zh/LC_MESSAGES/endianness.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: bitproto 0.4.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-06-19 01:28-0700\n" +"POT-Creation-Date: 2026-06-19 06:16-0700\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: zh \n" @@ -19,11 +19,11 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "Generated-By: Babel 2.18.0\n" -#: ../../endianness.rst:6 0b040be315ce42209b21a9e8b15b6036 +#: ../../endianness.rst:6 7136afd20fcd4d0d8a12974726896c23 msgid "Endianness" msgstr "字节序" -#: ../../endianness.rst:8 ccaaaf10bdfa4f648bcb9d02270e5878 +#: ../../endianness.rst:8 3d025bff8d20496f9f1edf9edfe0a6cf msgid "" "bitproto's wire format is **little-endian on every platform**: the lowest " "byte index on the wire holds the least-significant bits of a field. This is " @@ -35,11 +35,11 @@ msgstr "" "endian)**:编码后字节序列中索引最低的字节存放字段的最低有效位。这是编码格式的固定属性,与运行编码器或解码器的机器无关 —— " "字节序不同的两端始终可以互通。" -#: ../../endianness.rst:16 102ab05c4eb54687b25d8137490bbd8d +#: ../../endianness.rst:16 fc01d7e1b6e44805ac7db4130c27ef38 msgid "Language support" msgstr "各语言的支持情况" -#: ../../endianness.rst:18 4949128459f0422bb13dae054d386f55 +#: ../../endianness.rst:18 831aa8811cc8413fb0b22b4d415a411a msgid "" "Whether the *host* CPU is big-endian only ever mattered for C, because only " "C reads an integer field's raw memory bytes. Python and Go operate on " @@ -49,92 +49,93 @@ msgstr "" "*宿主机* CPU 是否为大端序只对 C 有影响,因为只有 C 会直接读取整数字段的原始内存字节。Python 和 Go 是对整数的 *值* " "做移位和掩码运算,这种方式天然与字节序无关。" -#: ../../endianness.rst:26 199c9c0766e04113b484d2840ecfba51 +#: ../../endianness.rst:26 012d2a84bcb642269599edfa18cfb020 msgid "Target" msgstr "目标语言" -#: ../../endianness.rst:27 688b7dde52824f65b24529a68090d35f +#: ../../endianness.rst:27 747bb89a0bbd473da1aa3196fc6d7c46 msgid "How bits are moved" msgstr "比特如何搬运" -#: ../../endianness.rst:28 f2ba25db7dbe4c54bc6e9cb8564a02a5 +#: ../../endianness.rst:28 29244b384e6c456798294482296844be msgid "Big-endian host" msgstr "大端序主机" -#: ../../endianness.rst:29 7185def3bcd24250bb7adcf4c8c05176 +#: ../../endianness.rst:29 5c4b505f2ec84d03baabd9eb286d51b7 msgid "Python" msgstr "Python" -#: ../../endianness.rst:30 0e787b8470584e63ab81d90da3c15128 +#: ../../endianness.rst:30 fea60dc320d54de89d55e32ca39772f0 msgid "value math on Python ints" msgstr "对 Python 整数做数值运算" #: ../../endianness.rst:31 ../../endianness.rst:34 -#: 41384d1bc15f45ada45248e4fdd697d3 d28241f219114b51b5d2002609b864d0 +#: 2bca643b475f47aeb485da537a563ae7 c14f9f62e9fc4e15964025fb7a2818e8 msgid "always correct" msgstr "始终正确" -#: ../../endianness.rst:32 69d0a06ec23d462f9e142333c75d80d1 +#: ../../endianness.rst:32 b7ae0ca3406f4e6587879b78edf45d7b msgid "Go" msgstr "Go" -#: ../../endianness.rst:33 cb9b9a23775744cc89f3f5ab9c07b6dc +#: ../../endianness.rst:33 14524635720b4d1ca4872ee28c2174c0 msgid "value shifts on typed fields" msgstr "对定型字段做数值移位" -#: ../../endianness.rst:35 a4d294b5cc7f44cb8263527b2e7fb893 +#: ../../endianness.rst:35 14db03952cd84c24955e7a887a149ff8 msgid "C (standard mode)" msgstr "C(标准模式)" -#: ../../endianness.rst:36 4fd18130c01a4c6f827652c3904fc3ec +#: ../../endianness.rst:36 d948cf287b9b4417950a0abdc2f43d50 msgid "``lib/c`` runtime" msgstr "``lib/c`` 运行库" #: ../../endianness.rst:37 ../../endianness.rst:40 -#: d7b60cd145a54177ac0e4d328767a09b e982e973ea5740e7887c8c0b6e4121ed +#: 1077b478251340129799f4a18e8a9d94 dba0c7e5fc144f03b389f5e00b51d0d6 msgid "correct" msgstr "正确" -#: ../../endianness.rst:38 76b701d8127a4e508b5cb4004301b984 +#: ../../endianness.rst:38 c23c81fcf4d74108bca273369cc04135 msgid "C (optimization mode)" msgstr "C(优化模式)" -#: ../../endianness.rst:39 ab408111deb7443b927252ec5053ffe0 +#: ../../endianness.rst:39 f5b13f6e5d6c47f0a780536fc836b026 msgid "generated bit-copy statements" msgstr "生成的比特拷贝语句" -#: ../../endianness.rst:42 267c254a223341d890878a779748f20d +#: ../../endianness.rst:42 93349714a55d4e37b2960c8294f345c0 msgid "" "So nothing special is required for Go or Python. The remainder of this page " "is about C." msgstr "因此 Go 和 Python 不需要做任何特殊处理。本页接下来的内容都是关于 C 的。" -#: ../../endianness.rst:48 0fda01f52aba404ca7e7841635e1b526 +#: ../../endianness.rst:48 57c84752f5024fdb86d4a844b71778a8 msgid "C standard mode" msgstr "C 标准模式" -#: ../../endianness.rst:50 b789baff2f8842d7b046e63d83fe28fc +#: ../../endianness.rst:50 cca64a9a0f8b4b019a9a2904e3eea409 msgid "" "The C library (``lib/c/bitproto.c``) detects a big-endian host automatically" -" via ``__BYTE_ORDER__`` and selects an endian-neutral code path. You may " -"also force it by defining ``BP_BIG_ENDIAN`` when compiling the library, for " -"toolchains that do not define ``__BYTE_ORDER__``:" +" (via ``__BYTE_ORDER__`` for GCC/Clang, ``__BIG_ENDIAN__`` for the TI ARM " +"CGT compiler, and ``__LITTLE_ENDIAN__ == 0`` for IAR) and selects an endian-" +"neutral code path. You may also force it by defining ``BP_BIG_ENDIAN`` when " +"compiling the library, for toolchains that expose none of these macros:" msgstr "" -"C 运行库 (``lib/c/bitproto.c``) 会通过 ``__BYTE_ORDER__`` " -"自动检测大端序主机,并选择与字节序无关的代码路径。对于不定义 ``__BYTE_ORDER__`` 的工具链,你也可以在编译运行库时定义 " -"``BP_BIG_ENDIAN`` 来强制启用:" +"C 运行库 (``lib/c/bitproto.c``) 会自动检测大端序主机(GCC/Clang 用 ``__BYTE_ORDER__``,TI " +"ARM CGT 编译器用 ``__BIG_ENDIAN__``,IAR 用 ``__LITTLE_ENDIAN__ == " +"0``),并选择与字节序无关的代码路径。对于这些宏都不提供的工具链,你也可以在编译运行库时定义 ``BP_BIG_ENDIAN`` 来强制启用:" -#: ../../endianness.rst:59 dfe5ca7c24b74b21a037d8a627cb31f4 +#: ../../endianness.rst:60 3aa2242253ac49afaf1f9d186fbb7dd0 msgid "" "On a little-endian host the library is byte-for-byte unchanged, so there is " "no performance impact on the common target." msgstr "在小端序主机上,运行库逐字节保持不变,因此对常见的目标平台没有任何性能影响。" -#: ../../endianness.rst:65 e88b8e2df1064aa88e0681f1e15a5577 +#: ../../endianness.rst:66 949c000ec51643ff81ec09786de2909d msgid "C optimization mode" msgstr "C 优化模式" -#: ../../endianness.rst:67 668c05ce7e5b4cd299438125249d1301 +#: ../../endianness.rst:68 0486098661a9470898754b4510b961d6 msgid "" ":ref:`Optimization mode ` generates plain " "bit-copy statements that read and write integer fields through their in-" @@ -146,28 +147,31 @@ msgstr "" "会生成直接的比特拷贝语句,通过整数字段的内存字节来读写它们。为了在小端序和大端序主机上都保持正确,bitproto " "默认会生成两份等价的代码路径,并用一个预处理宏来区分:" -#: ../../endianness.rst:80 c3e4f7e8383b4362af0360e008b10f49 +#: ../../endianness.rst:81 83de8141deaa4763b641eed9af2b9e0f msgid "" -"A big-endian host is auto-detected via ``__BYTE_ORDER__``; you may also " -"force the big-endian path by defining ``BP_BIG_ENDIAN`` when compiling the " -"generated code. The little-endian path is identical to earlier bitproto " -"releases, so there is no performance change on little-endian targets — only " -"the generated source is a little larger." +"A big-endian host is auto-detected (via ``__BYTE_ORDER__`` for GCC/Clang, " +"``__BIG_ENDIAN__`` for the TI ARM CGT compiler, and ``__LITTLE_ENDIAN__ == " +"0`` for IAR); you may also force the big-endian path by defining " +"``BP_BIG_ENDIAN`` when compiling the generated code. The little-endian path " +"is identical to earlier bitproto releases, so there is no performance change" +" on little-endian targets — only the generated source is a little larger." msgstr "" -"大端序主机会通过 ``__BYTE_ORDER__`` 自动检测;你也可以在编译生成的代码时定义 ``BP_BIG_ENDIAN`` " -"来强制使用大端序路径。小端序路径与早期版本的 bitproto 完全一致,因此在小端序目标上没有任何性能变化 —— 只是生成的源码会略大一点。" +"大端序主机会被自动检测(GCC/Clang 用 ``__BYTE_ORDER__``,TI ARM CGT 编译器用 " +"``__BIG_ENDIAN__``,IAR 用 ``__LITTLE_ENDIAN__ == 0``);你也可以在编译生成的代码时定义 " +"``BP_BIG_ENDIAN`` 来强制使用大端序路径。小端序路径与早期版本的 bitproto 完全一致,因此在小端序目标上没有任何性能变化 —— " +"只是生成的源码会略大一点。" -#: ../../endianness.rst:89 8d62efc6537d4a4f9cb8e5f7d54d1f6d +#: ../../endianness.rst:92 0529072cd7fc4d6da9f6e67c6db2611d msgid "The ``--endian`` option" msgstr "``--endian`` 选项" -#: ../../endianness.rst:91 e84c122aadef45e887a7e8d2f84f37b7 +#: ../../endianness.rst:94 d778bd1ba0b44dda9e155248ead64239 msgid "" "If you know your target's byte order you can drop the unused path and shrink" " the generated source with the ``--endian`` option (optimization mode only):" msgstr "如果你已经知道目标平台的字节序,可以用 ``--endian`` 选项去掉用不到的那份代码路径,从而缩小生成的源码(仅在优化模式下有效):" -#: ../../endianness.rst:105 dbc23d079cd24ab0ac8cb9144b9fe748 +#: ../../endianness.rst:108 3eb9c538794d4a34ae65ef5727f6b5e6 msgid "" "``--endian`` only affects optimization-mode C/C++ code. It has no effect on " "the wire format, and none on Go or Python." diff --git a/example/C-optimization-mode/example_bp.c b/example/C-optimization-mode/example_bp.c index 721c8ee..d5dfdec 100644 --- a/example/C-optimization-mode/example_bp.c +++ b/example/C-optimization-mode/example_bp.c @@ -1,8 +1,10 @@ // Code generated by bitproto. DO NOT EDIT. #include "example_bp.h" -#if !defined(BP_BIG_ENDIAN) && defined(__BYTE_ORDER__) && \ - (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#if !defined(BP_BIG_ENDIAN) && (\ + (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__BIG_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 #endif #ifdef BP_BIG_ENDIAN diff --git a/example/CPP-optimization-mode/example_bp.c b/example/CPP-optimization-mode/example_bp.c index 721c8ee..d5dfdec 100644 --- a/example/CPP-optimization-mode/example_bp.c +++ b/example/CPP-optimization-mode/example_bp.c @@ -1,8 +1,10 @@ // Code generated by bitproto. DO NOT EDIT. #include "example_bp.h" -#if !defined(BP_BIG_ENDIAN) && defined(__BYTE_ORDER__) && \ - (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#if !defined(BP_BIG_ENDIAN) && (\ + (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__BIG_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 #endif #ifdef BP_BIG_ENDIAN diff --git a/lib/c/bitproto.c b/lib/c/bitproto.c index 1ffbde5..e11f8f9 100644 --- a/lib/c/bitproto.c +++ b/lib/c/bitproto.c @@ -10,9 +10,11 @@ // fallback. Users may force this by predefining BP_BIG_ENDIAN. // __BYTE_ORDER__ / __ORDER_BIG_ENDIAN__ covers GCC/Clang. // __BIG_ENDIAN__ covers TI ARM CGT (--be32) and some other toolchains. -#if !defined(BP_BIG_ENDIAN) && ( \ +// __LITTLE_ENDIAN__ == 0 covers IAR (which always defines it). +#if !defined(BP_BIG_ENDIAN) && ( \ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ - defined(__BIG_ENDIAN__)) + defined(__BIG_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 #endif From 960788198f01d54dc96adb64210f665affab594f Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:36:29 -0700 Subject: [PATCH 5/9] fix c big-endian compiler macro detection --- .../bitproto/renderer/impls/c/renderer_c.py | 6 ++- example/C-optimization-mode/example_bp.c | 2 + example/CPP-optimization-mode/example_bp.c | 2 + lib/c/bitproto.c | 6 ++- tests/test_encoding/test_endian.py | 52 +++++++++++++++++++ 5 files changed, 66 insertions(+), 2 deletions(-) diff --git a/compiler/bitproto/renderer/impls/c/renderer_c.py b/compiler/bitproto/renderer/impls/c/renderer_c.py index 797e452..b06b078 100644 --- a/compiler/bitproto/renderer/impls/c/renderer_c.py +++ b/compiler/bitproto/renderer/impls/c/renderer_c.py @@ -412,12 +412,16 @@ def render(self) -> None: # Auto-detect a big-endian host so the default just works without # the user defining BP_BIG_ENDIAN; still overridable via -D. # __BYTE_ORDER__ / __ORDER_BIG_ENDIAN__ covers GCC/Clang. - # __BIG_ENDIAN__ covers TI ARM CGT (--be32) and some other toolchains. + # __ARM_BIG_ENDIAN covers ACLE-compatible Arm toolchains, including + # TI Arm Clang. __big_endian__ covers legacy TI ARM CGT (armcl). + # __BIG_ENDIAN__ covers some other toolchains. # __LITTLE_ENDIAN__ == 0 covers IAR (which always defines it). self.push("#if !defined(BP_BIG_ENDIAN) && (\\") self.push( " (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \\" ) + self.push(" defined(__ARM_BIG_ENDIAN) || \\") + self.push(" defined(__big_endian__) || \\") self.push(" defined(__BIG_ENDIAN__) || \\") self.push(" (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0)))") self.push("#define BP_BIG_ENDIAN 1") diff --git a/example/C-optimization-mode/example_bp.c b/example/C-optimization-mode/example_bp.c index d5dfdec..f4adc84 100644 --- a/example/C-optimization-mode/example_bp.c +++ b/example/C-optimization-mode/example_bp.c @@ -3,6 +3,8 @@ #include "example_bp.h" #if !defined(BP_BIG_ENDIAN) && (\ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__ARM_BIG_ENDIAN) || \ + defined(__big_endian__) || \ defined(__BIG_ENDIAN__) || \ (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 diff --git a/example/CPP-optimization-mode/example_bp.c b/example/CPP-optimization-mode/example_bp.c index d5dfdec..f4adc84 100644 --- a/example/CPP-optimization-mode/example_bp.c +++ b/example/CPP-optimization-mode/example_bp.c @@ -3,6 +3,8 @@ #include "example_bp.h" #if !defined(BP_BIG_ENDIAN) && (\ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__ARM_BIG_ENDIAN) || \ + defined(__big_endian__) || \ defined(__BIG_ENDIAN__) || \ (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 diff --git a/lib/c/bitproto.c b/lib/c/bitproto.c index e11f8f9..d254434 100644 --- a/lib/c/bitproto.c +++ b/lib/c/bitproto.c @@ -9,10 +9,14 @@ // to the wire, so the byte-copy fast paths below need an endian-neutral // fallback. Users may force this by predefining BP_BIG_ENDIAN. // __BYTE_ORDER__ / __ORDER_BIG_ENDIAN__ covers GCC/Clang. -// __BIG_ENDIAN__ covers TI ARM CGT (--be32) and some other toolchains. +// __ARM_BIG_ENDIAN covers ACLE-compatible Arm toolchains, including TI Arm +// Clang. __big_endian__ covers legacy TI ARM CGT (armcl). __BIG_ENDIAN__ +// covers some other toolchains. // __LITTLE_ENDIAN__ == 0 covers IAR (which always defines it). #if !defined(BP_BIG_ENDIAN) && ( \ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || \ + defined(__ARM_BIG_ENDIAN) || \ + defined(__big_endian__) || \ defined(__BIG_ENDIAN__) || \ (defined(__LITTLE_ENDIAN__) && (__LITTLE_ENDIAN__ == 0))) #define BP_BIG_ENDIAN 1 diff --git a/tests/test_encoding/test_endian.py b/tests/test_encoding/test_endian.py index d0d12e0..7f074a0 100644 --- a/tests/test_encoding/test_endian.py +++ b/tests/test_encoding/test_endian.py @@ -23,12 +23,15 @@ import os import shutil import subprocess +import sys import pytest HERE = os.path.dirname(__file__) CASES_DIR = os.path.join(HERE, "encoding-cases") LIB_C_DIR = os.path.abspath(os.path.join(HERE, "..", "..", "lib", "c")) +ROOT_DIR = os.path.abspath(os.path.join(HERE, "..", "..")) +EXAMPLE_PROTO = os.path.join(ROOT_DIR, "example", "example.bitproto") # Optimization-mode cases that emit encoded wire bytes to stdout (the "consts" # case supports optimization mode but prints nothing, so it is excluded here). @@ -46,6 +49,10 @@ ) +def _gcc_compile(source, output, *args: str) -> None: + subprocess.check_call(["gcc", "-c", *args, str(source), "-o", str(output)]) + + def _make(case: str, target: str, **env_extra: str) -> bytes: env = dict(os.environ, **env_extra) return subprocess.check_output( @@ -64,6 +71,51 @@ def _clean(case: str) -> None: ) +_BIG_ENDIAN_MACRO_CASES = [ + ("gcc-clang-byte-order", ["-D__BYTE_ORDER__=__ORDER_BIG_ENDIAN__"]), + ("acle-arm", ["-D__ARM_BIG_ENDIAN"]), + ("ti-arm-cgt", ["-D__big_endian__"]), + ("generic", ["-D__BIG_ENDIAN__"]), + ("iar-arm", ["-U__LITTLE_ENDIAN__", "-D__LITTLE_ENDIAN__=0"]), +] + + +@requires_tools +@pytest.mark.parametrize(("name", "macro_args"), _BIG_ENDIAN_MACRO_CASES) +def test_runtime_big_endian_macro_detection(name, macro_args, tmp_path) -> None: + """Runtime C library recognizes common compiler big-endian macros.""" + src = tmp_path / f"{name}.c" + src.write_text(f""" +#include "{os.path.join(LIB_C_DIR, "bitproto.c")}" +#ifndef BP_BIG_ENDIAN +#error "BP_BIG_ENDIAN not detected" +#endif +""") + _gcc_compile(src, tmp_path / f"{name}.o", *macro_args) + + +@requires_tools +@pytest.mark.parametrize(("name", "macro_args"), _BIG_ENDIAN_MACRO_CASES) +def test_optimization_mode_big_endian_macro_detection( + name, macro_args, tmp_path +) -> None: + """Generated optimization-mode C recognizes common big-endian macros.""" + outdir = tmp_path / "generated" + outdir.mkdir() + subprocess.check_call( + [sys.executable, "-m", "bitproto._main", "c", EXAMPLE_PROTO, str(outdir), "-O"] + ) + + src = tmp_path / f"{name}.c" + src.write_text(f""" +#include "{outdir / "example_bp.c"}" +#ifndef BP_BIG_ENDIAN +#error "BP_BIG_ENDIAN not detected" +#endif +""") + _gcc_compile(src, tmp_path / f"{name}.o", "-I", str(outdir), *macro_args) + + @requires_tools @pytest.mark.parametrize("case", OPT_MODE_CASES) def test_opt_mode_big_endian_branch(case: str) -> None: From b7c3d9d2ba217a5f2e90a365883317f62098dcb0 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:39:09 -0700 Subject: [PATCH 6/9] docs update big-endian macro detection notes --- changes.rst | 12 +++++++----- docs/endianness.rst | 17 ++++++++++------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/changes.rst b/changes.rst index cf7e5d7..a05586a 100644 --- a/changes.rst +++ b/changes.rst @@ -6,11 +6,13 @@ Version 1.3.1 .. _version-1.3.1: - Bugfix: Broaden ``BP_BIG_ENDIAN`` auto-detection beyond GCC/Clang's - ``__BYTE_ORDER__`` to also cover the TI ARM CGT (``__BIG_ENDIAN__``, e.g. - ``--be32`` on the TMS570) and IAR (``__LITTLE_ENDIAN__ == 0``) compilers, in - both the optimization-mode generated code and the standard-mode C library. - Previously these big-endian targets fell through to the little-endian path and - produced incorrect results for multi-byte fields. PR #84. + ``__BYTE_ORDER__`` to also cover ACLE-compatible Arm toolchains such as TI + Arm Clang (``__ARM_BIG_ENDIAN``), legacy TI ARM CGT (``__big_endian__``), + other toolchains that define ``__BIG_ENDIAN__``, and IAR + (``__LITTLE_ENDIAN__ == 0``), in both the optimization-mode generated code and + the standard-mode C library. Previously these big-endian targets fell through + to the little-endian path and produced incorrect results for multi-byte + fields. PR #84. - Packaging: Show the project README as the long description on the PyPI project page for the ``bitproto`` package. diff --git a/docs/endianness.rst b/docs/endianness.rst index cca3d35..8735618 100644 --- a/docs/endianness.rst +++ b/docs/endianness.rst @@ -48,10 +48,12 @@ C standard mode --------------- The C library (``lib/c/bitproto.c``) detects a big-endian host automatically -(via ``__BYTE_ORDER__`` for GCC/Clang, ``__BIG_ENDIAN__`` for the TI ARM CGT -compiler, and ``__LITTLE_ENDIAN__ == 0`` for IAR) and selects an endian-neutral -code path. You may also force it by defining ``BP_BIG_ENDIAN`` when compiling -the library, for toolchains that expose none of these macros: +(via ``__BYTE_ORDER__`` for GCC/Clang, ``__ARM_BIG_ENDIAN`` for +ACLE-compatible Arm toolchains such as TI Arm Clang, ``__big_endian__`` for +legacy TI ARM CGT, ``__BIG_ENDIAN__`` for other toolchains, and +``__LITTLE_ENDIAN__ == 0`` for IAR) and selects an endian-neutral code path. +You may also force it by defining ``BP_BIG_ENDIAN`` when compiling the library, +for toolchains that expose none of these macros: .. sourcecode:: bash @@ -79,9 +81,10 @@ emits two equivalent code paths guarded by a preprocessor macro: #endif A big-endian host is auto-detected (via ``__BYTE_ORDER__`` for GCC/Clang, -``__BIG_ENDIAN__`` for the TI ARM CGT compiler, and ``__LITTLE_ENDIAN__ == 0`` -for IAR); you may also force the big-endian path by defining ``BP_BIG_ENDIAN`` -when compiling the generated code. +``__ARM_BIG_ENDIAN`` for ACLE-compatible Arm toolchains such as TI Arm Clang, +``__big_endian__`` for legacy TI ARM CGT, ``__BIG_ENDIAN__`` for other +toolchains, and ``__LITTLE_ENDIAN__ == 0`` for IAR); you may also force the +big-endian path by defining ``BP_BIG_ENDIAN`` when compiling the generated code. The little-endian path is identical to earlier bitproto releases, so there is no performance change on little-endian targets — only the generated source is a little larger. From 6138ee22a11d80e62b1d54552fd86d2eac04847d Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:41:47 -0700 Subject: [PATCH 7/9] ci add qemu big-endian test job --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f15c9c9..70ab648 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,3 +69,38 @@ jobs: - name: Run tests run: | make test --no-print-directory -s + + big-endian: + + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + with: + platforms: s390x + + - name: Run endian tests on s390x + run: | + docker run --rm --platform linux/s390x \ + -v "${{ github.workspace }}:/work" \ + -w /work \ + python:3.13-bookworm \ + bash -euxo pipefail -c ' + apt-get update + apt-get install -y --no-install-recommends gcc make + python -m pip install -r compiler/requirements.txt -r tests/requirements_tests.txt + ln -sf /usr/local/bin/python /usr/local/bin/python3 + printf "%s\n" \ + "#!/usr/bin/env sh" \ + "PYTHONPATH=/work/compiler exec python -m bitproto._main \"\$@\"" \ + >/usr/local/bin/bitproto + chmod +x /usr/local/bin/bitproto + PYTHONPATH=compiler:lib/py python - <<'"'"'PY'"'"' + import sys + assert sys.byteorder == "big", sys.byteorder + PY + PYTHONPATH=compiler:lib/py python -m pytest tests/test_encoding/test_endian.py -v + ' From 6f066edd8ced8b413fbd11073884e4f1315d3cc5 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:44:37 -0700 Subject: [PATCH 8/9] ci fix qemu big-endian python wrapper --- .github/workflows/ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70ab648..e67b1d0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,15 +92,11 @@ jobs: apt-get update apt-get install -y --no-install-recommends gcc make python -m pip install -r compiler/requirements.txt -r tests/requirements_tests.txt - ln -sf /usr/local/bin/python /usr/local/bin/python3 printf "%s\n" \ "#!/usr/bin/env sh" \ "PYTHONPATH=/work/compiler exec python -m bitproto._main \"\$@\"" \ >/usr/local/bin/bitproto chmod +x /usr/local/bin/bitproto - PYTHONPATH=compiler:lib/py python - <<'"'"'PY'"'"' - import sys - assert sys.byteorder == "big", sys.byteorder - PY + PYTHONPATH=compiler:lib/py python -c "import sys; assert sys.byteorder == \"big\", sys.byteorder" PYTHONPATH=compiler:lib/py python -m pytest tests/test_encoding/test_endian.py -v ' From d241c6ee074203138d9a9a6fbf43a602dbfa0956 Mon Sep 17 00:00:00 2001 From: hit9 Date: Fri, 19 Jun 2026 06:49:57 -0700 Subject: [PATCH 9/9] ci fix qemu big-endian python path --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e67b1d0..154c30c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,6 +97,6 @@ jobs: "PYTHONPATH=/work/compiler exec python -m bitproto._main \"\$@\"" \ >/usr/local/bin/bitproto chmod +x /usr/local/bin/bitproto - PYTHONPATH=compiler:lib/py python -c "import sys; assert sys.byteorder == \"big\", sys.byteorder" - PYTHONPATH=compiler:lib/py python -m pytest tests/test_encoding/test_endian.py -v + PYTHONPATH=/work/compiler:/work/lib/py python -c "import sys; assert sys.byteorder == \"big\", sys.byteorder" + PYTHONPATH=/work/compiler:/work/lib/py python -m pytest tests/test_encoding/test_endian.py -v '