hoge diary - November 8, 2007

[プログラミング] Rake を使ってみる

Rake という新しいオモチャに手を出している今日この頃.Rake というのは make っぽい機能を提供してくれる Ruby のモジュールです.

make と比べると,make が文字列しか扱えないのに対して,Rake は Ruby の上で動くので,もう文字列,配列,ハッシュなどを慣れ親しんだ Ruby の機能でいろいろ操作できます.便利.

もう 1 個の利点といえば... cp や rm といったコマンドの名前が環境ごとに異なるということを考えなくともよいということでしょうか.書き手は FileUtils の関数を使って Rakefile (make でいう Makefile です) を書いておけば,あとは Ruby が吸収してくれるので楽です (コンパイラやリンカはコマンドが存在しないとダメですが...).

さて,Rake の使い方はいでさく氏のサイトに詳しく書いてあるのでそちらを参照するとして (私もそこで学びました),一通りの使い方が分かったところでさぁ書いてみようと,まずは以下の Rakefile を作りました.

TARGET = "test"

# Rake は最初に default と名づけられたタスクを実行する
task :default => TARGET

SRCS = FileList[ "test.cc", "test2.c" ]
OBJS = SRCS.ext('o')

# OBJS をリンクして実行ファイルを作る
file TARGET => OBJS do |t|
  sh "g++ -o #{t.name} #{t.prerequisites.join(' ')}"
end

# .o のファイルは .cc や .c から作られるということを教える.
# ファイル名を明示せずとも,Rake が自動的にこのルールを適宜当てはめてくれる.
rule ".o" => ".cc" do |t|
  sh "g++ -c -o #{t.name} #{t.source}"
end

rule ".o" => ".c" do |t|
  sh "gcc -c -o #{t.name} #{t.source}"
end

これを test.cctest2.c のあるディレクトリで実行すると,次のようにちゃんとビルドが実行できます.

$ rake
(in /home/hoge)
g++ -c -o test.o test.cc
gcc -c -o test2.o test2.c
g++ -o test.exe test.o test2.o
$

うまく動きました.test.cc だけ touch してから再実行すると,make と同様にちゃんと test.cc だけ再コンパイルしてくれます.

ここで,ソースコードは全て ./src に,オブジェクトファイルは全て ./objs に分けたい場合は,rule ".o" => ".cc" が使えない(マッチしない)ので,Rakefile を次のように書く必要があるみたいです.

TARGET = "test"

task :default => TARGET

OBJ_DIR = "objs"

SRCS = FileList[ "src/test.cc", "src/test2.c" ]

directory OBJ_DIR

file TARGET => OBJS do |t|
  sh "g++ -o #{t.name} #{t.prerequisites.join(' ')}"
end

# SRCS の各要素に対して 1 個ずつファイルタスクを作る
SRCS.each do |src|
  obj = src.sub( %r{^src/(.*)\.(cc|c)}, OBJ_DIR+'/\1.o' )
  file obj => [OBJ_DIR, src] do
    sh "g++ -c -o #{obj} #{src}"
  end
end

コンパイル前にオブジェクトファイル用のディレクトリを作ってもらわないといけないので,directory タスクを付け加えています.

最初は下のように書いてみたりもしましたが,Rake を実行時に objs/test.o の作り方が分からんと言われてしまいました.

TARGET = "test"

task :default => TARGET

# ソースは src ディレクトリ
SRCS = FileList[ "src/test.cc", "src/test2.c" ]

# 中間ファイルは objs ディレクトリ
OBJS = SRCS.sub(/^src\//, 'objs/').ext('o')

file TARGET => OBJS do |t|
  sh "g++ -o #{t.name} #{t.prerequisites.join(' ')}"
end

rule ".o" => ".cc" do |t|
  sh "g++ -c -o #{t.name} #{t.source}"
end

rule ".o" => ".c" do |t|
  sh "g++ -c -o #{t.name} #{t.source}"
end

それにしても,Rake 面白いですね.

コメント

名前(何でも可):

テキスト(http:// を含む内容は投稿できません):

トラックバック

トラックバック URI: https://www.pakunet.jp/hoge/trackback/2007110801

トラックバックはありません.


Valid XHTML 1.1! Valid CSS!
© 2004-2009 ぱくちゃん.
Last modified: Thu Nov 08 12:50:37 JST 2007