Simply answering the title question, I've come up with a semi-professional solution (that may be of use to some people) that automatically tags my code with the git version tag I'm pointing to so I don't have to (remember to) manually update a version number each time I build. I currently work in a small group (< 5 developers), and our configuration management is still a work in progress. But until that matures, this is a solution that works for me.
High level view, these are the steps:
In more detail:
The Script
I currently use a 3 number versioning scheme,, major.minor.build, where build can possibly be a string (for example, v1.8.3b). Note, that using echo -e to print newlines works for me, but perhaps printf is the better option
# queries git for the version tag I'm currently pointed at. Throughout SO there
# are different versions of this command, but this one works for me. And in fact
# all my tags are annotated, so I could just use "git describe"
VERSION=`git describe --tags`
# replace all the '.' with ' ', then split the array based on the spaces.
# Obviously this will have its limitations if there are spaces in your
# version tag, or maybe even wildcard characters, but that should never
# be the case for me
VER_ARRAY=(${VERSION//./ })
# pull out the major, minor, and build components. These can be used to
# pre-processor check different versions of my code for certain compatibility,
# should the need arise
V_MAJOR=${VER_ARRAY[0]}
V_MINOR=$(VER_ARRAY[1]}
V_BUILD=${VER_ARRAY[2]}
# all of my build tags are preceded by a 'v', so remove that simply by taking
# the substring starting at position 1
V_MAJOR=${V_MAJOR:1}
# define the path and header file
VERSION_HEADER=./path/to/codeVer.h
# write these to file. > creates the file and >> appends to the file
echo -e "// Auto-generated version header on " `date` "\n\n" > $VERSION_HEADER
echo -e "#define MY_CODE_VERSION \""$VERSION"\"\n\n" >> $VERSION_HEADER
echo -e "#define MY_CODE_MAJOR "$V_MAJOR >> $VERSION_HEADER
echo -e "#define MY_CODE_MINOR "$V_MINOR >> $VERSION_HEADER
echo -e "#define MY_CODE_BUILD \""$V_BUILD"\"\n\n" >> $VERSION_HEADER
The makefile
At the top of my makefile, I have $(shell ./genVer.sh). This tells make to run a shell command, ./genVer.sh is the path and name of the script. A better way to do this would be to make a .PHONY target for the script, and then put that target as a prerequisite for the pertinent targets,, but I have a lot of targets and this was a one-liner catch all.
The code
Now, in all relevant source/header files, I simply have
#include "codeVer.h"
....
#ifndef MY_CODE_VERSION
// although if codeVer.h cannot be found we will get a fatal error before
// this warning
#warning "Unable to find code version, defaulting to v0.0.0"
#define MY_CODE_VERSION "v0.0.0"
#endif
Now any time I make, the current version is extracted, the header is generated, my code #includes the file, and I get the correct version number without doing any manual work. Note, this doesn't just work for the latest version, if you checkout an older tag, this will work as well (provided of course the changes implementing this were in that version).
This does have its drawbacks. Most notably
- You have to build something in order to get the version. I actually added
codeVer.h to the .gitignore list since I don't want it tracked in the repo. This means you could potentially hand your code off to someone with this file missing, and they won't know what version it is. But if they're using git (like they're supposed to be doing!) and they git pull/clone your stuff, all the tags will come with it anyway.
make clean also generates this file (which seems counter-intuitive), but if you did it the right way and used a .PHONY target as described above, that wouldn't be an issue.
- Probably others I'm not thinking about at the moment.