rake rules with multiple prerequisites

J

Joel VanderWerf

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?
 
J

Jim Weirich

Joel said:
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.
 
J

Joel VanderWerf

Jim said:
Joel said:
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.

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:in `run'
/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 =.......
 
J

Jim Weirich

Joel said:
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
} }
 
J

Joel VanderWerf

Jim said:
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!
 
J

Joel VanderWerf

Joel said:
Jim said:
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!

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)
$
 
J

Joel VanderWerf

Joel said:
Joel said:
Jim said:
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!

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)
$

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top