How can I force a particular 'compile/link timestamp' in OBJ/EXE/DLL files?

Is there a way to control the 'time date stamp' which the Microsoft VC++ 6.0 compiler and linker put into object files and EXE/DLL files?

I have a relatively large project, comprising about 1000 source files, mostly JAVA and TEXT files, but a small number of Windows C/C++ sources.

The build process is automated using ANT, and produces jar files, war files and eventually exe files using NSIS.

I keep all the sources under version control using Subversion.

What I want to do is verify the MD5 checksum of the final build product, so I can have absolute confidence that a particular EXE was built from a particular set of checked out sources.

This mechanism works great for anything not using Microsoft tools.

For JAR and WAR files, all you have to do is TOUCH the individual components before packaging, (to force a predefined Build timestamp), and the MD5 of the JAR/WAR will be stable.

For NSIS EXE files, the same applies. If you TOUCH the component files, before running the .nsi script, the MD5 of the final product will be repeatable. The same is true for ZIP files and similar.

But for the Microsoft C++ source files, which are compiled using CL.EXE and linked using LINK.EXE, I cannot find how to force the compile timestamp and link timestamp to have a particular value.

Instead, the tools always use current time.

Microsoft embeds these timestamps into the COFF object and EXE/DLL files, so the object files are always slightly different on each build, and this makes the MD5 signature of the EXE/DLL (or any archive with such a file as a subcomponent) different.

This makes checking the resulting MD5 useless for confirming that a particular set of sources generates a particular release version of the deliverable.

Does anyone know how to get around this?

I was expecting some command line switch or environment variable settings or something like that which would cause the designated time to be used instead of current time.

The toolchain is Microsoft Visual Studio 6.0 Professional (the latest and greatest before .NET)

I have spent a lot of time experimenting in the past with workarounds, and getting really frustrated
each time.

I really would like to avoid having to keep copies of large binary files just to make my ZIP/WAR/NSIS files stable.

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Why don't you 'touch' ( these also after they were built using a custom Post Build Command?
It does ineed seem that the Linker puts a timesamp into the EXE header.  This google groups post

shows some code the poster used to obtain the "LinkTimestamp"  Perhaps you can use that as a starting point for writing code to modifying the EXE in a post-link step.
A program here:
   Windows XP Service Pack 2 Support Tools

might be used to locate the exact position of the timestamp in the file, by comparing the results of two identical compiles.
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

In this KB article:
    How to compare binary images of the same project builds
Microsoft suggests:
>> Use the Microsoft Portable Executable and Common Object File Format
     Specification from the MSDN Library to alter the date/time stamps so
     that they won't be a factor in the comparison

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
aswalesAuthor Commented:
Thanks for the confirmation.

I had experimented before by using the COFF spec and perfoming in-situ surgery on the timestamps. Worked fine at the OBJ level, but when I tried doing the same thing on the LINK output I hit another problem (sorry I forgot this bit)

It appears that LINK.EXE is unpredictable about which order it throws symbols and entry points into the output file.

I ran the same version of LINK.EXE, but different versions of the OS, on two different computers. One computer was running W2000SP4, the other running XP-SP2. (Actually I tried multiple computers, but it seemed the difference was OS-dependent).

When given exactly the same binary object files, library files, and command parameters, the binary output was different. Inspection using the appropriate MS tools showed that the differences were in entry point ordering.

This came as a big surprise. I suspected that LINK.EXE was using some external DLL routine for manipulating the entry point table, and the versions provided for XP and W2K were different (so much for thorough OS regression testing....)

And, of course, if I couldn't repeatably control the order of records in the output, then getting a signature such as MD5 to be consistent would be impossible.

What surprised me most about all of this was that I expected this type of operation to be routine. I would expect any program when given the same inputs to generate the same outputs. Otherwise the developers themselves would have a hard time doing reliable regression tests. It's an awful lot easier to check results for simple equality than to perform detailed analysis of the output by eye or program. To me, It's a very simple extension of unit testing philosophy.

Anyhow, I figured I must be missing something obvious, since any other professional organization releasing a product in EXE or DLL form would want a reliable way of confirming that their build process and toolchain generated accurate results. The term 'ISO-9001' came to mind.....

So there were two possibilities here. Either there was a way to force the Microsoft tools to do the job properly, or everyone else with the same interests as me chooses to bypass the MS tools and goes for some third party equivalent which does the right thing. But rather than hunt this down myself, I hoped this forum would help.

So the bottom line, I guess, is this:

If you have to verify that your delivered EXE/DLL product  can be repeatably rebuilt from a given set of sources and tools, but on different computers, how do you do it?

Thanks much
aswalesAuthor Commented:
I realize my problems with LINK.EXE generating different results were likely 'DLL HELL', since the version of the library MSVCRT.DLL was different. Perhaps a hashing function was different or something like that, leading to the iteration order varying when the entry point table was dumped.

So since my original question was answered, I'll close it off

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.