MSBuild – the voyage of the noob

I’ve been determined to have a play with build automation/continuous integration for a while now and just have always found something more fun to play with (ORM, MVC, etc.), though I know as the team where I work move forward, there needs to be some control and some vision on how all of our work should hang together. With that in mind, this weekend I started to read up on MSBuild (yup, I know there are other build managers out there, but I thought I’d start with that as my learning platform and move on from there).

Why do I need to modify the default build?

Why does anyone really I suppose, but I like what we get from it. As we move forward, the following I think will be useful to us:

automating unit test runs on successful builds

auto-deploying to our development server

minifying and concating javascript and css

ensuring coding style rules are followed (once I setup a set of company rules for us)

other things I haven’t imagined… there will be lots!

So where do I learn?

This was my first stumbling block. There are a lot of resources on MSBuild, and trudging through them to find the one that was right for my learning style and approach was a nightmare. I though to start out with the task that was at the forefront of my mind (concat/minify JS/CSS), but I just didn’t find any resources that were straightforward (my failing more than the resources available I’m sure!)

So what did I learn?

Firstly, a quick look at a post by Roy Osherove highlighted to me some of the tools available. I found two other visual build tools: MS Build Sidekick and MSBuild Explorer, both of which I found very useful in actually *seeing* the build process, but after a watch through those dnrTV vids, I though I’d try something straight forward – concating CSS files into a ‘deploy’ css.

Get into the .csproj file

MSBuild projects seem to be broken down quite succinctly into Targets, Tasks, Items, and Properties. For my particular need, I needed to look at Items and Targets.

The schema in MSBuild is incredibly rich – you get intellisense for the most part, but because you can define your own schema elements, you are never going to get 100% intellisense.

You have a number of different ‘DependsOn’ items (mostly defined in Microsoft.CSharp.targets file), so you can create tasks that hang onto some of these like so:

ConcatenateCSS;
$(BuildDependsOn);

This is telling the build process that I have a target called ‘ConcatenateCSS’ that should happen before the ‘BuildDependsOn’ target (roughly speaking!)

I then created that target with the following:

Which to me, looks bloody complex! I had to find some help on this one naturally. But essentially, we have created a target called ‘ConcatenateCSS’ which is going to execute before the build. We create an ItemGroup (and this is where the intellisense falls over) called ‘InFiles’, and we tell it to include everything ending in .css under the _assets\css folder (it seems the **\\*.css is the wildcard for recursion too, though I may be wrong on this!), and we want to exclude _assets\css\site.css (more on this in a sec).

I then send a message (which will be seen on ‘output’ during build which tells us it’s happening, and then use the combination of ‘ReadLinesFromFile’ and ‘WriteLinesToFile’. The %(InFiles.Identity) in the ReadLinesFromFile essentially turns this into a foreach loop, and Identity is one of the MSBuild defaults. So this is essentially, foreach of the files we’ve identified, output the contents to the ‘Lines’ variable/parameter. We then Write the whole lot back to our file using the @(Lines) variable.

Now, on each build, we generate a single css file (site.css) that our site can reference, but all edits go in via the broken files. Yes, there are more elegant ways to do this, and yes, I will likely do that in time, but I’ve made a start!

Where next?

I’d be lying if I said I could do the above without some solid examples and help, so the next steps for me are creating a solid understanding of the core concepts, playing with the tools, and looking to solve some of our core business issues as we move forward in order to take some of the human elements out of the build process. Obviously I have to investigate continuous integration and see where that all fits in too, but I’m happy with the start I’ve made.