Skip to main content

Progress Towards Reproducible UI Builds

· 5 min read
Sarah Jamie Lewis

Earlier this year we talked about the changes we have made to make Cwtch Bindings Reproducible.

In this devlog we will talk about how the Cwtch UI are currently built, the changes we have made to Cwtch UI to make future distributions verifiable, and the next steps we will be taking to make all Cwtch builds reproducible.

This will be useful to anyone who is looking to reproduce Cwtch UI builds specifically, and to anyone who wants to start implementing reproducible builds in their own project.

Building the Cwtch UI

The official Cwtch UI project uses the FLutter framework. The Cwtch UI deliberately tracks the stable channel.

All builds are conducted through the flutter tool e.g. flutter build. We inject two build flags as part of the official build VERSION and COMMIT_DATE:

flutter build linux --dart-define BUILD_VER=cat VERSION --dart-define BUILD_DATE=cat COMMIT_DATE

These flags are defined to be identical to Cwtch Bindings. VERSION is the latest git tag: git describe --tags --abbrev=1 and COMMIT_DATE is the date of the latest commit on the branch echo `git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M` > COMMIT_DATE

All Cwtch UI builds also depend on two external dependencies not managed directly by the flutter project: Tor (implicit as part of the fetchTor scripts) and libCwtch (defined in LIBCWTCH-GO.version, and fetched via the fetch-libcwtch scripts).

The binaries are downloaded via their respective scripts prior to the build, and managed via a separate update process.

Changes we made for reproducible builds

For reproducible linux builds we had to modify the generated linux/CMakeLists.txt file to include the following compiler and linker flags:

  • -fno-ident - suppresses compiler identifying information from compiled artifacts. Without this small changes in compiler versions will result in different binaries.
  • --hash-style=gnu - asserts a standard hashing scheme to use across all compiled artifacts. Without this compilers that have been compiled with different default schemes will produce different artifacts
  • --build-id=none - suppresses build id generation. Without this each compiled artifact will have a section of effectively randomized data.

We have also defined a new linker script that differs from the default by removing all .comment sections from object files. We do this because the linking process links in non-project artifacts like crtbeginS.o which, in most systems, us compiled with a .comment section (the default linking script already removes the .note.gnu* sections.

Tar Archives

Finally, following the guide at we have defined standard metadata for the generated Tar archives to make them also reproducible.

Limitations and Next Steps

The above changes mean that official linux builds of the same commit will now result in identical artifacts.

The next step is to roll these changes into repliqate as we have done with our bindings builds.

However, because Repliqate is based on Debian images and our official UI builds are based on an Ubuntu distribution the resulting archives differ by a single instruction at the start of a few sections - introduced because Ubuntu compiles and provides C Runtime (CRT) artifacts (e.g. crti.o with full branch protection enabled. On 64-bit systems this results in an endcr64 instruction being inserted at the start of the .init and .fini sections, among others.

In order to allow people to fully repliqate Cwtch builds in an isolated environment like repliqate, as we do for Cwtch Bindings, it will be necessary to provide instructions for setting up a hardened image that can work the same way in repliqate.

Pinned Dependencies

Additionally, while our repliqate scripts pin several major dependencies like flutter and go, and the dependencies managed by these systems are locked to specific versions, there are still a few dependencies within the ecosystems that are not strictly pinned.

The major one is libc. Operating systems rarely make big changes to packaged libc versions for a specific distribution (typically because doing so in a non-breaking way would be a major undertaking).

However this does mean that Cwtch reproduciblility is implicitly tied to operating system practices - this is something we would like to begin decoupling ourselves from going forward.

Stay up to date!

We expect to make additional progress on this in the coming weeks and months. Subscribe to our RSS feed, Atom feed, or JSON feed to stay up to date, and get the latest on, all aspects of Cwtch development.

Help us go further!

We couldn't do what we do without all the wonderful community support we get, from one-off donations to recurring support via Patreon.

If you want to see us move faster on some of these goals and are in a position to, please donate. If you happen to be at a company that wants to do more for the community and this aligns, please consider donating or sponsoring a developer.

Donations of $5 or more can opt to receive stickers as a thank-you gift!

For more information about donating to Open Privacy and claiming a thank you gift please visit the Open Privacy Donate page.

A Photo of Cwtch Stickers