Rakefileでg++コンパイルするとき、.oファイルを別ディレクトリにする
g++コンパイルするとき、".o"ファイルがソースと同じディレクトリにあるのがあまり好きではありません。
そこで、.objdirというディレクトリを作成し、そこに".o"や".mf"を置くようにしたいと思います。
CXX = "g++" CFLAGS = "-O2 -Wall" LIBS = "-lm" TARGET = "run.x" OBJDIR = ".objdir" srcs = FileList["*.cpp", "*.c"] objs = srcs.pathmap("#{OBJDIR}/%n.o") task :default => :all # clean require 'rake/clean' CLEAN.include objs CLOBBER.include TARGET,OBJDIR desc "Clean all." task :clean_all => :clobber directory OBJDIR desc "Build all." task :all => TARGET file TARGET => objs do |t| sh "#{CXX} -o #{t.name} #{t.prerequisites.join(' ')} #{LIBS}" end # build srcs.each do |src| obj = src.pathmap("#{OBJDIR}/%n.o") file obj => [src,OBJDIR] do sh "#{CXX} #{CFLAGS} -o #{obj} -c #{src}" end end # generate dependency information require 'rake/loaders/makefile' srcs.each do |src| dep = src.pathmap("#{OBJDIR}/%f.mf") file dep => [src,OBJDIR] do |t| # sh "#{CXX} -MM #{CFLAGS} #{src} > #{dep}" sh "#{CXX} -MM #{CFLAGS} #{src} | sed -e 's/\\(.*\\)\\.o:/#{OBJDIR}\\/\\1.o:/g' > #{dep}" end import dep CLEAN.include dep end
たぶん、できました。
今回は、ruleは使いませんでした。おそらくpathmapを駆使することでruleで同様のことができると思われますが、よくわかりませんでした。
Rakefileでは、動的タスク生成が可能なのでなんとかなってしまうところがありがたいです。
おまけ
一部sedを使っていますが、外部コマンドを使わないでやってみると、
# sh "#{CXX} -MM #{CFLAGS} #{src} | sed -e 's/\\(.*\\)\\.o:/#{OBJDIR}/\\/\\1.o:/g' > #{dep}" sh "#{CXX} -MM #{CFLAGS} #{src} > #{dep}" ruby %{-i -pe '$_.sub!(/(.*).o:/,"#{OBJDIR}/\\\\1.o:")' #{dep}}
"\"が4つも繋がっちゃいました。