Skip to content

[ENHANCEMENT] Make firmware builds reproducible: resource packing depends on filesystem ordering #5324

Description

@bgrupczy

Summary

Firmware builds are not reproducible: building the same source tree on two machines produces different firmware.bin and resources-image.lfs, because resource packing depends on filesystem iteration order.

Why it matters

Reproducible builds let a developer rebuild a release tag and confirm the result is bit-for-bit identical to the official build : proving the build environment is correct and that the official binary corresponds exactly to its published source (no tampering, no hidden divergence). Today that is impossible.

Root cause

Two build scripts iterate input directories in filesystem-dependent order:

  • utils/qoi_packer.py : os.listdir() over the GUI icons. The packed qoi.data atlas (stored in the LittleFS resource image) and the generated per-icon Resource offsets therefore vary by host.
  • utils/translations_and_fonts/lang.py : Path.iterdir() over the language directories, later emitted in dict-insertion order, so translation/font data varies by host.

os.listdir() and Path.iterdir() return entries in arbitrary, filesystem-dependent order (APFS, ext4, etc. all differ), so identical source builds to different binaries on different machines.

Evidence

  • Packing the 256-icon set under different input orderings produces a different atlas each time; sorting first yields one identical result regardless of order.
  • The same 256 icons enumerate in a different os.listdir() order on APFS vs an ext4/overlay filesystem (e90a158a vs b450fd54); since the packer preserves that order, the packed qoi.data (and the resource image) necessarily differ. Same-machine builds are byte-identical, so directory order is the only cross-host variable.
  • The build already runs in a pinned Docker image (which fixes the toolchain), but the source is mounted, not baked into the image, so os.listdir() reads the host filesystem's order : the container cannot canonicalize it.

Proposed fix

Sort both directory walks so output depends only on source content. Pull request: #5320.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions