taskの依存関係を理解する
最初のサンプルなので、順を追って説明していきます。
①単純なtask
task :default => :daily_report desc "1日のトレーニング内容を記録する" task :daily_report do puts "レポートを作成しました。" end
・task :default => :daily_report
により、rakeコマンドを簡潔に実行できる。
$ rake #=> レポートを作成しました。
・descに記述したものは以下のコマンドで見ることが出来る。
$ rake -T #=> rake daily_report # 1日のトレーニング内容を記録する
②依存関係を記述する
task :default => :daily_report desc "1日のトレーニング内容を記録する" task :daily_report => [:run,:swim] do puts "レポートを作成しました。" end desc "1日のswim量を報告します" task :swim do puts "今日あなたは2キロ泳ぎました" end desc "1日のrun量を報告します" task :run do puts "今日はあなたは4キロ走りました" end
・task :daily_report => [:run,:swim] do
の部分でtaskdaily_report
の依存関係を記述できます。
$ rake #=> 今日はあなたは4キロ走りました #=> 今日あなたは2キロ泳ぎました #=> レポートを作成しました。
・task :daily_report => [:swim,:run] do
とすると実行順序が変わることがわかります。
$ rake #=> 今日あなたは2キロ泳ぎました #=> 今日はあなたは4キロ走りました #=> レポートを作成しました。
・依存関係をクリアしないとrakeは失敗します。
以下のようにdaily_report
の依存関係の1つであるswimをコメントアウトしてrakeを実行します。
task :default => :daily_report desc "1日のトレーニング内容を記録する" task :daily_report => [:swim,:run] do puts "レポートを作成しました。" end #desc "1日のswim量を報告します" #task :swim do # puts "今日あなたは2キロ泳ぎました" #end desc "1日のrun量を報告します" task :run do puts "今日はあなたは4キロ走りました" end
$ rake #=> rake aborted! #=> Don't know how to build task 'swim' (see --tasks)
ファイルタスク:差分ビルドの実現
タスクではなく、あえてファイルタスクを用いる理由、それは差分ビルドの実現にある。 タスクとして定義された場合、そのタスクは必ず実行される。もっと言えば、いまそれをする必要が無くとも、定義されている以上実施してしまう。しかし、ファイルタスクの場合、必要なときだけタスクを実施するのである。具体的には、定義されたファイルを作ろうとする際、まず目的ファイルが作成済みかどうかを調べる。作成済みであれば、続けて依存先のファイルの更新日時を調べ、それが目的ファイルよりも新しくなっている場合のみ、変更があったと見なしてビルド作業を実施するのだ。これは大変な時間の節約になる。
例えば、同一フォルダ内に以下のようなファイルが3つある場合を想定します。
$ ls #=> Rakefile report.txt run.txt swim.txt $ cat run.txt #=> run: 12キロ $ cat swim.txt #=> swim: 5キロ $ cat report.txt #=> swim: 5キロ #=> run: 12キロ
task :default => :report desc "ファイルに記録します" task :report => "report.txt" file "report.txt" => ["swim.txt","run.txt"] do puts "ファイルを記録します" swim = File.read("swim.txt") run = File.read("run.txt") report = swim + run File.open("report.txt","w") do |file| file.puts(report) end end
ポイントはfile "report.txt" => ["swim.txt","run.txt"] do
で、report.txt
がswim.txt
とrun.txt
に依存していることです。
このような関係にある時、swim.txt
とrun.txt
に変更が加わらなければ、file'report.txt'が更新されることはありません。
$ rake
なにも実行されません。
$ echo "swim: 20キロ" > swim.txt $ rake #=> ファイルを記録します
今度はfile'report.txt'が更新されていることがわかります。
$ cat report.txt #=> swim: 20キロ #=> run: 12キロ
C言語のコンパイル
基本的なことだけ
CC = "gcc" task :default => "hello" file "hello" => ["hello.o"] do sh "#{CC} -o hello hello.o" end file "hello.o" => "hello.c" do sh "#{CC} -c hello.c" end task :clean do sh "rm -rf hello *.o" end
・依存関係を辿って行くと、hello=>hello.o=>hello.c
・gcc -c hello.c hello.oが作成される コンパイルのみ行う(オブジェクトファイルを生成する).
・gcc -o hello hello.o hello.oをhelloにリンクする
・コマンドを実行するときは、
$./hello
・rakeを2度実行しても何も起こらない
・hello.cを変更すれば、gcc -c hello.c
とgcc -o hello hello.o
の両方が実行される。
・hello.oを変更すればgcc -o hello hello.o
だけ実行される。
参照
rake 公式 C言語のビルドでほのぼのrakeでmakeするよ るびくる&RBのRubyプログラミング大作戦! ファイルを扱う作業をRakeで便利にしよう!(パート1:概要編) パーフェクト Ruby [Ruby][rake]Rakefileでgccコンパイルしてみる コンパイラ(gccコマンド)の使い方