Source-Level Versioning?

When you develop software, you’re always dealing with dependencies, and, if you’re lucky (or have made a quite enlightened choice of dependencies), you don’t have to worry too much about version numbers. But what if you do?

I won’t want to talk about dynamic link libraries (because I stopped coding for Windows a long time ago already) or shared object (because I don’t know everything there’s to know about them just yet) but only about source code.

Ideally, you’re working with a revision control software that makes versions and revisions quite explicit. Testing or checking out a file will usually give you some kind of version information message, such as ‘revision 42’ or ‘branch 2.1, v 1.54’ or whatever, so you know exactly what version, branch, etc., of source code you’re dealing with. However, you’re not always so lucky.

Consider the following file:

/* Copyright (C) 1991-1993,1995-2006,2007,2009 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#ifndef	_FEATURES_H
#define	_FEATURES_H	1

/* These are defined by the user (or the compiler)
   to specify the desired environment:

   __STRICT_ANSI__	ISO Standard C.
   _ISOC99_SOURCE	Extensions to ISO C89 from ISO C99.
   _POSIX_SOURCE	IEEE Std 1003.1.
...another 350-ish lines of code....

(it’s an excerpt from <features.h> found on my Ubuntu 10.04 box with gcc 4.4.3.) Can you spot what’s wrong with this header? It states the version of the GPL (for which I have mixed feelings—another story) but not the version of the library, nor the revision of this particular file. And while you can assume that between minor versions revisions are minor, and essentially harmless, they still can have the effect of breaking your code in unexpected ways, so versions are important.

Now, I don’t have any fool-proof solution to this problem just yet; but I’ll expose you what I have thought of so far (and feel free to comment or suggest different methods). I think that any source file should have a macro (despite macros being evil) that defines its version explicitly. Probably something reminiscent of include guards, something like __THIS_FILE_VERSION__ that would contain a numeric version such as 42 for 4.2, or maybe 421 for 4.2.1? That’s a possible solution given the severe limitations in the preprocessor’s ability to manipulate string-like symbols, but is it a sufficient solution?

Such #defines can be put manually (and thus error-pronely) into the files at release time, but it would be much better to have them automagically inserted by the revision control system at checkin/checkout. Say a full comment and a define like:

#ifndef __ATOMIC_TOASTER_H__
#define __ATOMIC_TOASTER_H__

/* file atomic-toaster.h
   checked out on 'Thu Aug 12 20:08:27 EDT 2010'
   by user 'steven'
   version 2.41 (branch 'xyz')


(Although, realistically, I would expect such a system to add doxygen-like tags to be somewhat robust to user edition. It’s rather hard to have your files not messed up by the editor: spaces changed to tabs, indentation changes, etc.) You could then test explicitly the version requirements:

#if defined(__ATOMIC_TOASTER_H_VERSION__) \
    && ( __ATOMIC_TOASTER_H_VERSION > 410 )
 #error dependency on atomic-toaster.h not met

* *

While I do not think that what I suggest is fool-proof, I believe that version-related compatibility issues can be partly enforced by external scripts (buildscripts, automake, and the like) but also at source-level using, maybe, language extensions in a design-by-contract mindset where part of the contract is the version numbers.

What’s your take on this? Suggestions? Ideas?

5 Responses to Source-Level Versioning?

  1. jsled says:

    Now, I don’t have any fool-proof solution to this problem just yet

    You don’t quite mention … what problem do you perceive, or trying to solve, exactly?

    • Steven Pigeon says:

      The problem I have is that you don’t always deal with code fresh out of a svn/git/etc (sometimes just getting people to use such tools as they should is a challenge). You may have code that comes from unidentified sources with unknown versions. In an ideal world, that would never happen. In the real world, however, you may end up with frankencode with parts coming from many different sources and half-baked configuration detection, something like a simple makefile that doesn’t do much instead of a real configuration script that detects the dependencies.

  2. Steven Pigeon says:

    If you want to comment on this blog, use a valid name and e-mail address.

  3. alexanderb says:

    there are frameworks that helps with lib versioning for .net applications:

  4. […] This post was mentioned on Twitter by Richard Laksana, Proggit Articles. Proggit Articles said: Source-Level Versioning: submitted by pdq [link] [comment] […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: