Rake Rocky III: Ant Attacks

Ant carries its own weight. In projects I’ve worked on where it’s used, I haven’t had to fiddle with it much. When I have, it’s mostly been copy and paste. I’ll show how Rake limits the need to copy. But first I say that making my first ant file from scratch was a bit of a challenge learning new syntax and semantics.

What’s that you say about the syntax? It’s just XML? Saying Ant is just XML is like saying that Lisp is just letters between parenthesis. In Lisp, only certain combinations of letters and parenthesis are going to be syntactically valid. Likewise only some combinations of elements and attributes in an XML document will be valid. (A description of what’s a syntactically correct is called a document type definition.) It’s still syntax just at the level of elements and attributes instead of letters and parenthesis. At this point, I know enough of Ant’s to get by, but not enough to have feel good.

I like Rake’s syntax because it really is just Ruby with some new methods and classes. This is only a plus if you already know Ruby. More than once I’ve shown Rake to people who’ve said, “well, I don’t know Ruby, so this isn’t going to help me. Why do you keep talking about Ruby anyway? Isn’t Perl good enough?”

The semantics of Ant was a little annoying too. The shell isn’t the best of interface, but at least I’m comfortable with the basics, rm $LIB/graph.jar. With Ant I needed to learn how to you say the same things in XML <delete file=”${lib.dir}/graph.jar”>. It’s not hard, but it’s work. With Rake, I write Ruby code when convenient and call the Shell when convenient. I know you can write Ant tasks in Java. I don’t know how. Perhaps you can even call the shell.

A real win for Rake is that it gives you a full language and where Ant only gives you a configuration file. What’s the difference? One of my projects has a bunch of packages. Each package has three targets. For example, you’ll have graph, graph-test, and run-graph-test. When you want to define a new target you copy the old target and rename things: vis, vis-test, and run-vis-test. Right or wrong, that’s how it’s done. In Ant, there’s lots of copying. Perhaps there’s a way to do this better. I don’t know.

And that’s the virtue of Rake. To avoid massive copying, I don’t need to know anything special. I just refactor the way one normally would in Ruby. Starting with the copying case:

task :graph => :init do |t|
  # stuff
end
task :graph_test => :graph do |t|
  # more stuff
end
task :run_graph_test => :graph_test do |t|
  # running stuff
end
task :vis => :init do |t|
  # stuff
end
task :vis_test => :graph do |t|
  # more stuff
end
task :run_vis_test => :graph_test do |t|
  # running stuff
end

we factor out repetition into a generator method:

class Symbol
  def + s
    (to_s + s.to_s).to_sym
  end
end
def regular_tasks basic
  test = basic + :_test
  run = :run_ + test
  task basic => :init do |t|
    # stuff
  end
  task test => basic do |t|
    # more stuff
  end
  task run => test do |t|
    # running stuff
  end
end
regular_tasks :graph
regular_tasks :vis

Abstraction at its finest. Next time we’ll consider the menace that is Make.