Chapter 16. Adding a Timestamp to an Executable

This chapter describes simple techniques for incorporating a “version string” and/or “timestamp” into a C-language compiled executable. This allows anyone (for example, a customer) to determine the exact version of a program by entering a simple shell command. The techniques described below support:

Once the particular version of the program is determined, you can use ClearCase commands to find a local copy, examine its config rec, and if appropriate, reconstruct the source configuration with which it was built. (Presumably, the local copy is a derived object that has been checked in as a version of an element.)

You can identify the appropriate derived object by attaching a ClearCase attribute with the version string to the checked-in executable, or you could simply rely on the timestamp and your ability to “what” the checked-in executable to find it.

Creating a `what' String

The what program searches for a null-terminated string that starts with a special four-character sequence:

@(#)

To include a “what string” in a C-language executable, define a global character-string variable. For example, these source statements would produce the two-line what listing above:

char *version_string = "@(#)monet R2.0 Baselevel 1";
char *version_time   = "@(#)Thu Feb 11 17:33:23 EST 1993;

As an alternative, you can generate the timestamp dynamically when the monet program is linked, using this procedure:

  1. Create a new source file, version_info.c, which contains the statements that define the “what” strings. But instead of hard-coding a date string, use a cpp(1) macro, DATE:

    In version_info.c:
    char *version_string = "@(#)monet R2.0 Baselevel 1";
    char *version_time = DATE;
    


    Note: The version_string could be generated dynamically, too (for example, with environment variables). But it is more likely that the project leader would manually edit this string's value before major builds.


  2. Revise your makefile so that before linking the executable, it compiles version_info.c. Use shell command substitution to dynamically incorporate the current time into the value for the DATE macro:

    SHELL = /bin/sh
    OTHER_OBJS = main.o cmd_line.o (and so on)
    monet: version_info.c $(OTHER_OBJS)
           cc -c -DDATE="\"@(#)`date`\"" version_info.c
           cc -o monet version_info.o $(OTHER_OBJS)
    

    A rebuild of monet will also be triggered if the version_string variable is edited manually in version_info.c.


    Note: If you use clearmake to build monet, you need not declare version_info.c as an explicit dependency.


Implementing a `-Ver' Option

You need not depend on the what command to extract version information from your executable. Instead, you can have the program itself output the information stored in the version_string and version_time variables. Just revise the source module that does command-line processing to support a “what version” option (for example, - Ver):

#include <stdio.h>
main(argc,argv)
    int argc;
    char **argv;
{
/*
 * implement -Ver option
 */
    if (argc > 1 && strcmp(argv[1],"-Ver") == 0) {
        extern char *version_string;
        extern char *version_time;
        /*
         * Print version info, skipping the "@(#)" characters
         */
        printf ("%s (%s)\n",
                    &version_string[4], &version_time[4]);
        exit(0);
    }
}