posted on Thursday, October 14, 2004 7:22 AM
by
stombeur
CruiseControl.NET and MSBuild
Hi all,
This is my first post to this blog, and I wanted to make it a more memorable one than 'this is a test' ;-)
This blog is (among other more worldly things I hope) going to be about automated builds. I'm currently working on a project that is in a proof-of-concept stage and is using Visual Studio 2005 Beta 1 and, by extension, the version of MSBuild that comes with it (v2.0.40607.16). In itself, that's not that unusual, but we also started out with the idea of automating builds and incorporating a number of good software practices or concepts in the build process (unit testing, static analysis, outputting reports to developers etc...).
If you start looking around the web for an automated build solution for .NET that can also function apart from Visual Studio, you'll probably end up with a combination of NAnt on the one side and CruiseControl.NET, Hippo.NET or Draco.NET on the other side. NAnt is the answer to scripting the real work behind your build process, and the other tools provide you with (a.o.) a way to schedule those builds (or execute on-demand builds) and a nice overview of past and current build results and reports.
What you don't get is a way to combine one of these tools with MSBuild. Of course, you can do this with NAnt by using the <exec> task to start msbuild.exe, but I wanted to cut out the middle man. Note: I do NOT want to start a religious war here and i don't consider MSBuild to be better than NAnt (or vice versa). Let's just say I wanted to make it more challenging by veering away from the path most travelled :-).
So here's a short overview and a sample of my experiences with running CruiseControl.NET (ccnet for short) with MSBuild instead of NAnt.
First of all, ccnet uses an xml configuration file to drive the build process: ccnet.config. This file is included in every 'server' folder in your ccnet setup. Next, it has a mechanism called 'builders' that delegate the actual build process to a more specialized tool. The <build> node in the ccnet.config xml file will be used to drive the builder.
Out of the box, a builder for NAnt (if you download the source, look for a file called NAntBuilder.cs) is included. When you look at the code, you'll see it's fairly easy to replace the arguments needed to run nant.exe with those needed to run msbuild.exe and hey-presto! - MSBuilder.cs is born.
The first thing you'll notice in the bowels of ccnet is that it uses a component called Exortech.Reflector to map builder properties onto xml. This means that you can decorate .NET properties with attributes that declare which xml nodes are going to be used to fill the properties with data.
This code:
[ReflectorProperty("buildArgs", Required = false)]
public string BuildArgs;
Will be filled in by the <buildargs> node in the following xml:
<build type="msbuild">
<executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.40607\MSBuild.exe</executable>
<baseDirectory>d:\temp\</baseDirectory>
<buildArgs>@mybuild.response</buildArgs>
<buildFile>mybuild.proj</buildFile>
<targetList>
<target>Build</target>
</targetList>
<buildTimeoutSeconds>300</buildTimeoutSeconds>
</build>
What you basically have to do is figure out what information you need to pass onto the msbuild executable, translate this into appropriate xml, and provide properties in the 'builder' that read the xml.
Download the MSBuilder.cs file here.
The way you get ccnet to use your custom builder is either by adding it to the ccnet source code and rebuilding it, or by building it into a plugin. You can create a plugin as follows:
- create a VS.NET 2003(!) library project
- add your custom builder to the project
- add the appropriate references (exortech reflector and a number of 'core' ccnet dlls)
- name the output of the project 'ccnet.<insert name here>.plugin.dll
- place the plugin dll in the 'server' folder of your ccnet project
Next, you can replace the standard <build> node in the ccnet.config file with the above 'msbuild' <build> node, write a small msbuild script ('.proj' file) and you're off.
In short:
1. build the custom 'builder' into a plugin dll
2. put the plugin dll in the ccnet server folder
3. put the custom xml in ccnet.config
4. point the custom xml to an appropriate msbuild script
5. force the ccnet project to build through its website (or schedule it) and watch the magic happen :-)
Coming up next on this blog:
- using the Microsoft SDC MSBuild tasks to do lots of stuff (source control, file management, nunit, fxcop, ...)
- creating custom MSBuild tasks yourself (or stealing them from NAnt) (it's not really stealing as long as you re-release them under the (L)GPL, is it ?)
- Whatever you want to hear, as long as its about MSBuild and/or CCNET