Skip to content

Executable determinism on Windows #9432

@zeramorphic

Description

@zeramorphic

Currently, builds using zig build-exe -O Release[*] targeting Windows are not deterministic. According to zig's documentation, this is unintended behaviour. A timestamp is embedded at 0x0080 in the executable file. This image shows a hexdump of two invocations of the following command.

zig build-exe -target x86_64-windows-gnu --library c --strip --name core out.o -O ReleaseSafe

The out.o file is unchanged between runs.

image

Without --strip, there was also another byte that changed elsewhere, which I assume came from a timestamp in some debug information - but that isn't the main point of this issue since there is already an easy fix (enabling --strip).

There is a blog post about build determinism on the LLVM website that suggests a way to make the build fully deterministic.

When targeting Windows, clang and clang-cl by default also embed the current time in a timestamp field in the output .obj file, because Microsoft’s link.exe in /incremental mode silently mislinks files if that field isn’t set correctly. If you don’t use link.exe’s /incremental flag, or if you link with lld-link, you should pass /Brepro to clang-cl to make it not write the current timestamp into its output.

Both link.exe and lld-link also write the current timestamp into output .dll or .exe files. To make them instead write a hash of the binary into this field, you can pass /Brepro to the linker as well. However, some tools, such as Windows 7’s app compatibility database, try to interpret that field as an actual timestamp and can get confused if it’s set to a hash of the binary. For this case, lld-link also offers a /timestamp: flag that you can give an explicit timestamp that’s written into the output. You could use this to for example write the time of the commit the code is built at instead of the current time to make it deterministic. (But see the footnote on embedding commit hashes below.)

Would it be possible to add a flag to zig build-exe that enables this kind of determinism? Alternatively, this deterministic timestamp-removing behaviour could be enabled by default and selectively disabled with a flag on zig build-exe. Thanks for your support!

Metadata

Metadata

Assignees

No one assigned

    Labels

    backend-llvmThe LLVM backend outputs an LLVM IR Module.bugObserved behavior contradicts documented or intended behaviorlinkingos-windows

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions