- Authentication, authorization and impersonation in WCF: WCF Training Kit (Safari Books Online)
- Herb Sutter: Writing modern C++ code: how C++ has evolved over the years (video from the //build/ event)
- Active, dormant and tombstoned apps: Multithreading in Mango
Monday, 31 October 2011
Currently Reading or Watching…
Sunday, 23 October 2011
Current Reading About Hedging
Where to invest in case of a catastrophe?
If you don’t own gold, now is a good time to buy
Saturday, 15 October 2011
TeamCity, msbuild and Version Numbers
How to automatically set all your solution’s projects to the same version number with msbuild and TeamCity?
We have a number of solutions mixing native and managed projects.
The mechanism we use to ensure all DLLs and EXEs have the same version number relies on modifying 2 files:
- A VersionInfo.h file for native projects
- A VersionInfo.cs file for managed projects
The .h file contains something like this:
#define PROJECT_VERSION 3,9,0,1234
#define PROJECT_VERSION_STR “3.9.0.1234”
All native projects in the solution have a resource file (.rc) that includes this unique VersionInfo.h. This is how the exe/dll obtain their version info.
On the .NET side, the VersionInfo.cs file contains:
[assembly: Assemblyversion(“3.9.0.1234”)]
[assembly: AssemblyFileversion(“3.9.0.1234”)]
All managed projects in the solution compile this VersionInfo.cs file (using a soft link, no duplication necessary).
So all we have to do in order to ensure that the 30+ binaries have exactly the same version number is to get our build script to modify the .h and the .cs just before building the solution.
Sounds easy!
Then there is the question of where to store the “3.9.0.1234” version. It should be in one single place of course. An obvious choice seems to be the TeamCity build number.
From Major.Minor.Build.Revision, we can set Major.Minor.Build by hand in TeamCity and have the Revision set automatically to the current SVN revision number, which is a handy way to relate builds to SVN revisions.
In the TeamCity project settings, the build number format field looks like this:
3.9.0.%build.vcs.number.MyProject_SVN_Root%
Then within our msbuild XML file we refer to the build number set in TeamCity like this:
$(BUILD_NUMBER)
The following msbuild lines update the version number stored in the VersionInfo.cs.
<FileUpdateFiles Files="VersionInfo.cs"Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"ReplacementText="$(BUILD_NUMBER)"/>
This regex does wonders to replace “1.2.3.4” with “3.9.0.1234”. But now, more tricky: when doing the string replace in VersionInfo.h (it’s always the native projects that cause trouble
), how do you replace
#define PROJECT_VERSION 1,2,3,4
with
#define PROJECT_VERSION 3,9,0,1234
given the string in $(BUILD_NUMBER) “3.9.0.1234”.
Can’t do anything a bit subtle with msbuild without having to download and install third-party tasks… So I’m currently looking into the TextString task from the MsBuild Extension Pack to tokenise the version string and then concatenate it back to the appropriate format. It’s all a bit complicated, there must be an easier way to do this…
Update (16/10/2011):
It’s actually not that bad, here is the code that formats $(BUILD_NUMBER) and updates the .h /.cs VersionInfo files.
<TextString TaskAction="Replace"OldString="$(BUILD_NUMBER)"OldValue="."NewValue=","><Output PropertyName="FormattedBuildNumber"TaskParameter="NewString"/></TextString><Message Text="Replacing version in VersionInfo.h with $(FormattedBuildNumber) and $(BUILD_NUMBER)"></Message><FileUpdateFiles Files="VersionInfo.h"Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"ReplacementText="$(BUILD_NUMBER)"/><FileUpdateFiles Files="VersionInfo.h"Regex="(\d+)\,(\d+)\,(\d+)\,(\d+)"ReplacementText="$(FormattedBuildNumber)"/><Message Text="Replacing version in VersionInfo.cs with $(BUILD_NUMBER)"></Message><FileUpdateFiles Files="VersionInfo.cs"Regex="(\d+)\.(\d+)\.(\d+)\.(\d+)"ReplacementText="$(BUILD_NUMBER)"/>
Monday, 3 October 2011
Getting Ready For FOWA London 2011
This is the schedule for tomorrow’s first day of FOWA (Forum of Web Apps) at the Brewery between Shoreditch and Whitechapel.
