make 改訂版(5章) 続き

シンボルの定義/未定義で実行ファイルの動作を切り替えられるのはとても便利。
でも、コンパイル時の指定を忘れていたり、記憶違いをしていたりすると、
思いもよらない動きをする実行ファイルが作成されてしまう。
(ファイルの編集でなくシンボル定義で切り替えているから、前回のオブジェクトファイルがそのまま使われてしまう)
コンパイル時のシンボル有無が不明なのを回避する方法

  1. 強制的にリコンパイル
  2. ファイル名で切り分け
    1. 自分でファイル名を変更する
    2. サフィックスルールを使う
  3. ディレクトリで切り分け

また、include命令を使うと、Makefileの情報を別ファイルから読み込むことが出来る。
これにより、マクロ定義だけ別ファイルに定義する、なんてことが可能になる。

強制的にリコンパイル

ダミーターゲットを使用する。
makeにとってダミーターゲットは実在のどんなファイルよりも新しいもの。
なので、コンポーネントにダミーターゲット(force_rebuild)を指定すると、必ずコンパイルが実行されるという仕組み
コンパイル実行時のみ、内部マクロFRCにforce_rebuildを定義することでオブジェクトファイルの強制リコンパイルを実現
(Makefile)

OBJS = main.o hoge.o piyo.o

main :
	${MAKE} ${OBJS} "CFLAGS=${CFLAGS}" 
	${CC} -o $@ ${OBJS}

rebuild : 
	${MAKE} ${OBJS} "CFLAGS=${CFLAGS}" FRC=force_rebuild
	${CC} -o main ${OBJS}

main.o hoge.o piyo.o : ${FRC}

force_rebuild :

clean :
	rm -f main *.o *~

(実行結果)

[kobakoba0723@fedora13-intel64 symbol]$ make
make main.o hoge.o piyo.o "CFLAGS=" 
make[1]: ディレクトリ `symbol' に入ります
cc    -c -o main.o main.c
cc    -c -o hoge.o hoge.c
cc    -c -o piyo.o piyo.c
make[1]: ディレクトリ `symbol' から出ます
cc -o main main.o hoge.o piyo.o
[kobakoba0723@fedora13-intel64 symbol]$ make CFLAGS=-DDEBUG
make: `main' は更新済みです
[kobakoba0723@fedora13-intel64 symbol]$ make rebuild CFLAGS=-DDEBUG
make main.o hoge.o piyo.o "CFLAGS=-DDEBUG" FRC=force_rebuild
make[1]: ディレクトリ `symbol' に入ります
cc -DDEBUG   -c -o main.o main.c
cc -DDEBUG   -c -o hoge.o hoge.c
cc -DDEBUG   -c -o piyo.o piyo.c
make[1]: ディレクトリ `symbol' から出ます
cc -o main main.o hoge.o piyo.o
[kobakoba0723@fedora13-intel64 symbol]$ make rebuild
make main.o hoge.o piyo.o "CFLAGS=" FRC=force_rebuild
make[1]: ディレクトリ `symbol' に入ります
cc    -c -o main.o main.c
cc    -c -o hoge.o hoge.c
cc    -c -o piyo.o piyo.c
make[1]: ディレクトリ `symbol' から出ます
cc -o main main.o hoge.o piyo.o
ファイル名で切り分け(自分で名前を変更する)

コンパイル時のオプションに応じてオブジェクトファイル、実行ファイルの名前を変える。
こうすることで、どのファイルが何のオプションでコンパイルされたかが明確に判る
(Makefile)
_debug.o のコマンド行で main.o をコピーしているのは、
シンボル無しでコンパイルしたオブジェクトファイルが上書きされるのを防ぐため

OBJS = main.o hoge.o piyo.o
OBJS_DEBUG = main_debug.o hoge_debug.o piyo_debug.o

main : ${OBJS}
	${CC} -o $@ ${OBJS}

main_debug : ${OBJS_DEBUG}
	${CC} -o $@ ${OBJS_DEBUG}

main_debug.o : main.c
	- cp main.o main.save
	${CC} ${CFLAGS} -DDEBUG -c $?
	mv main.o $@
	- mv main.save main.o

hoge_debug.o : hoge.c
	- cp hoge.o hoge.save
	${CC} ${CFLAGS} -DDEBUG -c $?
	mv hoge.o $@
	- mv hoge.save hoge

piyo_debug.o : piyo.c
	- cp piyo.o piyo.save
	${CC} ${CFLAGS} -DDEBUG -c $?
	mv piyo.o $@
	- mv piyo.save piyo

clean :
	rm -f main main_debug *.o *~

(実行結果)

[kobakoba0723@fedora13-intel64 symbol]$ make main
cc    -c -o main.o main.c
cc    -c -o hoge.o hoge.c
cc    -c -o piyo.o piyo.c
cc -o main main.o hoge.o piyo.o
[kobakoba0723@fedora13-intel64 symbol]$ make main_debug
cp main.o main.save
cc  -DDEBUG -c main.c
mv main.o main_debug.o
mv main.save main.o
cp hoge.o hoge.save
cc  -DDEBUG -c hoge.c
mv hoge.o hoge_debug.o
mv hoge.save hoge
cp piyo.o piyo.save
cc  -DDEBUG -c piyo.c
mv piyo.o piyo_debug.o
mv piyo.save piyo
cc -o main_debug main_debug.o hoge_debug.o piyo_debug.o
ファイル名で切り分け(サフィックスルールを使う)

自分で名前を変えるやり方は、対象ファイルが増えるたびにMakefileの修正が必要となり煩雑。
独自のサフィックスを使用して、シンボル定義/未定義でオブジェクトファイル名、実行ファイル名を変える
サフィックスの名前は、make -p -f/dev/null などで、定義済みでないものを選ぶ。
今回は、DEBUGシンボルなので.dサフィックスを使い、オブジェクトファイルのサフィックスも.d。
シンボルを定義しない方は通常の名前(.o)でオブジェクトファイルを作成するのでデフォルトのサフィックスルールでコンパイル
(Makefile)

OBJS = main.o hoge.o piyo.o
OBJS_DEBUG = main.d hoge.d piyo.d

.SUFFIXES : .d

main : ${OBJS}
	${CC} -o $@ ${OBJS}

main_debug : ${OBJS_DEBUG}
	${CC} -o $@ ${OBJS_DEBUG}

.c.d : 
	- cp $*.o $*.save
	${CC} ${CFLAGS} -DDEBUG -c $<
	mv $*.o $@
	- mv $*.save $*.o

clean :
	rm -f main main_debug *.o *.d *~

(実行結果)

[kobakoba0723@fedora13-intel64 symbol]$ make main
cc    -c -o main.o main.c
cc    -c -o hoge.o hoge.c
cc    -c -o piyo.o piyo.c
cc -o main main.o hoge.o piyo.o
[kobakoba0723@fedora13-intel64 symbol]$ main main_debug
cp main.o main.save
cc  -DDEBUG -c main.c
mv main.o main.d
mv main.save main.o
cp hoge.o hoge.save
cc  -DDEBUG -c hoge.c
mv hoge.o hoge.d
mv hoge.save hoge.o
cp piyo.o piyo.save
cc  -DDEBUG -c piyo.c
mv piyo.o piyo.d
mv piyo.save piyo.o
cc -o main_debug main.d hoge.d piyo.d
ディレクトリで切り分け

シンボル毎にディレクトリ・Makefileを用意し、その中にオブジェクトファイル、実行ファイルを作成する
(ディレクトリ構成)

トップディレクト
- main(DEBUGシンボル未定義)
- Makefile2
- main_debug(DEBUGシンボル定義)
- Makefile3
- src
|- main.c |- hoge.c |- piyo.c
- Makefile1
(Makefile1)
release_build :
	cd main; ${MAKE}

test_build :
	cd main_debug; ${MAKE}

clean :
	rm -f *~
	cd main; make clean
	cd main_debug; make clean
(Makefile2)
OBJS = main.o hoge.o piyo.o

main : ${OBJS}
	${CC} -o $@ ${OBJS}

main.o : ../src/main.c
	${CC} ${CFLAGS} -c $<

hoge.o : ../src/hoge.c
	${CC} ${CFLAGS} -c $<

piyo.o : ../src/piyo.c
	${CC} ${CFLAGS} -c $<

clean : 
	rm -f main *.o *~
(Makefile3)
OBJS = main.o hoge.o piyo.o
CFLAGS = -DDEBUG

main : ${OBJS}
	${CC} -o $@ ${OBJS}

main.o : ../src/main.c
	${CC} ${CFLAGS} -c $<

hoge.o : ../src/hoge.c
	${CC} ${CFLAGS} -c $<

piyo.o : ../src/piyo.c
	${CC} ${CFLAGS} -c $<

clean : 
	rm -f main *.o *~
(実行結果) (DEBUGシンボルを定義しない時)
[kobakoba0723@fedora13-intel64 symbol]$ make release_build
cd main; make
make[1]: ディレクトリ `main' に入ります
cc  -c ../src/main.c
cc  -c ../src/hoge.c
cc  -c ../src/piyo.c
cc -o main main.o hoge.o piyo.o
make[1]: ディレクトリ `main' から出ます
(DEBUGシンボルを定義した時)
[kobakoba0723@fedora13-intel64 symbol]$ make test_build
cd main_debug; make
make[1]: ディレクトリ `main_debug' に入ります
cc -DDEBUG -c ../src/main.c
cc -DDEBUG -c ../src/hoge.c
cc -DDEBUG -c ../src/piyo.c
cc -o main main.o hoge.o piyo.o
make[1]: ディレクトリ `main_debug' から出ます