RakefileFormat
3.1 はじめに
まず第一に、Rakefile 専用のフォーマットというのは存在しません。Rakefile は実行可能な Ruby のコードで構成されます。ruby スクリプトとして正当であれば、Rakefile としても正当です。
専用のフォーマットはないと説明しましたが、典型的な Ruby プログラムではあまり見かけない、ちょっと変わったイディオムを使用することがあります。Rakefile は、タスクとアクションを合わせて指定するために、その、ちょっと変わったイディオムをサポートしています。
それでは、Rakefile はどのように書くのでしょうか?
3.2 タスク
タスクは Rakefile の基本となる作業単位です。タスクは、タスク名(通常は、シンボルか文字列)、前提条件リスト(これも、シンボルか文字列)、アクション(ブロックとして与えられる)を持ちます。
単純なタスク
タスクは task メソッドを使って宣言されます。task は引数に、タスク名を一つ取ります。
task :name
前提条件付きのタスク
タスク名と => の後のリスト([ ]の中)に、どのような前提条件でも、指定することが出来ます。
task :name => [:prereq1, :prereq2]
注意!!: この構文はちょっと変わって見えますが、正当な Ruby のコードです。キーが :name 、値が前提条件([ ]の部分)の Hash を作っているだけです。要は、以下と同等です。
hash = Hash.new hash[:name] = [:prereq1, :prereq2] task(hash)
アクション付きのタスク
アクションは task メソッドのブロックの中に定義されます。どのような Ruby コードでもかまいません。ブロックパラメータを使って、task オブジェクトの参照を渡すこともあります。
task :name => [:prereq1, :prereq2] do |t| # アクション(t を利用できます。) end
複数回の定義
タスクが2回以上定義されることがあります。その場合、定義が実行されるたびに、前提条件とアクションを、既存の定義に追加します。これは、アクションの指定と、依存関係宣言を、別の場所(おそらく別のファイル)で定義することを許可するためです。
例えば下記は、上の項(アクション付きのタスクの項)で定義されたタスクと同等のものです。
task :name task :name => [:prereq1] task :name => [:prereq2] task :name do |t| # アクション end
3.3 ファイルタスク
いくつかのタスクは、あるファイルから別のファイルを生成します。ファイルが既に存在すれば、そのタスクは省略されるかもしれません。ファイルタスクはファイル生成処理に使用されます。
ファイルタスクは file メソッド(task メソッドの代わり)を使用してし定義されます。なお、ファイルタスクのタスク名には、シンボルではなく文字列が使用されるのが一般的です。
以下のファイルタスクは、実行形式ファイル(prog)を生成するために、2つのオブジェクトファイル、 a.o と b.o が存在することを想定しています。このタスクでは a.o と b.o の生成については触れません。
file "prog" => ["a.o", "b.o"] do |t| sh "cc -o #{t.name} #{t.prerequisites.join(' ')}" end
3.4 ディレクトリタスク
ディレクトリの作成が必要となるケースはよくあることです。directory メソッドは、ファイルタスクに足りない、ディレクトリ作成処理を実施します。例えば、
directory "testdata/examples/doc"
と、以下は同等です。
file "testdata" do |t| mkdir t.name end file "testdata/examples" do |t| mkdir t.name end file "testdata/examples/doc" do |t| mkdir t.name end
directory メソッドには、前提条件やアクションは指定できませんが、後から追加することなら可能です。例えば以下のようにします。
directory "testdata" file "testdata" => ["otherdata"] file "testdata" do cp Dir["standard_data/*.data"], "testdata" end
3.5 ルール
前提条件にファイル名が未指定の場合、Rake はルールリストから対応するタスクを探し出そうとします。
mycode.o が未定義の状態で、mycode.o タスクが実施されるとします。その場合でも rakefile には、以下のようなルールが存在します。
rule '.o' => ['.c'] do |t| sh "cc #{t.source} -c -o #{t.name}" end
上記のルールは、.o で終わるすべてのタスクに対応します。それは、前提条件に、拡張子 .c のソースファイルが存在することを指定します。mycode.c というファイルを発見すれば、mycode.c から mycode.o を生成するタスクを自動的に作り出します。
mycode.c が見つからない場合は、再帰的に、ルールに対応するタスクがないかを探そうとします。
ルールに対応するタスクが見つかった時、参照(ブロックパラメータ)に、source 属性がセットされます。これは、アクション内でで、ソースファイルを扱えるようにするためです。
3.6 高度なルール
ルールパターンには正規表現が使用できます。ソースファイル名を求めるのに proc 利用されることもあります。これは、複雑なルールパターンや、複雑な手順でソースファイル名を求めるのに対応するためです。
以下のルールは、上の項(ルールの項)と同等です。
rule( /\.o$/ => [ proc {|task_name| task_name.sub(/\.[^.]+$/, '.c') } ]) do |t| sh "cc #{t.source} -c -o #{t.name}" end
注意!! : Ruby の都合で、ルールに対する最初の引数が正規表現の場合、括弧を省略することは出来ません。
以下のルールを、Java ファイルのために利用することがあるかもしれません。
rule '.java' => [ proc { |tn| tn.sub(/\.class$/, '.java').sub(/^classes\//, 'src/') } ] do |t| java_compile(t.source, t.name) end
注意!! : java_compile は、Java コンパイラを呼び出す命令の例えです。
3.7 ファイル読み込みの依存関係
ruby ファイル(別の rakefile も含む)でありさえすれば、require でそのファイルを読み込むことが出来ます。取り込まれたルールと宣言は、既存の定義に追加されます。
ファイルの読み込みは、タスクが評価される前に実施されるので、読み込まれるファイルは、あらかじめ準備されている必要があります。このことは、取り扱いの難しい依存ファイルを作る原因になりました。ファイルの読み込みに、準備が間に合わない状態です。
import メソッドは、すべての rakefile が読み込まれた後、rake コマンドで指定されたターゲットより先に実施されます。しかも、import メソッドに指定したファイル名にマッチするタスクがある場合は、ファイルを読み込む前に、そのタスクを実施します。このことにより、依存ファイルの生成と読み込みを、一回の rake コマンドで行うことが可能になります。
- 例
require 'rake/loaders/makefile' file ".depends.mf" => [SRC_LIST] do |t| sh "makedepend -f- -- #{CFLAGS} -- #{t.prerequisites} > #{t.name}" end import ".depends.mf"
.depends.mf が存在しない場合や、ソースファイルに対して古い状態である場合は、ファイルが取り込まれる前に、新しい .depends.mf を生成します。
3.8 コメント
Ruby のコメント(# から始まる)は、どこでも使用することができます。タスクやルールにコメントを使用しても問題はありません。しかし、タスクが -T オプション(後述します)に対応することを望む場合は、desc メソッドを使用する必要があります。
- 例
desc "配布パッケージの作成" task :package => [ ... ] do ... end
-T(こだわり派は --task)オプションは、タスクに定義されたコメントを画面にリストアップします。desc メソッドでコメントを定義してあれば、半自動的に要約が生成されます。
traken$ rake -T (in /home/.../rake) rake clean # Remove any temporary products. rake clobber # Remove any generated file. rake clobber_rdoc # Remove rdoc products rake contrib_test # Run tests for contrib_test rake default # Default Task rake install # Install the application rake lines # Count lines in the main rake file rake rdoc # Build the rdoc HTML Files rake rerdoc # Force a rebuild of the RDOC files rake test # Run tests rake testall # Run all test targets
-T オプションでは、タスクのコメントのみがリストアップされます。前提条件も合わせてリストアップしたい場合は -P(もしくは --prereqs)オプションを使用してください。
3.9 その他
do/end か { } か
Ruby のブロックは、do/end か { } のどちらかで指定されますが、rakefile でタスクやルールを指定する場合は、do/end を使用することを、強くおすすめします。rakefile で、task/file/rule メソッドを使用する場合には、括弧を省略することが多いため、{ } を使用してしまうと、期待した動作にならないことがあるからです。
例えば、プロジェクトのオブジェクトファイルのリストを返す、object_files メソッドがあるとします。そして、ルールの前提条件にその object_files メソッドが使用され、アクションの指定には { } を使用するとします。
# このようにしてはいけません!! file "prog" => object_files { # ここにアクションが定義されると思いますが、うまく動いてくれません。 }
{ } は do/end より優先順位が高いため、{ } のブロックを、file メソッドのブロックではなく、object_files メソッドのブロックとして扱われてしまいます。
以下が、タスクを指定する適切な方法です。
# このようにしてください!! file "prog" => object_files do # ここにアクションで、うまくいきます。。 end
Keyword(s):
References:[AboutRakeUserGuide] [SideMenu]