Rake rules with multiple prerequisites


#1

Is it possible to have a rule which has a prerequisite specified by a
proc and also a FileList? I can use several procs, as a workaround:

generic_files = [proc {“foo”}, proc {“bar”}, proc {“baz”}]
rule /^site_\w+/ => [
proc {|fn| site_cfg_file(fn)},
*generic_files
] do … end

But it would be nice to use a FileList. However, when I try

generic_files = FileList[“foo”, “bar”, “baz”]

rake says it doesn’t know how to build the task.

Is there a better way of doing this?


#2

Joel VanderWerf wrote:

Is it possible to have a rule which has a prerequisite specified by a
proc and also a FileList? I can use several procs, as a workaround:

generic_files = [proc {“foo”}, proc {“bar”}, proc {“baz”}]
rule /^site_\w+/ => [
proc {|fn| site_cfg_file(fn)},
*generic_files
] do … end

But it would be nice to use a FileList. However, when I try

generic_files = FileList[“foo”, “bar”, “baz”]

rake says it doesn’t know how to build the task.

Is there a better way of doing this?

Actually that should work. If rake is reporting that it cannot build
your task, then probably one of the prerequisites cannot be built.
Remember, your rule says that you can build a site_XXX file if the
following file (or rules to build the following files) exist:
site_cfg_file(fn), “foo”, “bar” and “baz”. I would check to see if
“foo”, “bar” and “baz” all exist.


– Jim W.


#3

Jim W. wrote:

Remember, your rule says that you can build a site_XXX file if the
following file (or rules to build the following files) exist:
site_cfg_file(fn), “foo”, “bar” and “baz”. I would check to see if
“foo”, “bar” and “baz” all exist.

Here’s what happens in this example:


generic_files = [proc {“foo”}, proc {“bar”}, proc {“baz”}]
#generic_files = FileList[“foo”, “bar”, “baz”]

rule /^site_\w+/ => [
proc {|fn| “__#{fn}”},
*generic_files
] do |t|
p t.name
end

task :__site_stuff

file “foo” do touch “foo”; end
file “bar” do touch “bar”; end
file “baz” do touch “baz”; end

As it is, it works:

$ rake site_stuff
(in /home/vjoel/ruby/misc/rake)
touch foo
touch bar
touch baz
“site_stuff”

But when I flip comments on the first two lines, I get:

$ rake site_stuff --trace
(in /home/vjoel/ruby/misc/rake)
rake aborted!
Don’t know how to build task ‘site_stuff’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake.rb:1287:in []' /usr/local/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake.rb:300:in[]’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake.rb:1719:in run' /usr/local/lib/ruby/gems/1.8/gems/rake-0.7.0/lib/rake.rb:1719:inrun’
/usr/local/lib/ruby/gems/1.8/gems/rake-0.7.0/bin/rake:7
/usr/local/bin/rake:18

Furthermore, if I comment out the proc:

proc {|fn| “__#{fn}”},

(still using the FileList) then rake goes into a tailspin:

$ rake site_stuff --trace
(in /home/vjoel/ruby/misc/rake)
rake aborted!
Rule Recursion Too Deep: [site_stuff => site_stuff => site_stuff =>
site_stuff =…


#4

Jim W. wrote:

The problem is that a plain string in the rule dependency list already
has a meaning: it is the file extension to be used in the name of the
source file for the target.

That’s what I was guessing. I’ll stick with procs, as you suggest below:

You can do this:

generic_files = FileList[“foo”, “bar”, “baz”].collect { |fn| lambda { fn
} }

Thanks!


#5

Joel VanderWerf wrote:

Jim W. wrote:

Remember, your rule says that you can build a site_XXX file if the
following file (or rules to build the following files) exist:
site_cfg_file(fn), “foo”, “bar” and “baz”. I would check to see if
“foo”, “bar” and “baz” all exist.

Here’s what happens in this example:

Oops. Sorry, I misread your example. I thought you were saying the
first example with the [proc{“foo”} … ] wasn’t working.

As I understand, what you would like is:

FileList[“foo”, … ]

to work as well.

The problem is that a plain string in the rule dependency list already
has a meaning: it is the file extension to be used in the name of the
source file for the target.

Furthermore, if I comment out the proc:

proc {|fn| “__#{fn}”},

(still using the FileList) then rake goes into a tailspin:

$ rake site_stuff --trace
(in /home/vjoel/ruby/misc/rake)
rake aborted!
Rule Recursion Too Deep: [site_stuff => site_stuff => site_stuff =>
site_stuff =…

The reason for the tail spin is that plain strings in the depedency list
for rules specifies file extensions. Since “site_stuff” has no
extension, it comes out unchanged in the dependency list. So it looks
like “site_stuff” depends on “site_stuff”, which is an circular
dependency.

You can do this:

generic_files = FileList[“foo”, “bar”, “baz”].collect { |fn| lambda { fn
} }


– Jim W.


#6

Joel VanderWerf wrote:

} }

Thanks!

On second thought… would it be possible for the proc to return a
FileList? It doesn’t seem to work now, but it would be a nice feature,
wouldn’t it?

$ cat rakefile
generic_files = proc {FileList[“foo”, “bar”, “baz”]}

rule /^site_\w+/ => [
proc {|fn| “__#{fn}”},
generic_files
] do |t|
p t.name
end

task :__site_stuff

file “foo” do touch “foo”; end
file “bar” do touch “bar”; end
file “baz” do touch “baz”; end

$ rake site_stuff
(in /home/vjoel/ruby/misc/rake)
rake aborted!
can’t convert Rake::FileList into String

(See full trace by running task with --trace)
$


#7

Joel VanderWerf wrote:

I found a small patch to make this example work,

Patch commited, test case added. The CVS head now has the change. You
can pick it up there or with:

gem install rake -s http://onestepback.org/betagems

The beta version is 0.7.0.1.

– Jim W.


#8

Jim W. wrote:

– Jim W.

Great! Just installed it and it works nicely. Thanks!


#9

Joel VanderWerf wrote:

} }
rule /^site_\w+/ => [
file “baz” do touch “baz”; end

$ rake site_stuff
(in /home/vjoel/ruby/misc/rake)
rake aborted!
can’t convert Rake::FileList into String

(See full trace by running task with --trace)
$

I found a small patch to make this example work, but of course it could
break something else. It seems like a natural thing to do: just flatten
the result of Rake::TaskManager#make_sources. Normally, the result would
be an array of strings, but this patch allows the translation procs to
return an array of filenames (or a FileList), rather than just one.

— rake.rb.bck 2006-03-20 22:00:12.000000000 -0800
+++ rake.rb 2006-03-20 22:00:12.000000000 -0800
@@ -1427,7 +1427,7 @@
else
fail “Don’t know how to handle rule dependent: #{ext.inspect}”
end

  •  }
    
  •  }.flatten
    

    end

    end