Tuesday, January 20, 2009

MSBuild

Recently I posted a little about what I was calling the MSBuild Blahs, but probably more aptly titled “How I spent my Christmas Vacation”, and thought that it needed a follow up.

I continued to [1] twiddle with MSBuild until I was able to build something that met our needs for deployment – ok, should meet our needs. It goes into our development environment this week to work any kinks out.  I’ve definitely reached the ‘stage’ of learning that you could call (0ver) confidence with the language (is it a language, or a tool?).  You definitely have to change the way you think about accomplishing a task.

The push that got me ‘over the hump’ (besides just head banging)?  I read on a blog/MSDN post about XSLT being “the language of XML” and that “MSBuild was built on XML”, so therefore, the “idea of batching targets was taken from XSLT”.

Once I started thinking of everything as ‘batching’ targets, things started falling into place.   I found the post that helped me make the leap, by Jeff C. in the MSBuild v. Nant in the MSDN MSBuild forum.  Other helpful articles/posts I can be linked back to Sayed Ibrahim Hashimi or the MSBuild Team.

You can be successful with either tool.  If your just starting to develop your package and deployment scripts,  and target the Windows platform, then checkout MSBuild.   If you’ve got existing Nant scripts, target non-Windows platforms, or use open source tools, your likely to get better synergy out of using Nant.  With anything, your mileage may vary.

Con

Yes, I’m starting with the Cons, sue me.

  • Learning Curve – I personally had a higher learning curve for MSBuild than I did with Nant.  This is primarily due to lack of intuitiveness about batching, and transformations – two important concepts in MSBuild, which leads to…
  • Batching – this concept is reportedly borrowed from XSLT – really?  Because of the 30 developers I could probably name off the top of my head only two are what I’d call well versed in XSLT, and one is technically a manager now so I’m not sure he counts!  My XSLT skills are the equivalent of using flint to start a fire.  Yeah, I can do it but its probably going to take a while and I might even get hurt along the way.
  • Quirky Syntax – @ is for collections (ItemGroup), % is to address an item in that collection (ItemGroup) and $ is for addressing a value in a PropertyGroup.  Ok, then lets throw in that % is really like using an MSBuild transform which uses the syntax of @(property->’%(itemmetadata)’).  Do we need to say more? 
  • PropertyGroup trumps ItemGroup – if you happen to have an ItemGroup name that collides with a PropertyGroup, the PropertyGroup takes precedent, so you may spin wheels trying to figure out why that shiny new target you just built is spitting out the wrong information (or none at all).
  • ItemGroup Scope – I discovered that if I created an item group at a ‘global’ level called ‘Servers’ and then used the CreateItem task to create another group (or as an Output from a custom task) and it, too, was named ‘Servers’ then the values were appended to the global instance of ‘Servers’.  I’d like to be able to have variable declarations be aware of scope.   This cuts down on me having to be too creative on variable naming.

Pro

These Cons are offset by the absolute coolness of:

  • ItemMetadata – Creating an ItemGroup and then applying pieces of metadata as necessary to describe the item, thats nice.  The one thing is that there is no real enforcement of separation of ‘data’ and ‘logic’, which I’ve tried to do in our scripts.  I didn’t like that my item metadata (e.g. servers collection, or services collection) might be mixed in with the ‘logic’ of working with that collection.  This is true regardless of using MSBuild or Nant and both have constructs for allowing separation.
  • Batching – Ok, I know I listed this in ‘Cons’ column, but there is something to be said about eliminating foreach loops, which is what batching does, at the cost of some intuitiveness.  It did shorten my scripts somewhat.   Again, while nice, it requires getting over a learning curve that I’m not sure is worth it – maybe its more mentionable as a side effect?

At the end of the day, I’ve come to like MSBuild (yes, me eating crow), but things could definitely be done to help smooth out the learning curve. 

When asked why don’t you use batch files, PowerShell, etc…and why use MSBuild, or NAnt, at all, think of it like this:  MSBuild, or NAnt, is like your workflow runtime.  You get richer error handling, conditional decisions and some other gooey goodness that make it worth your while to adopt one, or the other.  Your Targets are then akin to activities.  If you want your activity to invoke a batch file, power shell script, vbscript, you absolutely can. 

Don’t forget to take advantage of the community supported MSBuild Task libraries out there.  There are three that I’ve found which are fairly solid – my only complaint is that the help files don’t always match up to the Task (e.g. property names), but a quick dive into Reflector and your good to go.  As always, if the shoe doesn’t fit, don’t hesitate to jump in and make a better shoe, err custom task.

 

[1] – twiddle, a polite term for a the Thunderdome style cage fight between myself and MSBuild.  Since I’m here to write this story, you know I’m clearly the winner.  Ignore the new eye patch, its just a flesh wound.