make 改訂版(5章)
再帰的なmake
複数のディレクトリにまたがったコンパイルをする時に
make ってやると下位ディレクトリまで含めて依存関係を解消できる
[kobakoba0723@fedora13-intel64 recursive]$ make cc -c -o main.o main.c cd hoge; \ make all make[1]: ディレクトリ `hoge' に入ります cc -c -o hoge1.o hoge1.c cc -c -o hoge2.o hoge2.c make[1]: ディレクトリ `hoge' から出ます cd piyo; \ make all make[1]: ディレクトリ `piyo' に入ります cc -c -o piyo1.o piyo1.c cc -c -o piyo2.o piyo2.c make[1]: ディレクトリ `piyo' から出ます cc -o main main.o hoge/hoge1.o hoge/hoge2.o piyo/piyo1.o piyo/piyo2.o
ファイル構成とかMakefileの中身とか
top dir
- Makefile | |
- main.c | |
- hoge | |
- Makefile | |
- hoge1.c | |
- hoge2.c | |
- piyo |
hoge, piyoディレクトリのMakefile[piyoの場合は、hogeのかわりにpiyo]
all : hoge1.o hoge2.0 clean : rm -f *.o rm -f *~
OBJS = main.o \ hoge/hoge1.o \ hoge/hoge2.o \ piyo/piyo1.o \ piyo/piyo2.o main : main.o hoge_obj piyo_obj ${CC} ${CFLAGS} -o $@ ${OBJS} hoge_obj : cd hoge; \ ${MAKE} all piyo_obj : cd piyo; \ ${MAKE} all clean : rm main *.o *~ cd hoge; make clean cd piyo; make clean
下位ディレクトリのMakefileが簡単に書けるのは、サフィックスルールを使えているから
この場合、各種オブジェクトファイルはソースファイルと同じパスにできるから、
トップディレクトリのMakefileのOBJSには、パスまで含めてオブジェクトファイルを記載する。
また、makeでなく${MAKE}と書いているのは、
コマンドラインで指定したマクロを下位のmakeコマンドにも自動的に反映させるため。
内部マクロを使ってもう少し簡単に...ならなかった
$?以外のマクロには、D(ディレクトリ)やF(ファイル)という修飾子をつけることが出来る
以下はFの時の意味だが、Dの場合は、ファイルをディレクトリに変える
マクロ | 意味 |
${@F} | ターゲット($@)のファイル名部分 |
${*F} | コンンポーネントのファイル名からサフィックスを除いたファイル名 |
$<(コンポーネント($<)のファイル名部分)っていうのもあるけど、表組の中に書くとtdタグが追加されるのはなんでだ。
これを使うと、トップのMakefileは、
OBJS = main.o \ hoge/hoge1.o \ hoge/hoge2.o \ piyo/piyo1.o \ piyo/piyo2.o main : main.o modules ${CC} ${CFLAGS} -o $@ ${OBJS} modules : hoge/hoge1.o hoge/hoge2.o piyo/piyo1.o piyo/piyo2.o cd ${<D}; \ ${MAKE} ${<F} clean : rm -f main rm -f *.o rm -f *~ cd piyo; make clean cd hoge; make clean
この状態でmakeすると
[kobakoba0723@fedora13-intel64 recursive]$ make cc -c -o main.o main.c cc -c -o hoge/hoge1.o hoge/hoge1.c cc -c -o hoge/hoge2.o hoge/hoge2.c cc -c -o piyo/piyo1.o piyo/piyo1.c cc -c -o piyo/piyo2.o piyo/piyo2.c cd hoge; \ make hoge1.o make[1]: ディレクトリ `hoge' に入ります make[1]: `hoge1.o' は更新済みです make[1]: ディレクトリ `hoge' から出ます cc -o main main.o hoge/hoge1.o hoge/hoge2.o piyo/piyo1.o piyo/piyo2.o
makeが走る前に個々のオブジェクトが作成されちゃったよ。。。って、サフィックスルールかぁ。
じゃあ、このマクロを使おうとすると、サフィックスルールを無効化しないといかんのか?
そんな馬鹿な話はないだろうから、使い方が間違ってるんだろうけど、どうやって使えばいいんだ。。。
複数人で開発する
メインとなるソースファイルがどこかにあって、
自分が担当するソースだけローカルで修正して、それを使ってコンパイルしたい時にはVPATHマクロが役に立つ
VPATHマクロは、コンポーネントを検索するパスを指定することが出来る
/usr/src/hoge_prj
- Makefile(コンポーネント・実行ファイルは、相対パスで記述しておく) |
- main.c |
- hoge.c |
- piyo.c |
- hoge.c |
[kobakoba0723@fedora13-intel64 hoge_prj]$ make -f /usr/src/hoge_prj/Makefile VPATH=/home/kobakoba0723/hoge_prj:/usr/src/hoge_prj cc -c -o main.o /usr/src/hoge_prj/main.c cc -c -o hoge.o hoge.c cc -c -o piyo.o /usr/src/hoge_prj/piyo.c cc -o main main.o hoge.o piyo.o
コマンドラインから#ifdef用のシンボル定義
#ifdef とか #ifndef とか条件コンパイルをするときのシンボル情報をコンパイルの時に渡せるCFLAGS=-Dシンボル名例えば、デバッグ用の出力をしたい時なんかに、Makefileとmain.cを書いて、 (Makefile)
OBJS = main.o main : ${OBJS} ${CC} -o $@ ${OBJS} clean : rm -f main *.o *~(main.c)
#include <stdio.h> int main(void) { fprintf(stderr, "hello world\n"); #ifdef DEBUG fprintf(stderr, "debug information\n"); #endif return 0; }make するときに CFLAGS を指定してやればシンボルがちゃんと渡る。
[kobakoba0723@fedora13-intel64 symbol]$ make cc -c main.c cc -o main main.o [kobakoba0723@fedora13-intel64 symbol]$ ./main hello world [kobakoba0723@fedora13-intel64 symbol]$ make clean rm -f main *.o *~ [kobakoba0723@fedora13-intel64 symbol]$ make "CFLAGS=-DDEBUG" cc -DDEBUG -c main.c cc -o main main.o [kobakoba0723@fedora13-intel64 symbol]$ ./main hello world debug informationmake cleanをやらないと再コンパイルできない。。。 そのうえ、このままだとシンボルをつけてコンパイルした実行ファイルか、つけてないのかが判らない。