Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the binary output not equal when compiling again?

I'm using a build script to compile several C# projects. The binary output is copied to a result folder, overwriting the previous version of the files, and then added/committed to subversion.

I noticed that the binary output of the compilation are different even when there was no change to the source or environment at all. How is this possible? Isn't the binary result supposed to be exactly equal for the same input?

I'm not intentionally using any kind of special timestamps anywhere, but does the compiler (Microsoft, the one included in .NET 4.0) possibly add timestamps itself?

The reason I'm asking is I'm committing the output to subversion, and due to the way our build server works the checked in changes trigger a rebuild, causing the once again modified binary files to be checked in in a circle.

like image 711
mafu Avatar asked Jan 19 '12 14:01

mafu


2 Answers

ANOTHER UPDATE:

Since 2015 the compiler team has been making an effort to get sources of non-determinism out of the compiler toolchain, so that identical inputs really do produce identical outputs. See the "Concept-determinism" tag on the Roslyn github for more details.


UPDATE: This question was the subject of my blog in May 2012. Thanks for the great question!


How is this possible?

Very easily.

Isn't the binary result supposed to be exactly equal for the same input?

Absolutely not. The opposite is true. Every time you run the compiler you should get a different output. Otherwise how could you know that you'd recompiled?

The C# compiler embeds a freshly generated GUID in an assembly on every compilation, thereby guaranteeing that no two compilations produce exactly the same result.

Moreover -- even without the GUID, the compiler makes no guarantees whatsoever that two "identical" compilations will produce the same results.

In particular, the order in which the metadata tables are populated is highly dependent on details of the file system; the C# compiler starts generating metadata in the order in which the files are given to it, and that can be subtly changed by a variety of factors.

due to the way our build server works the checked in changes trigger a rebuild, causing the once again modified binary files to be checked in in a circle.

I'd fix that if I were you.

like image 186
Eric Lippert Avatar answered Sep 18 '22 07:09

Eric Lippert


Yes, the compiler includes a timestamp. Additionally, in some cases the compiler will auto-increment the assembly version number. I haven't seen any guarantee anywhere that the binary result is meant to be identical.

(Note that if the source is already in Subversion, I'd generally steer clear of also adding the binary files in there. I'd usually only include releases of third-party libraries. It depends on exactly what you're doing though.)

like image 39
Jon Skeet Avatar answered Sep 18 '22 07:09

Jon Skeet