Skip to content

Build system tweaks for reproducible builds#447

Closed
threema-danilo wants to merge 3 commits intoranisalt:masterfrom
threema-ch:reproducible-builds
Closed

Build system tweaks for reproducible builds#447
threema-danilo wants to merge 3 commits intoranisalt:masterfrom
threema-ch:reproducible-builds

Conversation

@threema-danilo
Copy link
Contributor

Hello, we have spent some time to make builds of this library reproducible (at least to a certain degree, we have not yet finished testing and it's possible that we missed some edge cases).

Is this something that you're interested in integrating into your upstream project?

In case of questions, I'm happy to help.

const env = {
...process.env,
// Avoid embedding timestamps into linked binary on macOS
ZERO_AR_DATE: "1",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we set this as an environment variable directly in bindings.gyp? I would rather not involve another script if it just changes the environment like this.

Also, is this something we want for all builds, or is reproducible builds something for specific scenarios?

Copy link
Contributor Author

@threema-danilo threema-danilo Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you find a way to do it in a cross-platform way, I'd be happy to change it! However, setting env variables on Linux/macOS is with ZERO_AR_DATE=1, and on Windows it's $env:ZERO_AR_DATE=1 (at least in PowerShell, I'm not sure about CMD). I'm not aware of a cross-platform syntax unfortunately.

Also, is this something we want for all builds, or is reproducible builds something for specific scenarios?

I don't see any benefit in having timestamps embedded in the binaries. As such, I'd always set this variable (unless there's a scenario where embedded timestamps would be needed).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work if it was set to the GitHub workflow step environment? That would be available on build when released, but local builds will still contain timestamps unless the user also sets ZERO_AR_DATE=1

Alternatively, I believe that npm scripts are portable and setting the build script to

    "install": "ZERO_AR_DATE=1 node-gyp-build",

works (at least it works with yarn)

(sorry for the late reply)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work if it was set to the GitHub workflow step environment? That would be available on build when released, but local builds will still contain timestamps unless the user also sets ZERO_AR_DATE=1

In our case we have node-argon2 as a dependency (pulled in through the source code, not npm builds), and we want to build our product reproducibly. So setting a GitHub workflow env variable wouldn't work.

Alternatively, I believe that npm scripts are portable and setting the build script to

That's a misunderstanding, the npm scripts will run in your local shell environment. So this will work on Linux and macOS, but not on Windows.

The portable approach is having a .js file called through the npm script.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, in that case I think it would be better to use cross-env which does the trick for all platforms and it's quite a small dependency.

    "install": "cross-env ZERO_AR_DATE=1 node-gyp-build",

and add it to the dependencies and I'll merge it if that's OK :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL about cross-env, that package looks nice! Yes, feel free to update my branch as desired 🙂

binding.gyp Outdated
"defines+": ["_HAS_EXCEPTIONS=1"],
"msvs_settings": {
"VCCLCompilerTool": { "ExceptionHandling": 1 }
"VCCLCompilerTool": {"ExceptionHandling": 1},
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep unchanged

Suggested change
"VCCLCompilerTool": {"ExceptionHandling": 1},
"VCCLCompilerTool": { "ExceptionHandling": 1 },

Copy link
Contributor Author

@threema-danilo threema-danilo Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line will be modified in any case due to the trailing comma, but I updated the commit to remove the whitespace change.

(I also rebased against current master.)

- The /Brepro flag is undocumented by Microsoft, but can be found on the
  internet¹ and it removes timestamps from the resulting binary. I tested
  that it works as intended - timestamps are gone.
- Omit debug info to avoid mismatching paths or RSDS signature
- Disable incremental building (since it's a potential source of
  non-determinism)

¹ https://nikhilism.com/post/2020/windows-deterministic-builds/#fix-dates-and-times-in-portable-executables
...to achieve local determinism.
Previously the file system timestamp of the object file (`argon2.o`)
would influence the output binary. The env variable ZERO_AR_DATE=1
avoids this.
@ranisalt
Copy link
Owner

I didn't have permission to push to your branch, so I merged it through the command line 0d88d0d

Waiting for CI to pass to release v0.44 with the changes :)

@ranisalt ranisalt closed this Aug 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants