首页 文章

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

提问于
浏览
385

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

有没有办法将任务称为方法?或者我怎样才能达到类似的效果呢?

7 回答

  • 3

    如果您需要将任务作为一种方法,那么使用实际方法呢?

    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
    
    • 这个执行依赖项,但它只在尚未调用的情况下执行任务:
    Rake::Task["build"].invoke
    
    • 这首先重置任务的already_invoked状态,然后再次执行任务,依赖项和所有:
    Rake::Task["build"].reenable
    Rake::Task["build"].invoke
    

    (请注意,已经调用的依赖项不会被重新执行)

  • 112

    例如:

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

    那应该让你理智,我自己也需要同样的东西 .

  • 5
    task :build_all do
      [ :debug, :release ].each do |t|
        $build_type = t
        Rake::Task["build"].execute
      end
    end
    
  • -1
    task :invoke_another_task do
      # some code
      Rake::Task["another:task"].invoke
    end
    
  • 11

    如果您希望每个任务都能运行而不管任何失败,您可以执行以下操作:

    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
    
  • 55

    如果项目真的是被编译的结果,那么我建议不要创建一般的调试和发布任务 . 您应该使用在您的示例中非常可行的文件任务,如您所述,您的输出将进入不同的目录 . 假设您的项目只是使用gcc将test.c文件编译为out / debug / test.out和out / release / test.out,您可以像这样设置项目:

    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)
    

    这有点像所要求的那样,但显示了我的观点:

    根据需要创建

    • 输出目录 .

    • 仅在需要时重新编译文件(此示例仅适用于最简单的test.c文件) .

    • 如果要触发发布版本或调试版本,您可以随时掌握所有任务 .

    • 此示例包含一种定义调试版本和发布版本之间的小差异的方法 .

    • 无需重新启用使用全局变量进行参数化的构建任务,因为现在不同的构建具有不同的任务 . 构建任务的代码重用是通过重用代码来定义构建任务来完成的 . 看看循环如何不执行两次相同的任务,而是创建任务,以后可以触发(通过全部任务或在rake命令行上选择其中一个) .

相关问题