Rakefileでg++コンパイルするとき、ヘッダファイルの依存関係をインポートしてみる
Rakefileは便利なのでg++コンパイルでMakefileの代替になればと思い、いろいろ模索中です。
ひとまず、簡単なメイクは作れるようになってきたところです。
で、問題が1つ浮上。
これまでMakefileでヘッダファイルの依存関係を定義(-MM)していましたが、それをRakefileでどう記述すればよいかわかりません。
ネットでいろいろ漁ってみたのですが、なかなか解が見つからず。。
自力でなんとかするしかないか。。。
まずは自力で。。
とりあえず、なんとなくうまくいったっぽいRakefileをメモします。
あまり、Rakefileのドキュメント見ずに書いたのでちょっぴり不安ですが。。
CXX = "g++" CFLAGS = "-O2 -Wall -I./" LIBS = "-lm" TARGET = "run.x" srcs = FileList["*.cpp"] objs = srcs.ext('o') task :default => :all task :all => TARGET #clean require 'rake/clean' CLEAN.include objs CLOBBER.include TARGET task :clean_all => :clobber file TARGET => objs do |t| sh "#{CXX} -o #{t.name} #{t.prerequisites.join(' ')} #{LIBS}" end rule '.o' => ['%n.cpp', "%n.d"] do |t| sh "#{CXX} #{CFLAGS} -c #{t.source}" end # generate dependency information srcs.each do |src| dep = src.sub(/\.(c|cpp)$/,".d") file dep => src do |t| tmp = `#{CXX} -MM #{CFLAGS} #{src}` obj,arg = tmp.gsub(/\\\n /,"").split(":") str = "file " + obj.inspect + " => [" + arg.split(' ').map{|m| m.inspect }.join(",") + "]" File.open(t.name,"w") {|f| f.write str} end import dep CLEAN.include dep end
肝となるのは、以下の記述です。
srcs.each do |src| ・・・ end
処理の流れは、
- "g++ -MM"で依存関係データを取得
- それを、"file obj => [srcs]"の形式に置換
- その文字列を、".d"ファイルに書き込む
- 最後に"import"で".d"をインポートする
そして、".o"を生成するruleに"%n.d"を追加。
eachを使って処理できるのがrubyっぽいかも。
あっているのかなぁ、自信なし。
それと、もうちょっと綺麗に書ければなぁ。
rake/loaders/makefieを使う
よく調べたら、-MMで吐き出されたファイルをそのまま使用できることがわかりました。
ただし、拡張子は".mf"にする必要がありそうです。
改変後は以下のとおりです。
CXX = "g++" CFLAGS = "-O2 -Wall -I./" LIBS = "-lm" TARGET = "run.x" srcs = FileList["*.cpp"] objs = srcs.ext('o') task :default => :all task :all => TARGET #clean require 'rake/clean' CLEAN.include objs CLOBBER.include TARGET task :clean_all => :clobber file TARGET => objs do |t| sh "#{CXX} -o #{t.name} #{t.prerequisites.join(' ')} #{LIBS}" end rule '.o' => ['%n.cpp'] do |t| sh "#{CXX} #{CFLAGS} -c #{t.source}" end # generate dependency information require 'rake/loaders/makefile' srcs.each do |src| dep = src+".mf" file dep => src do |t| sh "#{CXX} -MM #{CFLAGS} #{src} > #{t.name}" end import dep CLEAN.include dep end
無駄な正規表現使わずにすっきり書くことができました。
最初、".d"っていうファイル名で依存関係のファイルを作っていたのですが、なぜかsyntaxエラーに。そこで、".mf"に変えたところ、うまく通りました。
".mf"はMakefileの記述だよ、って教えてあげているみたいですね。