Anyone with experience at a software shop that goes through some kind of release cycle of client software will indubitably have some form of automated build process (at least one can hope this is the case!).  In my experience one of the most monotonous and time consuming tasks is working on a build script that nobody cares enough about to develop or debug properly.  I've found that even the most seasoned of developer will revert to the debugging techniques analogous to alert('this should never happen!');.  This technique usually involves a developer making a change, committing to SCM (your build script IS in SCM right?) and forcing a build.

Would you normally develop software in this manner?  Of course not.  Why is a build script so much different from any other system or process you develop?  In modern monolithic IDE's like Visual Studio, it's easy to take for granted how much our environment is already honed to increase a developer's productivity.  As part of my effort creating a Deployment Pipeline I quickly discovered I needed a good way to develop NAnt scripts.  With a little research I've found an easy recipe to develop sustainable build scripts.

There are some key points I want to discuss in a series of posts.  For this post I'll only go over point 1.

  1. Take the time to setup your IDE
  2. Using NAntAddin (TODO)
  3. Isolate environment specific variables so you can develop your script without testing on your build server (TODO)

Setting up your Visual Studio 2010 IDE

Install NAnt

NAnt is one of those wonderful pieces of software that require nearly no deployment what-so-ever (which is nice for a deployment-centric technology!).  Just extract and use.  If you've never heard of NAnt then you'll want to check out the site and start reading up, because it's the tool I use for all the following build scripts.  Download the latest stable version of NAnt (0.91 alpha2 as of this writing) and extract it to a directory your choosing (i.e. C:\nant-0.91-alpha2\).  Add the \bin path to your PATH system environment build for ease of use at the command line.

Install NAntContrib

NAntContrib is a wonderful toolkit of NAnt extensions that are invaluable for build engineering.  You can find out all about it at their website, but the main task I use from this project is the msbuild task.  If you want to use the latest .NET framework you'll have to get one of the nightly builds.  There are several different ways to install and use NAntContrib.  I prefer to unpack the libraries into the "<nant>\bin\tasks" directory as mentioned in their readme.  This allows you to use all its functionality without explicity referencing it in each script.  However, for the sake of clarity I'll explicitly load the library in my sample script.

Enable IntelliSense for NAnt Scripts

One of the greatest things that about developing in a modern IDE is IntelliSense.  Visual Studio easily extends this capability to XML files by allowing you to copy an XML Schema Definition (XSD) file to your Visual Studio XSD folder (usually in the following location: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Xml\Schemas).  For my NAnt deployment this located at the following location, C:\nant-0.91-alpha2\schema\nant.xsd.

Enable IntelliSense for NAntContrib tasks

In order to get NAntContrib "extra goodness for NAnt" (as their project description gloats), you will want to generate a combined XSD for both NAnt and NAntContrib and use this as the namespace of your root build script <project> node.  Thankfully, NAntContrib makes this easy with the following script.

<?xml version="1.0" encoding="utf-8" ?>
<project name="Foo" default="build" xmlns="http://nant.sourceforge.net/release/0.91-alpha2/nant-0.91-alpha2.xsd-and-nantcontrib-0.85.xsd">
 <property name="NAntContrib" value="C:\Users\Sean\Documents\Source\seandev\blog\building sustainable nant scripts\lib\nantcontrib-0.85\bin" />
 <loadtasks assembly="${NAntContrib}\NAnt.Contrib.Tasks.dll" />
 <target name="go">
  <nantschema output="nant-0.91-alpha2-and-nantcontrib-0.85.xsd" target-ns="http://nant.sourceforge.net/release/0.91-alpha2/nant-0.91-alpha2.xsd-and-nantcontrib-0.85.xsd"/>
 </target>
</project>

I gave it a new namespace name in order to avoid ambiguity with scripts that may reference the plain old NAnt XSD, but this is really a matter of personal taste.  Once this target successfully runs it will create an XSD in the same directory as the build script.  Copy this file into your Visual Studio XSD folder as outlined above for the plain old NAnt XSD.  Restart Visual Studio.

From now on whenever you build a build script you'll want to reference the namespace by the name you assigned above.  Now you should be able to view all the NAnt and NAntContrib targets when you're working on your build scripts.