Live Fast, Code Hard, Die Young

Posts tagged ‘rake’

Rake tutorial

Rake is a great tool for creating build scripts even if you primarily develop on Windows and normally don’t use Ruby. In my last article I showed you how easy it is to set it up and get started. This time I am going to show you some more examples of how it can be used.

One thing I really like about Rake build scripts is that you can divide the work into many small tasks that can be developed and tested individually. When you got them all working it is just a matter of chaining them together using the Rake dependency mechanism and you’re done. This speeds up the development of build scripts quite a lot in my opinion.

Dependencies

So how do we setup dependencies between tasks in Rake? Well, it’s very easy. The Ruby language makes the syntax pretty sleek as well:

task :deploy do
  puts "Deploying..."
end

task :default => :deploy do
  puts "Done!"
end

In this example I have two tasks called deploy and default. The default task is dependent on deploy, which means that Rake will run the deploy task first and if it is successful it will continue with the default task. Pretty simple really.

You can also create empty tasks that simply depend on others. If you have more than one dependency just surround the tasks in brackets:

task :release => [:newversion, :deploy, :package]

By default Rake will run the default task. If you want Rake to run the release task instead you can do that:

C:\>rake release

Internal and public tasks

Once I started filling my build script with different tasks I ran into the situation where I wanted some tasks to be considered “internal”. I wanted to run them on my own for testing purposes, but they were not meant to be run by others. Instead I wanted to expose some sort of public API of tasks to be run from the command line to guide the user of what was possible. Rake has a way of handling this by decorating tasks with the special keyword “desc”. If you put a “desc” statement before the task it becomes the public documentation for that task, which to me is a great way of exposing it as part of a public API. This is how you do it:

desc "Perform a deploy and package a release version"
task :release => [:newversion, :deploy, :package]

To view a list of documented tasks you simply run Rake with the -T parameter. Here is an example of how this looks in one of my projects:

An example of output from Rake

This gives a nice list of all the commands available to a user that is new to my project. I like this a lot. 🙂

If you want a little bit more involved example you can take a look at the rakefile that I use for one of my projects. You can find it on GitHub.

Next time I will show you how to use Rake to build .NET projects. Stay tuned!

Advertisement

Using Rake in .NET projects

Last year I started using Rake for my .NET build scripts and it has been a quite pleasant experience that I wanted to share with you. “Hmmm, isn’t Rake one of those scary Ruby tools from the other side of the fence?” you might ask. Yes, indeed, it is a Ruby tool! Many good things have come from the Ruby community but sadly many .NET developers seem to be scared of even learning about them. “Yuck, strange Ruby stuff from the Linux world! I can’t use my .NET knowledge and that must be a bad thing, doesn’t it?” Well, that’s a shame! Rake can be used on Windows! And besides, I think it never hurts to at least dip a toe in the ocean once in a while and experience something different than the usual stuff you work with. When a tool helps you to accomplish things with simple elegancy it couldn’t hurt to try it.

So what is Rake?

Rake is a tool for creating build scripts. It is a modern variant of the good old Make tool where you describe different tasks and the dependencies between them. Each task is a series of Ruby statements to be executed when the task runs. The flexible nature of the Ruby language makes the task descriptions very brief and elegant.

Here is an example of a task called “deploy” that copies files:

task :deploy do
    src_path = File.join(BASE_PATH, "Output/bin/.")
    dest_path = File.join(BASE_PATH, "Deploy")
    puts "Deploying files..."
    FileUtils.cp_r src_path, dest_path
end

Why use Rake?

Okay, now we know a little about what Rake is, but you may still ask why do we need build scripts at all? Can’t we do everything with Visual Studio and some pre/post build commands?

Sure, we can do quite well with just Visual Studio for small projects. But in larger and more complex projects we often run into situations that require some form of automation and we don’t want to do them every time we build with VS. We need scripts to do various stuff such as deployment and packaging. Maybe we need to update some files with version info, compile an installation kit, upload it via ftp to a server and so on. I’m sure you can come up with a range of time consuming stuff you do on a regular basis that could be done more quickly and reliably by a script instead. The more you can automate the tedious repetitive tasks the more time you can spend doing things that really matter to the customer.

So why not use a simple bat file to run some commands? Yes, that’s one solution but bat files have some significant problems. One is that the error handling is quite cumbersome, you have to use goto statements for flow control and you cannot easily reuse functionality across different bat files. In my experience, as soon as the complexity of the build script rises it will quickly blow up in your face and become a maintenance nightmare. Another glaring omission is the ability to express dependencies between tasks. That is one pretty important thing for structuring a build script successfully that bat files lack.

But what about MSBuild? Wasn’t it created for this purpose exactly? Yes, I have used MSBuild (and before that NAnt) and it sort of works, but it feels very limited. Both MSBuild and NAnt are XML based and declarative. For me, declarative programming is not very intuitive (XSLT anyone?). I feel that I have to think harder before I get things right, instead of just describing what to do in the order I would do it when performing the task manually. With MSBuild I get these set of predefined tasks that I can use, but if they don’t do exactly what I want I’m out in the cold. To me, it feels much more powerful and flexible to write code to do what I want in a build task, and easier to understand and maintain too. Maybe it’s a matter of taste so ultimately you’ll have to decide for yourself…

Getting started

Many people are scared because they think it is difficult to setup Ruby and Rake on Windows. This is not the case. To get started you simply run the Ruby Installer that you can download here:

http://rubyinstaller.org/

After installing Ruby, hit the Windows key and type “Ruby”. Then click “Start Command Prompt with Ruby” in the list that appears. This will bring up a command window where you can use Ruby commands.

To install stuff in Ruby you use “gem”. To install Rake simply type:

C:\>gem install rake

Now you are good to go!

Your first script

By default Rake will look for a file called “rakefile.rb” so create a text file with that name and write your first build task like this:

task :default do
    puts "Wonderful world!"
end

Then launch this script like this:

C:\>rake
Wonderful world!

Pretty simple, wasn’t it?

In a future post I will show some more examples of what the build scripts may look like, so stay tuned!