Forum: Ruby rake rules with multiple prerequisites

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-19 23:48
(Received via mailing list)
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?
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-20 13:15
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 Weirich
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-20 19:05
(Received via mailing list)
Jim Weirich 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: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 =.......
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-20 19:45
Joel VanderWerf wrote:
> Jim Weirich 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 Weirich
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-20 20:08
(Received via mailing list)
Jim Weirich 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!
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-20 20:14
(Received via mailing list)
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)
$
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-21 07:04
(Received via mailing list)
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
10d4acbfdaccb4eee687a428ca00a5d8?d=identicon&s=25 Jim Weirich (weirich)
on 2006-03-21 07:52
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 Weirich
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-03-21 09:08
(Received via mailing list)
Jim Weirich wrote:
> -- Jim Weirich
>

Great! Just installed it and it works nicely. Thanks!
This topic is locked and can not be replied to.