tags:

views:

3501

answers:

9

How can I insert compilation timestamp information into an executable I build with Visual C++ 2005? I want to be able to output something like this when I execute the program:

This build XXXX was compiled at dd-mm-yy, hh:mm.

where date and time reflect the time when the project was built. They should not change with each successive call of the program, unless it's recompiled.

+5  A: 
__DATE__ 
__TIME__

are predefined as part of the standards for C99 so should be available to you. They run once with the preprocessor.

sparkes
A: 

Visual C++ also supports __TIMESTAMP__ which is almost exactly what you need. That being said, the tough part about build timestamps is keeping them up to date, that means compiling the file in which __TIMESTAMP__ is used on every rebuild. Not sure if there's a way to set this up in Visual C++ though.

Eric Scrivner
+4  A: 

Though not your exact format, DATE will be of the format Mmm dd yyyy, while TIME will be of the format hh:mm:ss. You can create a string like this and use it in whatever print routine makes sense for you:

const char *buildString = "This build XXXX was compiled at " __DATE__ ", " __TIME__ ".";

(Note on another answer: TIMESTAMP only spits out the modification date/time of the source file, not the build date/time.)

Jim Buck
+1  A: 

I think, the suggested solutions to use DATE, TIME or TIMESTAMP would be good enough. I do recommend to get a hold of a touch program to include in a pre-build step in order to touch the file that holds the use of the preprocessor variable. Touching a file makes sure, that its timestamp is newer than at the time it was last compiled. That way, the date/time in the compiled file is changed as well with each rebuild.

HS
+1  A: 

TIME and DATE can work, however there are some complications.

If you put these definitions in a .h file, and include the definitions from multiple .c/.cpp files, each file will have a different version of the date/time based on when it gets compiled. So if you're looking to use the date/time in two different places and they should always match, you're in trouble. If you're doing an incremental build, one of the files may be rebuilt while the other is not, which again results in time stamps that could be wildly different.

A slightly better approach is to make GetBuildTimeStamp() prototypes in a .h file, and put the TIME and DATE macros in the implementation(.c/.cpp) file. This way you can use the time stamps in multiple places in your code and they will always match. However you need to ensure that the .c/.cpp file is rebuilt every time a build is performed. If you're doing clean builds then this solution may work for you.

If you're doing incremental builds, then you need to ensure the build stamp is updated on every build. In Visual C++ you can do this with PreBuild steps - however in this case I would recommend that instead of using DATE and TIME in a compiled .c/.cpp file, you use a text-based file that is read at run-time during your program's execution. This makes it fast for your build script to update the timestamp (no compiling or linking required) and doesn't require your PreBuild step to understand your compiler flags or options.

Joe Schneider
Another way is to have a single special file that contains the time stamping, and make sure that the makefile used for building rebuilds that particular file every time the program is rebuilt. That is the most common solution that I have seen for larger software projects.
jakobengblom2
+1  A: 

Well... for Visual C++, there's a built in symbol called __ImageBase. Specifically:

EXTERN_C IMAGE_DOS_HEADER __ImageBase;

You can inspect that at runtime to determine the timestamp in the PE header:

const IMAGE_NT_HEADERS *nt_header= (const IMAGE_NT_HEADERS *)((char *)&__ImageBase + __ImageBase.e_lfanew);

And use nt_header->FileHeader.TimeStamp to get the timestamp, which is seconds from 1/1/1970.

Mat Noguchi
A: 

Has anyone got Mat Noguchi's code to work? I tried it but get offset_pointer undeclared identifier. I'd sure like to get this to work!

Reworked the code to make it more Copy/Pasteable.
MSN
A: 

Thanks to MSn for clearing up my confusion re Mat Noguchi's posting! It cleared up the compile error I was getting.

FYI, on my system, there is no FileHeader.TimeStamp but there is a FileHeader.TimeDateStamp.

A: 

Regarding the Mat Noguchi ImageBase business..

I now have this working and it does exactly what I want BUT one odd thing cropped up.

Now when I do BATCH BUILD I get the following error during linking of the debug version of my app.

inking... .\Debug\Solar.obj : error : Internal error during ReadSymbolTable ExceptionCode = C0000005 ExceptionFlags = 00000000 ExceptionAddress = 0043A725 NumberParameters = 00000002 ExceptionInformation[ 0] = 00000000 ExceptionInformation[ 1] = 00000018 CONTEXT: Eax = 00000000 Esp = 0012F3B4 Ebx = 4005686C Ebp = 40001A80 Ecx = 00000000 Esi = 40001A80 Edx = 00000000 Edi = 3FFF0000 Eip = 0043A725 EFlags = 00010246 SegCs = 0000001B SegDs = 00000023 SegSs = 00000023 SegEs = 00000023 SegFs = 0000003B SegGs = 00000000 Dr0 = 0012F3B4 Dr3 = 4005686C Dr1 = 40001A80 Dr6 = 00000000 Dr2 = 00000000 Dr7 = 00000000 Error executing link.exe. Tool execution canceled by user.

A second BATCH BUILD links the debug version without error.