typedef int (*funcptr)();

An engineers technical notebook

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.