01 Oct 2009

続、Makefileの書き方再入門。簡潔なMakefile編

前回(Makefileの書き方スピード再入門 - フリーフォーム フリークアウト)の内容について、twitterで@makingさんに、pyopyopyoさんの素晴らしい記事について教えていただきました。

Twitter / making: .@cou929 make -pみてみるといいです。 ...

Makefile は簡潔に書きましょう - ぴょぴょぴょ? - Linuxとかプログラミングの覚え書き -

内容は、最大限にmakeビルトインのルールを活用して、極力シンプルなMakefileを書こうというものです。

デフォルトのルールの確認

Makefileがあるディレクトリで、make -p します。出力は結構大きいです。

簡潔な書き方の例

例えば、foo.cppをコンパイルして、fooというバイナリを作るときは、

all: foo

これだけで全てやってくれます。これはすごい。ソースコードが複数ファイルに分かれている場合でも、ルールを一行追加するだけでOKです。

foo: foo.o bar.o

コンパイラオプションを追加したり、パスが通っていない場所に作りかけの自前ライブラリがある場合などには、最小限のマクロだけ追加します。

CXXFLAGS += -Wall -I/foo/bar/include    # cのプログラムの場合はCFLAGS
LDFLAGS += -L/foo/bar/lib -lfoo

昨日の例を改善

Before
CC=g++
LIB=
LIBDIR=-L/opt/local/lib
INCDIR=-I/opt/local/include
CFLAGS=-Wall
TARGETS=foo
SRCS=foo.cpp
OBJS=$(SRCS:.cpp=.o)

all: $(TARGETS) $(OBJS)

$(TARGETS): $(OBJS) 
        $(CC) $(LDFLAGS) -o $@ $(OBJS) $(INCDIR) $(LIBDIR) $(LIB)

.cpp.o:
        $(CC) $(CFLAGS) -c $< $(INCDIR) $(LIBDIR) $(LIB)

.PHONY: clean
clean:
        $(RM) *~ $(TARGETS) $(OBJS)
After
TARGETS=foo
CXXFLAGS += -Wall
LDFLAGS += 
all: $(TARGETS)

.PHONY: clean
clean:        $(RM) *~ *.o $(TARGETS)

かなりすっきりしました。本当はもっとストイックに切り詰めたほうがいいのかもしれませんが、個人的にはcleanが欲しいのでこうしてあります。今後も改善していきたいです。

謝辞

個人的には、まさに発想の転換というか、目からうろこでした。makingさん、pyopyopyoさんありがとうございます!