From: "James M. Lawrence" Date: 2008-09-25T09:18:49+09:00 Subject: Re: Rake dependencies unknown prior to running tasks Joe Wę—¦lfel wrote: > I didn't say what was being built couldn't be determined > programmatically. I said it couldn't be determined until certain > portions were already built. To build those things initial things I > need a build tool, such as Rake. If the suggestion is that I > shouldn't actually execute any Rake tasks until after I've determined > all possible tasks then the catch 22 your talking about actually > occurs. The only practical solution I've come up with so far is to > have Rake build the initial targets and then call itself again to > determine the rest of the dependency graph and build the remaining > targets. If there were a way to augment the initial dependency > graph dynamically then this wouldn't be necessary. I just don't > happen to know of one. If you really cannot know what is going to be built, for example if a program generates files whose names are taken from /dev/random and then other tasks depend on those files, then you are in a pickle. Normally this kind of thing is handled by 'import', but this assumes tasks can be determined (for example examining the makedepend output). What do you think of this: task :setup_a do puts "setup_a" end task :setup_b do puts "setup_b" end task :setup => [:setup_a, :setup_b] do puts "setup phase complete. defining new tasks..." task :main_a do puts "main_a" end task :main_b do puts "main_b" end puts "restarting..." throw :restart end task :main => [:main_a, :main_b] do puts "main phase complete." end task :main_a => :setup task :main_b => :setup task :default => :main do puts "all done." end % rake -f test/Rakefile.restart-flag (in /Users/jlawrence/work/rake) setup_a setup_b setup phase complete. defining new tasks... restarting... main_a main_b main phase complete. all done. I may be inflicting hardship on myself since this would complicate drake (http://drake.rubyforge.org), but anyway... This patch is for regular rake; the git branch is the same thing. % git clone git://github.com/quix/rake.git % cd rake % git checkout -b restart-flag origin/restart-flag diff --git a/lib/rake.rb b/lib/rake.rb index 7c84f57..3010261 100755 --- a/lib/rake.rb +++ b/lib/rake.rb @@ -560,8 +560,15 @@ module Rake # Invoke the task if it is needed. Prerequites are invoked first. def invoke(*args) - task_args = TaskArguments.new(arg_names, args) - invoke_with_call_chain(task_args, InvocationChain::EMPTY) + catch(:done) { + loop { + catch(:restart) { + task_args = TaskArguments.new(arg_names, args) + invoke_with_call_chain(task_args, InvocationChain::EMPTY) + throw :done + } + } + } end # Same as invoke, but explicitly pass a call chain to detect @@ -573,8 +580,8 @@ module Rake puts "** Invoke #{name} #{format_trace_flags}" end return if @already_invoked - @already_invoked = true invoke_prerequisites(task_args, new_chain) + @already_invoked = true execute(task_args) if needed? end end -- Posted via http://www.ruby-forum.com/.