Reproducible Builds on Windows

Danilo mail at dbrgn.ch
Mon Dec 2 00:08:13 UTC 2024


Hi folks

I'm involved with trying to achieve reproducible builds for Threema Desktop 2.0 (https://three.ma/md).

Threema Desktop is an Electron application containing both native node modules (written in C, using node-gyp as build system) as well as a Rust binary.

To achieve reproducible builds, things I've discovered and fixed so far:

- I added the undocumented `/Brepro` MSVC linker flag to ensure that no timestamps are added to the PE binaries
- I added the `/PDBALTPATH:%_PDB%` MSVC linker flag to avoid having absolute build directory paths embedded in the PE binaries
- I added a `rust-toolchain.toml` file to the Rust subproject to ensure that the identical toolchain version is being used for all builds

For node modules, the linker flags can be added in `binding.gyp`. For example:

    ...
    "msvs_settings": {
      ...
      "VCLinkerTool": {
        "AdditionalOptions": [
          # Reproducible builds: Do not include timestamps in binary
          "/Brepro",
          # Reproducible builds: Do not include absolute paths to debug symbols in binary
          "/PDBALTPATH:%_PDB%"
        ]}
    },
    ...

For the Rust project, the config can be added in `.cargo/config.toml`:

    [target.'cfg(target_env = "msvc")']
    rustflags = ["-C", "link-args=/Brepro"] # Reproducible builds on Windows

For debugging, diffoscope (especially the try.diffoscope.org website) was a big help, thanks!

One aspect that I cannot get rid of is the embedded toolchain information, as well as differing behavior between toolchain versions. As an example, the COFF header of the PE files contains the following header fields when buliding with the Visual Studio 2022 toolchain:

    MajorLinkerVersion»     14
    MinorLinkerVersion»     42

>From what I could gather, there is no way to really solve this issue. The approach that we currently plan to implement is to simply declare the toolchain version we used, and let the user deal with the effort to get it installed.

Are there any alternatives? How are other Windows projects dealing with this? Is there maybe a way to build using a MSVC toolchain in a container using Docker for Windows, or something similar? Or can a MSVC redistributable toolchain be installed to a directory, and selected using some environment variables?

Cheers,
Danilo


More information about the rb-general mailing list