Building’s the Foundation

Posted by – November 25, 2008


Let me get this off my chest. I think about Build Scripts all the time. I spent the better part of the first 6 months at my current job migrating old legacy .Net 1.1 web apps from  CVS to .Net 2.0 and Subversion. Part of that included migrating the projects from CVS to SVN, then taking the old projects and migrating those into our current directory structure for projects. After that, I had to template the config files and create build scripts that could build a local, test or production version of an app with a single command.

During the course of this, I used PowerShell, Ruby and of course, NAnt.

I found that, like many things, I was able to find some things I loved about all of them. And lots of things I hated about most of them. PowerShell, for one, has some great ideas in it. It’s truly a good idea. I love the idea of being able to leverage the .Net Framework from my scripts. It really is a good idea. But after the few scripts that I wrote in PowerShell, I don’t think that I could use it again. I found the syntax either annoying or clunky the whole time. Especially once I started writing the scripts in Ruby.

Now Ruby I have some experience in as I’ve done a bit of Rails development. Lots of the notations I like. I have some difficulty in using a dynamic language at times, most notably I find myself missing method signatures that are strongly typed. However, the annoyances are small, and mostly come in the form of me running into issues with working with the file system. I think those annoyances mostly come from me not fully understanding some of the intricacies of working with the filesystem on windows with ruby.

I find the biggest difference between the two is how easy it is to use Ruby from within a CygWin Bash shell. I’ve been a longtime linux user, and actually my first unix-like operating system that I used at home was FreeBSD. Because of FreeBSD, I was a long time user of tcsh. In fact, it was less than a year ago that I finally made the move over to bash. Either way, both of these shells provide power, ease of use and so many advantages that I can’t believe that Microsoft doesn’t have them in any of it’s shells. I mean seriously, how does anyone live without a searchable history in a command prompt?

And this brings us to NAnt. I was in love with NAnt when I first started. It was great to use, simple and it could do so much. But I started to find myself hitting situations where things would become very murky and difficult to keep track of where things were happening, especially when I tried to make things generic so they could be called in many places. For example, here is how a template file is expanded in our code:

   1: <target name="expand.template.file">
   2:     <copy file="${template.file}.template" tofile="${template.file}" overwrite="true">
   3:         <filterchain>
   4:             <replacetokens>
   5:                 ....lots of tokens...
   6:             </replacetokens>
   7:         </filterchain>
   8:     </copy>
   9: </target>


But where does ${template.file} get set? Why, the line before we call expand.template.file of course!

   1: <property name="template.file" value="${some.dir}\app.config"/>
   2: <call target="expand.template.file" />


I just find that this can be confusing, especially to newcomers who don’t know which targets act as functions. I know that you could do a search through the code and find it, but it’s just not as clean or explicit as something like:

   1: expandTemplate(filename)
   3: def expandTemplate(filename)
   4:     ...expand in here...
   5: end


So I think that you can see where I’m going with this. After a while of doing this, I started to think a lot about Rake. After all, I had used it in Rails projects previously. As you can tell, I’m quite a fan of Ruby. After a while, things began to cool off. I had gotten almost all of our projects converted and I wasn’t writing build files as much anymore. But I kept on thinking about it. Recently, I’ve been writing build files again. I’ve also been reading that I’m not the only person who feels this way.

I’ve noticed a few projects that seem to be reaching for what I want. There’s Boo Build System (and yes, it is shortened to BooBS. Nice work Ayende), PSake (which JP seems to have picked up) and then there’s Rake. Rake seems to be the only one that isn’t geared towards some sort of .Net problem (not that it can’t). It turns out that though there was a lot of hype around boo a while back, I just don’t think it’s something I’m up for learning just yet. And as for PSake, I downloaded the source and nothing against James (it’s not his fault, it’s the syntax!) I barely made it through the first PS1 file before my head hurt and I remembered why I stopped writing PowerShell scripts in the first place.

That leaves me with Rake. And it seems like I’m not the only one. The only difference is that I would absolutely love to see a Gem built with some custom .Net tasks for rake. This is something that I’ve been seriously contemplating putting some time into, but haven’t fully explored yet. Most notably, I would like to take the syntax of:

   1: require 'lib/nunittask'
   3: do |nunit|
   4:   nunit.library = "foo.dll"
   5: end


And replace it with something along the lines of:

   1: require 'lib/nunittask'
   3: nunit :test, :library => 'foo.dll', :depends => [:load_properties, :compile]


I get the feeling that this could be wrapped up in a function which could use Hash which could hide away the nastiness of do |task| block and take these scripts to an entirely new level. I’m not entirely sure how the naming would work, but I’m sure it would.

After writing this, I think I’m going to start taking a much closer look. Has anyone heard of anything like this in the works/already released?

1 Comment on Building’s the Foundation

  1. [...] NAnt completely removes the Don’t from Don’t Repeat Yourself, unless you want to lose readability like I stated this morning. [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>