0011. Build: pin nanopb at 0.4.9.1
Date: 2026-09-28
The nanopb runtime is vendored and the generator pinned at 0.4.9.1. The worry was that pinning would silently change the firmware already in the field; the evidence below, extracted verbatim from Tag Firmware Build Reproducibility, settled that it does not. The mismatch that made a pin necessary is in the build reproducibility investigation.
Evidence
The worry was that fixing on 0.4.9.1 would shift the .pb.* files away from what
built the firmware now in the field, making the first commit of generated sources
a silent behavioural change.
It does not. Both generators were run over six proto variants (the five
distributed ones and bittag-legacy, distributed at the time of the test) from
the repository's own .proto files and CombineFiles.cmake-combined options,
and all 24 outputs compared:
- 0.4.8 vs 0.4.9.1 -- identical but for the
/* Generated by nanopb-... */comment and some trailing blank lines. No declaration, field descriptor, size macro orPB_BINDentry differs in any of the 24 files compared. - 0.4.8 vs the tree's actual old generator (
1f0c2e1, the0.4.8-11-g1f0c2e1snapshot) -- the only code change tonanopb_generator.pyacross those eleven commits is insidefields_declaration_cpp_lookup, emitted solely under--cpp-descriptors, which this project does not pass.
Moving to 0.4.9.1 from that snapshot also changes no runtime behaviour:
pb_common.o and pb_encode.o are byte-identical when cross-compiled for
cortex-m4 and cortex-m33, and the sole semantic difference -- a leak fix in
pb_decode_ex under PB_ENABLE_MALLOC -- is in a function garbage-collected out
of the linked images, which call plain pb_decode.