rakeにはtaskやfile以外に、ruleという定義が使えます。簡単に言うとmakeのサフィックスルールで、こういうファイルだったら、こういうファイルにしますよ、という正しくルールを定義するためのものです。以下簡単に使い方。
rule '.o' => '.c' do |t|
sh "gcc -o #{t.name} #{t.source}"
end
上記は「".o"で終わるタスク名(ファイル名じゃない!)が与えられ、そのタスク名の".o"を".c"に置き換えたものをソースファイルとし、そのソースファイルが存在するならタスクを実行する」という意味になります。実際に実行してみた方が分かりやすいですね。
$ ls src
hello.c
$ rake --rules src/hello.o # --rulesオプションをつけると実際どうやってruleが解決されているか分かる
Attempting Rule src/hello.o => src/hello.c
(src/hello.o => src/hello.c ... EXIST)
gcc -o src/hello.o src/hello.c
$ rake --rules src/world.o
Attempting Rule src/world.o => src/world.c
(src/world.o => src/world.c ... FAIL)
rake aborted!
Don't know how to build task 'src/world.o'
(See full trace by running task with --trace)
これ、パッと見ると、拡張子でしか定義できないように見えます。実は正規表現を与えることが出来るので、そうすれば自在にパターンを定義できます。
rule %r{^dist/.+\.o} => '%{^dist,src}X.c' do |t|
sh "gcc -o #{t.name} #{t.source}"
end
$ rake --rules dist/hello.o
Attempting Rule dist/hello.o => src/hello.c
(dist/hello.o => src/hello.c ... EXIST)
gcc -o dist/hello.o src/hello.c
ちなみに変換方法に指定されている"%{^dist,src}X"はpathmapという仕組みで、"%X"だけ指定するとマッチしたタスク名をファイル名と見立て、「拡張子を取り除いた文字列」を意味し、"%{正規表現,置換文字列}X"とすると、「拡張子を取り除き、正規表現にマッチした文字列を置換文字列に置き換えた文字列」となります。ぐっちゃぐちゃですね。まあ上記の例を見ていただければと思います。
ちなみに変換方法にはProcのインスタンスを与えることが出来るので、そちらを与えると自由自在に変換できますね。
ちょっと前にruleについて調べていたら、なかなか融通効かないなーと思っていましたが、正規表現とProcを使えばやりたい放題でした。