Monday, 13 April 2009

Using Subversion Revision as the AssemblyVersion - Revisited

I've been using MSBuild tasks for a while to automate the generation of an AssemblyInfo.cs file with an AssemblyVersion that matches the current Subversion revision (commit number). See my prior post here. But, I've had mixed success with that approach and this posting is about using the Tortoise SubWCRev.exe utility that I hope will be more appropriate to open source projects.

The Need
  • Automate the file and assembly version numbers to use the Subversion revision number for the revion number in '...'.
  • Make the project configuration visible in the Visual Studio 2008 UI.
  • Suitable for debugging by typical developers using the VS2008 UI.
  • Project compilation without third party application installation.

The Problem

The MSBuild community task approach works but its configuration is obfuscated from the typical software developer user. It requires all users to have the MSBuild community tasks installed on the developer's (user) PC. That alone is not the 'obfuscation', thing is that if a user tries to build the project on a PC that does not have the MSBuild communicaty tasks intalled they are given an error that cannot be fixed withing the Visual Studio 2005/2008 UI that they are using. This is the critical 'usability' issue that I have found.

It has not been such a problem for commercial use as a software devs are resolved early and only once on each developer box and probably documented for future developement or maintenance.

But I have found it to be a big inhibitor for open source software users. The code cannot just be download and compiled without either reading all the documentation to find such details (a deoderant ... it ought to be self evident or, better still ... just work). It means that if you have many users you will incur a significant support cost or the inhitor will reduce user product acceptance. In other words ... ungood.

The Solution

After much googling I came across Bruce Boughton's blog showing how to use the TortoiseSVN SubWCRev.exe utility in a pre-build event. His solution did require a little pocking around in the Visual Studio project file and also required TortoiseSVN to be installed on the PC. I've adapted it a bit here is my solution:

  1. Add the existing AssemblyInfo.cs file to Subversion's ignore list. This file will be replaced by the auto generated file later.
  2. Copy your existing AssemblyInfo.cs file to a file named AssemblyInfo_temp.cs. This will become the source file used by the auto generator. Move this new file into the Properties folder by drag and drop in VS Solution Explorer pane.
  3. In the new AssemblyInfo_temp.cs file add required SubWCRev.exe keywords. We want to set the version revision so change your [assembly : AssemblyVersion("1.0.0.0")] to [assembly : AssemblyVersion("1.0.0.$WCREV$")]. If you want the FileVersion to be the same, delete the FileVersion entry.
  4. Copy the TortoiseSVN SubWCRev.exe file into your source tree. I keep a Lib folder in the root (trunk) of all my project source folders. In this case I copy the file to Lib\TortoiseSVN\SubWCRev.exe to make it clear it is a TortoiseSVN file. This way anybody can download the project and compile without the need to install TortoiseSVN (although anybody using Subversion should anyway).
  5. Now add as a project pre-build event: $(SolutionDir)..\Lib\TortoiseSVN\subwcrev.exe $(ProjectDir). $(ProjectDir)Properties\AssemblyInfo.cs.tmpl $(ProjectDir)Properties\AssemblyInfo.cs.
Done. This solution does require copying a TortoiseSVN file into your source tree. TortoiseSVN is an open source project, check its license to be sure you can use it. Otherwise install TortoiseSVN and reference the installed file.

12 comments:

Nalle said...

Great solution, thanks!

xeno.by said...

After using your magic idea in my several OSS projects, I've augmented it a bit:

rem Synchronize assembly build number with SVN revision
"$(ProjectDir)..\ThirdPartyStuff\TortoiseSVN\subwcrev.exe" "$(ProjectDir)." "$(ProjectDir)Properties\AssemblyInfo.template" "$(ProjectDir)Properties\AssemblyInfo.cs"

Upgrades:
1) Added "rem ..." so that VS tells the beholder why it's spitting weird lines into build log.
2) Put path to SVN's tool in quotes, so that the script works regardless of whitespaces in ProjectDir.
3) Replaced SolutionDir with ProjectDir in the path to the tool. Otherwise, the script fails when the project is included into several solutions that are located in different dirs.

vbscript2 said...

Works well! Thanks for posting.

Jeff said...

Why not put subwcrev.exe in your system path instead of placing in your source tree?

Rob Smyth said...

Hi Jeff,

I put stuff like NUnit etc in a project lib path so that they are all in the repository. It means that the code can be put on any box and build the same bin. Avoids the need to install stuff but much more importantly it gives a reproducable development environment.

For example, which version of NUnit was used for this project?

bstein said...

Thanks for the clear explanation. I've always wanted to do this

bstein said...

Thanks for the clear explanation. I've always wanted to do this

bstein said...

Thanks for the clear explanation. I've always wanted to do this

Tim said...

Nice solution!

An alternative I've used is the Happy Turtle SVN plug-in for the Build Version Increment VS Add-in (http://happyturtle.codeplex.com/)

The plus of this solution is that it can be setup up with out having to edit the build process. It will still allow other developers to build without needing to have the add-in installed, but it needs to be installed in order to get the version numbers inserted into builds.

Your solution is nice because after setting up the build process it is ready as soon as the code is checked out.

JMuller said...

Hi, im having a little problem to get this working on a Windows 7 32 bit machine. I have tried the 32 and 64 bit version of subwcrev.exe, but no luck. Any idea?

Im using the following build event:

"$(SolutionDir)\Solution Items\TortoiseSVN\subwcrev.exe" $(ProjectDir). $(ProjectDir)Properties\AssemblyInfo.cs.tpl $(ProjectDir)Properties\AssemblyInfo.cs

Rob Smyth said...

Hi JMuller,

You said:

Hi, im having a little problem to get this working on a Windows 7 32 bit machine.


It can be difficult to debug. What you do is look at your output text. This should show you the command line it generated. It will have the project path etc. Open up a command prompt window and past the command into there. Now you can debug it.

Try a 'dir' with the path to see if the path is correct, etc.

Good luck

Rob

Per Falk said...

Works great BUT it just prints the revision of the assembly file not the project.
If I commit changes to Program.cs and rebuild, the revision is the same in the assembly file. Is there a workaround to get the revision of the project folder?