Build numbers in binaries using waf
My build system of choice these days for any C++ project is waf. One of
the things I always like havig is the build number included in the final
binary, so that with a simple ./binary --version
or even ./binary
the
version is printed that it was built from. This can make it much simpler to
debug any potential issues, especially if fixes may have already been made but
a bad binary was deployed.
Setup the wscript
Make sure that your wscript somewhere near the top contains the following:
APPNAME = 'myapp' VERSION = '0.0.0'
Then in your configure(cfg)
add the following:
cfg.env.VERSION = VERSION cfg.env.APPNAME = APPNAME git_version = try_git_version() if git_version: cfg.env.VERSION += '-' + git_version
The try_git_version()
function is fairly simple and looks like this:
def try_git_version(): import os import sys version = None try: version = os.popen('git describe --always --dirty --long').read().strip() except Exception as e: print e return version
It runs git describe --always --dirty --long
which will return something
along these lines: 401b85f-dirty
. If you have any annoted tags, it will
return the tag name as well.
If git
is not installed, or it is not a valid git
directory, then it will
simply return None
. At that point all we have to go on is the VERSION
variable set at the top of the wscript.
Now that we have our configuration environment set up with the VERSION
we
want to get that into a file that we can then include in our C++ source code.
Create a build_version.h.in
file
#ifndef BUILD_VERSION_H_IN_941AD1F24D0A9D #define BUILD_VERSION_H_IN_941AD1F24D0A9D char VERSION[] = "@VERSION@"; #endif /* BUILD_VERSION_H_IN_941AD1F24D0A9D */
Add the following to build(ctx)
ctx(features='subst', source='build_version.h.in', target='build_version.h', VERSION = ctx.env['VERSION'], )
This uses the substitution feature to transform build_version.h.in
into
build_version.h
, while inserting the version into the file.
Include build_version.h
in your source code
#include "build_version.h"
And add something along these lines to your main()
:
std::cerr << "Version: " << VERSION << std::endl;
This will print out the VERSION
that has been stored in build_version.h
.
Full example
Check out my mdns-announce project on Github for an example of how this is implemented.