如何在执行所有其他任务后运行Rake任务? (即Rake AfterBuild任务)

时间:2009-11-06 18:43:47

标签: ruby rake

我是Rake的新手并使用它来构建.net项目。我感兴趣的是有一个Summary任务,打印出已完成内容的摘要。我希望始终可以调用此任务,无论调用rake的任务是什么。

有没有一种简单的方法可以实现这一目标?

由于


更新问题,回复Patrick's answer我想要的是在所有其他任务之后运行一次的后续任务,所以我想要的输出是:

task :test1 do 
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

Rake::Task.tasks.each do |t|
    <Insert rake magic here>
#  t.enhance do 
#    puts 'after'
#  end
end

$ rake test1
test1
after

$rake test2
test2
after

$rake test1 test2  
test1
test2
after

如果

task :test3 =>[:test1, :test2]
   puts 'test3'
end

    $rake test3
test1
test2
test3
after

即使赏金消失了,任何进一步的帮助都非常赞赏。 (可悲的是,我不认为我可以提供另一笔赏金。)

7 个答案:

答案 0 :(得分:37)

你应该能够通过'增强'来实现这个目标:

Rake::Task["my_task"].enhance do
  Rake::Task["my_after_task"].invoke
end

这将导致在'my_task'之后调用'my_after_task'。

如果要将其应用于所有任务,只需遍历所有任务并为每个任务调用增强功能:

Rake::Task.tasks.each do |t| 
  t.enhance do 
    Rake::Task["my_after_task"].invoke
  end
end

完整的测试文件:

task :test1 do 
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

Rake::Task.tasks.each do |t|
  t.enhance do 
    puts 'after'
  end
end

输出:

$ rake test1
test1
after

$ rake test2
test2
after

答案 1 :(得分:11)

将此作为新答案发布,以保持另一个可用。这不太优雅,因为我必须深入了解Rake并手动更新任务列表,但它确实有效。

task :test1 do
  puts 'test1'
end

task :test2 do 
  puts 'test2'
end

task :after do
  puts 'after'
end

# top_level_tasks is't writable so we need to do this ugly
# instance_variable_set hack...
current_tasks =  Rake.application.top_level_tasks
current_tasks << :after
Rake.application.instance_variable_set(:@top_level_tasks, current_tasks)

输出:

$ rake test1
test1
after

$ rake test1 test2
test1
test2
after

答案 2 :(得分:10)

找到了这个使用Ruby方法here的简单优雅答案at_exit

值得注意的是,at_exit之后定义的方法将在每次调用rake脚本时运行,无论任务运行如何,或者是否运行任何任务。这包括运行rake -T(列出可用任务)。确保at_exit仅在前一个任务告知它时才执行任何操作。

rakefile.rb

desc "Lovely task a"
task :a do
  puts "a"
end

desc "Lovely task b"
task :b do
  puts "b"
end

task :cleanup do
  puts "cleanup"
end

at_exit { Rake::Task[:cleanup].invoke if $!.nil? }

$ rake a b
a
b
cleanup
$ rake -T
rake a # Lovely task a
rake b # Lovely task b
cleanup

如果您不想,也不需要让它运行任务。

at_exit do
  puts "cleanup"
end

或者让它运行方法

def on_exit_do_cleanup
  puts "cleanup"
end

at_exit { on_exit_do_cleanup }

您可能希望确保只有在任务实际运行时才进行清理,以便rake -T不会进行清理。

rakefile.rb

do_cleanup = false

desc "Lovely task a"
task :a do
  puts "a"
  do_cleanup = true
end

desc "Lovely task b"
task :b do
  puts "b"
  do_cleanup = true
end

task :cleanup do
  return unless $!.nil? # No cleanup on error
  return unless do_cleanup # No cleanup if flag is false
  puts "cleanup"
end

at_exit { Rake::Task[:cleanup].invoke }

答案 3 :(得分:4)

除了丑陋的Rake.application.instance_variable_set之外,你可以像这样增强命令行的最后一项任务:

  last_task = Rake.application.top_level_tasks.last
  Rake::Task[last_task].enhance do
    puts 'after'
  end

这应该完全符合你的需要!

答案 4 :(得分:4)

您可以使用Kernel.trap调用并附加到“Exit”信号。它将在正常和异常退出时触发。

把它放在你的rakefile中:

Kernel.trap("EXIT") do
  Rake::Task[:final].invoke
end

现在,只要你做出“最终”任务,它就会在程序的最后执行。无论如何。

task :final do
  puts "Hit return to continue..."
  STDIN.getc
end

答案 5 :(得分:1)

我不知道这是不是最好的方式,但它更简单:

完成所有“公共任务”总结称为实际任务的任务。

task :compile => :realcompile do
   summary stuff
end

答案 6 :(得分:0)

如果有人来到这里寻找如何在所有其他任务(例如,特殊的环境加载任务)之前运行任务,你仍然可以使用相同的增强方法,除了第一个争论:

task :environment do
  env = (ENV['RACK_ENV'] || 'production').downcase
  # do things before other tasks
end

# run environment task before all tasks for setup
Rake::Task.tasks.each do |t|
  next if t.name == 'environment'
  t.enhance [:environment]
end