Rakeタスク内からRakeタスクを実行する方法は?


411

私はグローバル変数に応じて、2つの方法でプロジェクトをコンパイルする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
どちらが答えですか?
nurettin 2012年

私はコミュニティの投票に参加し、221回(執筆時)に賛成票を投じた答えを選びます。オリジナルのポスターがSOを去りました
MPritchard 2013年


参考までに、新しいスレッドを作成してRails環境をロードする必要がないため、のようなものを使用するRake::Task["build"].invoke方が使用するよりもはるかにパフォーマンスが高くなる可能性がsystem rake buildありますsystem rake build
ジョシュアピンター

回答:


639

タスクがメソッドとして動作する必要がある場合は、実際のメソッドを使用してみませんか?

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
    
  • すでに呼び出された依存関係は、再度有効にしない限り、自動的に再実行されないことに注意してください。Rake> = 10.3.2では、次のものを使用してそれらを再度有効にすることもできます。

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

96
タスクが名前空間にある場合は、タスクを呼び出すときに名前空間を含める必要があることに注意してください。例えば。Rake::Task['db:reset'].invoke
David Tuite、2011

126
問題のタスクが引数を取る場合、それらを#invokeの引数として渡すことができます。例えば。Rake::Task['with:args'].invoke("pizza")
トロッター2011

27
環境変数を設定する必要がある場合は、invokeを呼び出す前に設定してください。例:ENV['VERSION'] = '20110408170816'; Rake::Task['db:migrate'].invoke詳細については、こちらをご覧ください。
Michael Stalker 2013年

13
私は最近#reenable()、前提条件を再び有効にしないことを発見し、それを必要としました。 Rakeへのこの追加(> = 10.3.2)は、#all_prerequisite_tasks()前提条件の前提条件を含むすべてのタスクを反復します。したがって、Rake::Task[task].all_prerequisite_tasks.each &:reenable
Richard Michael

4
@kch、これらを一緒に文字列化できますか(コマンドラインrake db:reset db:migrateなど)。あなたのような何かを行うことができます: Rake::Task["db:reset", "db:migrate"].invoke
ジェフ

125

例えば:

Rake::Task["db:migrate"].invoke

6
これは、まだ呼び出されていない場合にのみタスクを呼び出します。しかし、2回依存する他のすべてのタスクでタスクを呼び出す必要があります。

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

それはあなたを整理するはずです、私自身と同じものが必要でした。


これは機能的ですが、冗長すぎます。確かにこれ以上のものはありませんか?
kch、2009

13
task :invoke_another_task do
  # some code
  Rake::Task["another:task"].invoke
end

このような解決策が必要になった理由の1つは、rakeタスクの読み込みに時間がかかるためです。上記のようなソリューションを実装することで、読み込み時間を節約できますか?
Dipan Mehta

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

:buildタスクの本体を実行するだけで、それに依存するタスクを呼び出さないため、機能しません。

4

失敗に関係なく各タスクを実行したい場合は、次のようにすることができます。

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

-1

プロジェクトが実際にコンパイルされてファイルが生成されるものである場合は、一般的なデバッグタスクとリリースタスクを作成しないことをお勧めします。あなたが言うように、あなたの例ではかなり実行可能なファイルタスクを使うべきです、あなたの出力は別のディレクトリに行きます。プロジェクトがtest.cファイルをコンパイルしてout / debug / test.outとout / release / test.outを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. グローバル変数でパラメーター化されたビルドタスクを再度有効にする必要はありません。これは、ビルドごとにタスクが異なるためです。ビルドタスクのコードの再利用は、コードを再利用してビルドタスクを定義することによって行われます。ループが同じタスクを2回実行するのではなく、作成されたタスクがどのようにトリガーされるかを確認します(後でall-taskによって、またはrakeコマンドラインでそれらの1つを選択して)。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.