Monday, October 12, 2009

Generating Automatic Version Numbers

All of my projects use a special version numbering scheme - major.minor.revision.build - revision is the Subversion revision and build is a build number based on the current date. Whenever I build a project I want this version number to be updated automatically (if it has changed), but making this work using QMake isn't obvious ... but once you know how, it could be used for a variety of different uses.

I have a special Qt-based EXE project that generates the version number by creating a version.h file that looks something like this:

#ifndef VERSION_H
#define VERSION_H

namespace Version
{
static const int MAJOR = 1;
static const int MINOR = 2;
static const int REVISION = 2572;
static const int BUILD = 15280;
}

#endif // VERSION_H

I then #include this header where necessary. The EXE is passed the major/minor version number and the name of the output file (e.g. version.h) and it extracts the SVN revision and generates the special build number. I'll spare you the code - all you need to know is how to ensure this EXE is launched each time I build a project that requires it.

First, I use a subdirs project that contains the version-generator .pro file, ensuring I have a version.exe file to execute. Then, in my main apps .pro file I have something like this:

MAJOR = 1
MINOR = 2
VERSION_HEADER = ../version.h

versiontarget.target = $$VERSION_HEADER
versiontarget.commands = ../version/debug/version.exe $$MAJOR $$MINOR $$VERSION_HEADER
versiontarget.depends = FORCE

PRE_TARGETDEPS += $$VERSION_HEADER
QMAKE_EXTRA_TARGETS += versiontarget

The MAJOR and MINOR definitions are changed by hand when required, the rest is automatic. The key part here is the FORCE keyword - this is poorly (if at all?) documented and ensures that the QMAKE_EXTRA_TARGETS command works every time. Extending this scheme to run additional targets would be simple - create another 'target' type and add it to the list (for example, you may want to launch a shell script that generates some code, etc.)

Getting this to work involved a lot of StackOverflow/Qt-list posts - I hope you find it useful.

8 comments:

  1. thanks, this is extremely useful, I was wondering how to accomplish this :-)

    Chris

    ReplyDelete
  2. Thank you Rob! I was trying to do the exact same thing. Excellent work... :-)

    This is something that really should be better supported by qmake natively.

    ReplyDelete
  3. one small question, how do you know when to increase the build number since i am trying to use this code in a project with several folder and i would not like to update a build number if one folde that was not modify

    ReplyDelete
  4. I increase the major and minor versions by hand (by changing the main .pro file). The other version number components (the SVN revision and build date) are changed automatically but the new version.h file only gets created if the version has actually changed.

    If you like I can post the source to the Qt console app I use to generate the version number.

    ReplyDelete
  5. Hi, I am able to create the header file, but the problem is this.

    I have project that the struct looks like this.
    root
    -SerialCom
    --Dev1
    --Dev2
    -Ethernet
    --App1
    --App2

    so what i would like is if i modify the App1 but not Dev1 and Dev2 and so on the build number that is going to be update is just from App1 and no the others...

    Additional i am using mercurial(HG) for version control. so i have to add this line in the .pro file to ge the version.

    REV = $$system(hg id -n)

    well about the code it would be nice to see it, i also i can share mine if you want but i think is no the best solution.

    one more question where did you find information about this force i am trying to find something on internet but no results, or can you give some hints how to googled about this.

    And one more time, THANKS for such as useful utility. and as you said it can be used for other things(NICEEE ;))

    there is something else that came to my mind, what about when is a work group with the build number and the revision itself.

    I hope that this is not to crazy and you still would like to answer jejejeje..

    ReplyDelete
  6. Rob, can you post the Qt program you wrote to generate the header?

    Thanks,

    Jeff

    ReplyDelete
  7. Never mind, I found the version.cpp file... Thanks!

    Jeff

    ReplyDelete
  8. Good for you.
    Everyone else can find it here: http://qtcreator.blogspot.de/2010/01/code-to-generate-version-number-header.html

    ReplyDelete