Welcome to Atalasoft Community Sign in | Help

Writing NAnt tasks with nested types

If you follow the Atalasoft Blogs by whatever means, and you're reading this, it's quite possible you've also read Jacob's blog post about extending NAnt.  If you haven't already, go check it out since he's covered a huge amount of ground related to what I'm going to show in this and subsequent posts.  In fact, I'll assume you've either read his post, or have some general idea about extending NAnt.

First, let me give some background on why I did this task.

At Atalasoft, our builds (built by Jacob) can run in parallel, but our .NET 2.0 and 64-bit builds cannot.  Before our installer is created we want the .NET 2.0 and 64-bit assemblies to have the same version numbers.  In order for that to happen, we introduced a dependency on the .NET 2.0 build by the 64-bit build (the version number is a guaranteed increasing, randomly generated number that, in the case of the 64-bit build, is obtained from the built .NET 2.0 assemblies).  For continuous integration, the version numbering is internal, and not as important to our engineering department.  With that in mind, it should be easy to break the dependency just for a nightly build, but how?  Enter ChangeSetId, LastChangeLabeller, and a special Atalasoft NAnt task called AtalaFileRegex (the "Atala" prefix is somewhat of a running joke internally, but helps future build engineers realize it's not a built-in task for NAnt, yet).  The ChangeSetId and LastChangeLabeller topics will be covered in another, upcoming post.

Now, you ask, why the FileRegex task when we're dealing with version numbers?  Ah, well, assembly version numbers are gotten a few different ways, and I wanted to alleviate a pain in our current build setup (preceding Jacob) where we use no less than 3 different approaches for updating version numbers for 3 different file types (AssemblyInfo.cs/.cpp, and any .rc files).  Enter AtalaFileRegex!

I imagined a task that I could give a FileSet to, a regular expression to match, and a string to replace that match with.  It's a sharp (no pun intended) tool that you can easily break things with if you're not careful, but incredibly powerful if you are careful!

So we set out to make our task (this is where you read Jacob's blog).  And in our shiny new task, we'd like to have a FileSet.  Easy, peasy!  In your public instance properties, make a field that is the NAnt.Core.Types.FileSet, and add some getter/setter code, like the following:

        /// <summary>
        /// All the matching files in this set will be updated according
        /// to the given regex/replace
        /// </summary>
        [StringValidator(AllowEmpty = false)]
        public FileSet RegexFileSet
            get { return _fileSet; }
            set { _fileSet = value; }

Notice I use the BuildElement() decorator here, instead of the already familiar TaskAttribute() decorator.  This means that it's a nested element.  The way you'd write your NAnt task with this is

<taskname taskattribute=something taskattribute2=somethingelse>

      <fileset basedir="${Dir.Source}">
        <include name="**\AssemblyInfo.cs" />
        <include name="**\AssemblyInfo.cpp" />


Sweet!  That was easy...

Next time I'll write a walk through on how to make your own type, and add that to your new task. 

Published Wednesday, May 07, 2008 4:04 PM by dterrell
Filed under: , ,


Thursday, May 08, 2008 7:33 AM by If you build it, They will come

# Extending NAnt with your own types

Last time I talked about how to nest existing elements in your custom NAnt tasks. Now that you've had

Thursday, May 08, 2008 12:50 PM by DotNetKicks.com

# Writing NAnt tasks with nested types

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Tuesday, May 13, 2008 8:59 PM by If you build it, They will come

# AtalaFileRegex: Putting it together

In my recent blog posts Writing NAnt tasks with nested types and Extending NAnt with your own type I

Anonymous comments are disabled