Programming: May 2008 Archives

Here's the problem: you have a software package in a Subversion repository and you're using the GNU Autotools build-chain. You'd really like to have the revision number from subversion as the subminor revision in the PACKAGE_VERSION preprocessor object macro #define-d in config.h so that it automatically appears in your software.

Sounds easy enough, but it's both surprisingly difficult and surprisingly easy to achieve.

The problem is that the ways of achieving this I've found online embed something in the distribution files that require that the person building the software for installation has to have subversion or the Autotools or both installed in order to get a meaningful version number. That's a pain.

This solution requires only that the developer is working on a Unix-like system with sh, tr and a recent version of subversion installed.

The Solution

The solution is really this easy. Put the following in configure.ac:

define([svnversion], esyscmd([sh -c "svnversion|tr -d '\n'"]))dnl
AC_INIT([myprog], [0.1.svnversion], [myprog@example.com])

I also include a line like this so I can get the SVN version seperately:

AC_DEFINE(SVN_REVISION, "svnversion", [SVN Revision])

This assumes that you have a recent version of subversion installed with the svnversion program and you're developing on a Unix-like platform with sh and tr (which includes pretty well every flavour of Unix/Linux).

What this does is use m4, the macro language autoconf is built on, to define a macro, svnversion which uses the m4 function esyscmd (which calls a program and captures its stdout) to call the svnversion program and trim the bothersome trailing newline from its output using tr.

Now, one apparent shortcoming turns out to be a feature, not a bug. If you run autoreconf in a directory that's been modified from the repository version, the subminor revision number obtained from svnversion is non-numeric — it embeds information about the revisions used, not just the topmost revision — so you get a subminor revision like “42:43M”. This causes some difficulty building because the SVN_VERSION macro (if you include it), which should be be a valid C literal, is not an integer literal. So why is this a feature and not a bug? Because you shouldn't be building the software for distribution from a stale repository and this ensures that you're not doing that. In practice, it turns out to be very useful, rather than a pain, since it helps makes sure that make distcheck will fail if you've modified files and not done a svn commit and/or svn update.