我有一个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

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


当前回答

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

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的习语,下面是你从过去的答案中编译出来的可能性:

This always executes the task, but it doesn't execute its dependencies: 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)

其他回答

我建议不要创建一般的调试和发布任务,如果项目确实需要编译并生成文件。您应该使用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)

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

output directories are created, as necessary. the files are only recompiled if needed (this example is only correct for the simplest of test.c files). you have all tasks readily at hand if you want to trigger the release build or the debug build. this example includes a way to also define small differences between debug and release-builds. no need to reenable a build-task that is parametrized with a global variable, because now the different builds have different tasks. the codereuse of the build-task is done by reusing the code to define the build-tasks. see how the loop does not execute the same task twice, but instead created tasks, that can later be triggered (either by the all-task or be choosing one of them on the rake commandline).

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

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

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

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的习语,下面是你从过去的答案中编译出来的可能性:

This always executes the task, but it doesn't execute its dependencies: 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 :invoke_another_task do
  # some code
  Rake::Task["another:task"].invoke
end
task :build_all do
  [ :debug, :release ].each do |t|
    $build_type = t
    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
  end
end

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