2013年02月08日

Makefileの依存関係の記述を自動化する簡単な方法

ビルドにmakeコマンドを使うときにはMakefileにファイルの依存関係を書いておく必要があります。

しかし、開発の途中でインクルードするヘッダファイルが増えてくると、これらの依存関係を手作業で記述するのは面倒です。(そして、これをサボったことでハマることもよくあることです。:)

ここでは、gccの機能を使ってこれを自動化する方法を紹介します。



gccのプリプロセッサで依存関係を自動生成する

gccでコンパイルするときに -MD というオプションをつけると、コンパイルとともに拡張子が.dのファイルが作成されます。これはMakefileと同じ書式でそのファイルの依存関係が記述されています。

詳しくはgccのマニュアルを参照してください。

http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Preprocessor-Options.html

生成した依存関係のファイルをMakefileにとりこむ

Makefileの中でCのコンパイルオプションに -MDを追加するには、Makefileの最初の方で以下を追加します。

CFLAGS += -MD

生成された.dファイルをとりこむにはMakefileの最後の方に以下を追加します。

-include *.d

行頭の'-'は*.dのファイルが無くてincludeが失敗した場合でもそれを無視するための指定です。

また、自動生成された *.dのファイルを削除するために、cleanのところに以下を追加するとよいでしょう。

    rm -f *.d

サンプル

簡単な例で説明します。

$ cat hello.c 
#include <stdio.h>
#include "message.h"

main()
{
	printf("%s, world\n", MESSAGE);
}
$ cat message.h 
#define MESSAGE "Hello"

このように、hello.cはmessage.hをインクルードしています。

とりあえず以下のようなMakefileでこれをmakeすることができます。

CFLAGS = -g

OBJS = hello.o

hello: $(OBJS)

clean:
	rm -f hello $(OBJS)

しかしこれには hello.oがmessage.h に依存していることが記述されていないため、message.hを修正してもhello.oは再コンパイルされません。

以下の赤字の部分を追加します。

CFLAGS = -g
CFLAGS += -MD

OBJS = hello.o

hello: $(OBJS)

clean:
	rm -f hello $(OBJS)
	rm -f *.d

-include *.d

これでmakeすると

$ make
cc -g -MD   -c -o hello.o hello.c
cc   hello.o   -o hello

自動生成されたhello.dの内容は以下の通りです。

$ cat hello.d
hello.o: hello.c /usr/include/stdio.h /usr/include/features.h \
 /usr/include/x86_64-linux-gnu/bits/predefs.h \
 /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \
 /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-linux-gnu/4.6/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h message.h

次回のmakeではこのhello.dがMakefileにインクルードされるので、message.hを修正したらhello.oが再コンパイルされます。

おまけ

以下のワンライナーでコンパイルに必要な全てのソースファイルを一覧できます。

$ cat *.d | sed -e 's/^.*://' -e 's/\\$//' | tr ' ' '\012' | sort | uniq

(sedで行頭の:までを削除、行末のバックスラッシュを削除。trで空白を改行に変換。sortして重複を削除。)



トラックバックURL

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード