Builds and Build Scripts
Currently, I’m using BAT files for my build automation. Over the years, I’ve been pretty happy with BAT files for this purpose. Microsoft has done a very good job of improving the capability of the command language over the years. Recently, though, I’ve been bumping into the limitations of BAT files.
My main problem is the weak support for variables. I use Environment variables and SET for script variables. In most use, it works great. Since each invocation of a BAT file gets its own Environment, new variables are automatically “local” to that file; this makes structured programming easy, as long as you don’t mind each subroutine being in a separate file (I don’t). However, global state management is extremely difficult.
So, I’ve been looking for an alternative.
One obvious choice would be vbscript or javascript, using Windows Scripting Host. After all, it was built for scripting, right? I tried this years ago, when WSH first came out. I learned that both vbscript and javascript are horrible programming languages (hence the move at Microsoft from ASP (vbs, js) to ASP.NET (c#, vb). The scripts were only marginally more maintainable than Perl (my first build scripting language, 10 years ago).
My next choice was PowerShell. I’ve been intrigued by PowerShell since I first saw it at PDC two years ago (when it was still called “Monad”). The idea of seamlessly calling into the .NET library is compelling. Reality turned out to be a different story. While I’m sure that PowerShell makes doing routine WMI or ADSI automation easy (the interfaces in .NET for these are horrible), batch-style automation (where you are automating the execution of programs themselves) is terrible. I found myself repeatedly calling directly into .NET to do things that should have been built into the scripting language (like changing the current directory). It was slow, slow going. When I finally hit a wall, unable to figure out how to do what should have been a simple task, I gave up.
I decided to try Ruby. Now, as some of you know, I looked at Ruby for scripting way back in the ‘90s when scripting (around Python back then) was just heating up. I was looking for an alternative for Perl (sound familiar?), but didn’t like the arcane syntax of Python. Ruby looked promising, but since there wasn’t a community of any size around it, I abandoned it as an alternative. A decade can make a big difference. Thanks to Ruby on Rails, its now (in my opinion) hotter than Python. I did a quick check on capabilities, and it looked like I could easily do with Ruby what I couldn’t figure out how to do in PowerShell. I decided to give it a try.
Sure enough, in less time than I spent with PowerShell, I was able to get a couple of my BAT scripts coverted to Ruby. As an aside, I’m using Ruby in Steel as my development environment. It’s great: it allows me to do my work right in Visual Studio 2005, with syntax highlighting, Intellisense, and integrated debugging.
The only real problem I was running into was Ruby’s syntax. Ruby is definitely not in the “Algol” family of languages like C, C++, Java, and C#. I was handling the simple stuff easily, but the more complex stuff was sailing over my head. The books I had (O’Reilly’s Learning Ruby and Ruby in a Nutshell) were very little help. I decided to pick up a couple of other books. Since the Ruby Cookbook was some help with my trial scripts, I picked it up as well as the “Ruby Bible”, Programming Ruby (the “pickaxe book”). I was shocked to discover the existence of a utility called Rake!
Rake is a Ruby-based Make utility. This intrigued me, so I did some research. Rake is a cross between Unix Make and Java’s Ant. With it, you can do dependency-style builds (like Make) or task-style builds (like Ant or NAnt). The beauty of it is that the build scripts are still just Ruby!
I’m a big fan of the task-style build process used by NAnt, but I don’t like the fact that the input file is XML. XML is just not suited for process-based programming, such as build scripts. It’se extremely difficult to read and maintain. Rake lets me build tasks and task dependencies, just like NAnt, but each step is procedural, not just a list of XML elements. As an added bonus, I get the full power of Ruby to accomplish what I need to do. Remember that the thing that got me down this path in the first place was the limitations of BAT files.
The outcome of all this is, first, that I’ll be giving Rake a try for build automation (and I have high hopes). Secondly, I’m intrigued by Ruby’s capabilities for creating DSL’s (Domain Specific Languages). DSL’s are hot right now. .NET’s LINQ is an interesting example of a DSL. The problem with LINQ is that it required changing the compiler to support it (due to the syntactic limitations of C#). Ruby’s flexible syntax makes implementing a usable DSL possible without changing the interpreter. I’m starting to think that this will be the ultimate advancement that Ruby brings to general programming.
As usual, this ability is not new. Stack based programming languages, like Forth and (yes) Postscript, have had this capability for years (or decades!), but stack-based programming languages have their own problems. Having similar capabilities in a more “traditional”, object oriented language is refreshing.
Now, I’m off to the store, to buy yet more Ruby books
…
8/12/2007 9:58:42 AM (Pacific Daylight Time, UTC-07:00)
development