Thursday, September 27, 2012

Version strings in C or C++ code

This comes up every now and then and I have a hard time recalling the trick each time, so here goes: we have a revision control system (ex: git) and we'd like to include some useful version information (ex: the tag and hash via git describe) in our codebase for easy identification.  As such, we need to send that information down as a const string.

The simple way to do this is to escape the quotes around the string, something like:

VERSION=$(shell git describe)

CFLAGS += -DVERSION=\"$(VERSION)\"


Alternately, you can pass the raw output and stringify it via preprocessor macros as needed.  This is useful when you need both a string and raw version of something.  In the Makefile, that's just a matter of not putting the value in quotes.  For example:

VERSION=$(shell git describe)

CFLAGS+=-DVERSION=$(VERSION)


Now in our C or C++ code, we need a macro that stringifies this, however it needs to stringify the value rather than literal name of the VERSION:

#define _STR(s) # s
#define STR(s) _STR(s)

/* then, somewhere... */
const char *version_string = STR(VERSION);

printf("version: %s\n", version_string);


The _STR macro stringifies via the '#' operator while the STR macro ensures that _STR acts on the result of a macro rather than the literal macro name. A huge thanks to my friend Andrey Smirnov for teaching me this macro.