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:
Using the standard UNIX what(1) command to determine the version of an executable:
% what monet monet R2.0 Baselevel 1 Thu Feb 11 17:33:23 EST 1993 |
Adding a “what version?” command-line option to the executable itself:
% monet -Ver monet R2.0 Baselevel 1 (Thu Feb 11 17:33:23 EST 1993) |
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.
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:
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. |
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. |
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);
}
}
|