如何从Rake任务中运行Rake任务?

我有一个Rakefile,它以两种方式编译项目,根据全局变量$build_type,可以是:debug:release(结果在不同的目录中):

task :build => [:some_other_tasks] do
end

我想创建一个任务,编译项目的两个配置依次,像这样:

task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
# call task :build with all the tasks it depends on (?)
end
end

是否有一种方法可以像调用方法一样调用任务?或者我怎样才能实现类似的目标?

155231 次浏览
task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
Rake::Task["build"].execute
end
end

例如:

Rake::Task["db:migrate"].invoke
task :build_all do
[ :debug, :release ].each do |t|
$build_type = t
Rake::Task["build"].reenable
Rake::Task["build"].invoke
end
end

这应该能解决你的问题,我也需要一样的东西。

如果您需要将任务作为一个方法来执行,那么使用一个实际的方法如何?

task :build => [:some_other_tasks] do
build
end


task :build_all do
[:debug, :release].each { |t| build t }
end


def build(type = :debug)
# ...
end

如果你宁愿坚持rake的习惯用语,下面是你的可能性,从过去的答案汇编:

  • 这个函数总是执行任务,但是它不执行它的依赖项:

    Rake::Task["build"].execute
    
  • This one executes the dependencies, but it only executes the task if it has not already been invoked:

    Rake::Task["build"].invoke
    
  • This first resets the task's already_invoked state, allowing the task to then be executed again, dependencies and all:

    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
    
  • Note that dependencies already invoked are not automatically re-executed unless they are re-enabled. In Rake >= 10.3.2, you can use the following to re-enable those as well:

    Rake::Task["build"].all_prerequisite_tasks.each(&:reenable)
    

如果你想让每个任务在没有任何失败的情况下运行,你可以这样做:

task :build_all do
[:debug, :release].each do |t|
ts = 0
begin
Rake::Task["build"].invoke(t)
rescue
ts = 1
next
ensure
Rake::Task["build"].reenable # If you need to reenable
end
return ts # Return exit code 1 if any failed, 0 if all success
end
end
我建议不要创建一般的调试和发布任务,如果项目真的是被编译并导致文件。您应该使用file-tasks,这在您的示例中是非常可行的,正如您所述,您的输出将进入不同的目录。 假设你的项目只是编译一个test.c文件来输出/调试/测试。彻底/释放/测试。在GCC中,你可以像这样设置你的项目:

WAYS = ['debug', 'release']
FLAGS = {}
FLAGS['debug'] = '-g'
FLAGS['release'] = '-O'
def out_dir(way)
File.join('out', way)
end
def out_file(way)
File.join(out_dir(way), 'test.out')
end
WAYS.each do |way|
desc "create output directory for #{way}"
directory out_dir(way)


desc "build in the #{way}-way"
file out_file(way) => [out_dir(way), 'test.c'] do |t|
sh "gcc #{FLAGS[way]} -c test.c -o #{t.name}"
end
end
desc 'build all ways'
task :all => WAYS.map{|way|out_file(way)}


task :default => [:all]

这个设置可以这样使用:

rake all # (builds debug and release)
rake debug # (builds only debug)
rake release # (builds only release)

这比要求的要多一点,但显示了我的观点:

  1. 根据需要创建输出目录。
  2. 这些文件只在需要时重新编译(本例仅适用于最简单的test.c文件)。
  3. 如果您想要触发发布构建或调试构建,那么您手头已经有了所有任务。
  4. 此示例还包括一种定义调试和发布构建之间的小差异的方法。
  5. 不需要重新启用使用全局变量参数化的构建任务,因为现在不同的构建具有不同的任务。构建任务的代码使用是通过重用代码来定义构建任务来完成的。看看循环如何不执行相同的任务两次,而是创建任务,这些任务稍后可以被触发(通过all-task或在rake命令行上选择其中一个)。
task :invoke_another_task do
# some code
Rake::Task["another:task"].invoke
end