td2sk の日記

技術メモとかゲームとか

Makefileの自動生成

この記事の内容は古くなっています。

をどうぞ

久々に、というか初めて本格的にC++を使ってプログラムを書いているのだが、Makefileを書くのが面倒で仕方ない。C++で依存関係といえば#include。つまり#include行を取り出してMakefileにぶち込むスクリプトを書けばいいわけだ。しかしここで変なバグを作って混乱するのも馬鹿らしい。
だからコンパイラに任せてしまおう。

参考にしたのは以下のページ。GNU Makeのマニュアルの日本語訳。
GNU Make 再コンパイル作業を制御するプログラム

gccでは、

gcc -MM hoge.cpp

とすれば、cppファイルを解析して、依存しているヘッダファイルを自動的に取り出してくれる。
これを使えば以下の手順でMakefileを自動生成できる。

  1. 各々の.cppに対して、gcc -MM
  2. 結果を.dependファイルに書きだす
  3. Makefileで、自動生成された.dependをinclude

ところで、.dependもソースやヘッダファイルに依存している。ソースコードに新しく#includeを追加すれば依存関係が変わるのだから当然だろう。
ゆえに、このファイルもMakefileによって必要に応じて生成し直さないといけない。
そのために、.dependファイルも.oファイルと同じものに依存させればよい。
具体的には

$ gcc -MM hoge.cpp
  hoge.o : hoge.cpp hoge.hpp foo.h bar.h

を、sedを使って

$ gcc -MM hoge.cpp | sed 's/\($*\)\.o[ :]*/\1.o hoge.depend : /g'
 hoge.o hoge.depend : hoge.cpp hoge.hpp foo.h bar.h

などとすればいい。

Makefileにすると以下のようになる。

PROGRAM := hoge
SOURCES := $(wildcard *.cpp)
OBJS := $(SOURCES:.cpp=.o)
DEPENDS := $(SOURCES:.cpp=.depend)
CXX := g++
CPPFLAGS := -O2

.PHONY: all
all: $(PROGRAM)
$(PROGRAM): $(OBJS) 
	$(CXX) -o $(PROGRAM) $(CPPFLAGS) $^


%.depend: %.cpp
	@echo generating $@
	@$(SHELL) -ec '$(CC) -MM $(CPPFLAGS) $< | sed "s/\($*\)\.o[ :]*/\1.o $@ : /g" > $@; [ -s $@ ] || rm -f $@'


ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEPENDS)
endif

.PHONY : clean
clean:
	rm -f $(PROGRAM)
	rm -fr $(OBJS)
	rm -fr $(DEPENDS)

これで当面、Makefileには触れなくてよさそうだ

(追記)2011/7/8 Makefileを一部修正
(追記)2012/11/9 Makefileを修正