Versioning Groups of Assemblies in sync
We often build groups of assemblies that all need to be marked with the same build number. Rather than having the build check out a whole bunch of AssemblyInfo.cs files from source control, set their file versions, and check them in, we use Visual Studio .NET's handy and (not widely known) Linked file feature to centralize the version information into a single file. Then the build only has to worry about updating the build number in one place. Here's how we do it.
Create a VersionInfo.cs file in a central place in your source tree.
---VersionInfo.cs---
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyFileVersion("1.0.0.123")]
In each of the projects that need to be versioned in sync, do the following:
- Remove the AssemblyFileVersion attribute from AssemblyInfo.cs so you don't have duplicates.
- Select Add Existing Item... to the project
- In the file-open dialog navigate up to the VersionInfo.cs file and click the little down arrow on the right side of the Open button and select Link File
This will write the following into your csproj file.
---MyProject1.csproj---
<VisualStudioProject>
<CSHARP>
<Files>
<Include>
<File
RelPath = "AssemblyInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "VersionInfo.cs"
Link = "..\VersionInfo.cs"
SubType = "Code"
BuildAction = "Compile"
/>
We use CruiseControl.NET, NAnt and NAntContrib's Visual SourceSafe tasks in our build process. Centralizing the versioning in a single VersionInfo.cs simplifies our build process and guarantees that all assemblies built at the same time will be marked with the same build number.
I did have to write a custom NAnt task that sets the version into the VersionInfo.cs file using a regular expression search and replace. The custom task is called like this:
<!-- label-to-apply property provided by CruiseControl.NET -->
<property name="label-to-apply" value="1.0.0.2"/>
:
<setversion file="VersionInfo.cs" fileVersion="${label-to-apply}"/>
Because I didn't find anything in NAnt or NAntContrib that did anything this simple for me, but maybe I just missed it. Anyway, this system is working quite nicely for us.