🕷 zenspider.com

by ryan davis



sitemap
Looking for the Ruby Quickref?

Simulating .PHONY in Rake

Published 2012-01-09 @ 16:55

Tagged ruby, thoughts

Makefiles have a construct called .PHONY. You declare your task a non-filesystem based task like so:

1
.PHONY: mytask

and then make knows that it shouldn’t force your task to run just because “mytask” doesn’t exist in the filesystem.

Rake doesn’t bother with such nonsense. It doesn’t assume that all tasks map to the filesystem. That’s great. What’s not great is that it does assume that if your file task has non-file-task dependencies, that they should probably rebuild even if those tasks have run. The problem code looks like:

1
2
3
def out_of_date?(stamp) # on FileTask
  @prerequisites.any? { |n| application[n, @scope].timestamp > stamp}
end

In my case, I was trying to intelligently hook up some generated files to isolate so they could access their compiler:

1
2
file "lib/ruby18_parser.rb" => :isolate
file "lib/ruby19_parser.rb" => :isolate

The problem is that :isolate is a regular task, and they calculate their dependencies like so:

1
2
3
def timestamp # on Task
  prerequisite_tasks.collect { |pre| pre.timestamp }.max || Time.now
end

:isolate doesn’t have any prerequisites, so it falls back to Time.now. This is wrong in my case, as it forces my parser files to regenerate every time.

What I need is a prerequisite that fixes this with a timestamp earlier than my files:

1
2
3
4
5
def (task(:phony)).timestamp # omg I love/hate this grammar construct
  Time.at 0
end

task :isolate => :phony

and everything is happy.

I’m going to officially ask that :phony gets added to rake so others can be spared this pain.