Makefileを書いてみる.2
前回の復習
Makefileの基本的な文法は以下のようなものだった。
# Makefile
ターゲット: 依存ファイル1 依存ファイル2 依存ファイル3
コマンド行1
コマンド行2
コマンド行3
そして一例として
#Makefile hello: hello.o thank.o gcc -o hello hello.o thank.o hello.o: hello.c gcc -c hello.c thank.o: thank.c gcc -c thank.c
を作成してmakeした。このMakefileの実行ファイルhelloをビルドする箇所に注目すると、"hello"という文字列と"hello.c"という文字列が2回ずつ登場している。複数回書くのは面倒。
自動変数?
どうせコマンド行にはターゲットと依存ファイルが登場するのだから、GNU makeに自動的に指定してもらえば楽。その役割を担うのが自動変数らしい。わかりやすい自動変数に示す。
$@ | ターゲットファイル名 |
$< | 依存ファイル1 |
$^ | すべての依存ファイル |
(例)自動変数を使ってMakefileを書き直したい
Makefileを以下のように書き直してみる(beforeとafterを示す)。
#Makefile (before) hello: hello.o thank.o gcc -o hello hello.o thank.o hello.o: hello.c gcc -c hello.c thank.o: thank.c gcc -c thank.c #Makefile (after) hello: hello.o thank.o gcc -o $@ $^ hello.o: hello.c gcc -c $< thank.o: thank.c gcc -c $<
afterをmakeするとbeforeのときと同じ結果が得られる。
マクロの定義方法?
今までは、Makefileにファイル名を直接書いていたけれど、マクロを使うと他への流用がしやすくなる。マクロの定義の仕方は
マクロ名 = 文字列
で、マクロの参照の仕方は
$(マクロ名)
である。
(例)マクロを使ってMakefileを書き直したい
Makefileを以下のように書き直してみる。
#Makefile (before) hello: hello.o thank.o gcc -o $@ $^ hello.o: hello.c gcc -c $< thank.o: thank.c gcc -c $< #Makefile (after) OBJS = hello.o thank.o hello: $(OBJS) gcc -o $@ $^ hello.o: hello.c gcc -c $< thank.o: thank.c gcc -c $<
これをmakeするとbeforeのときと同じ結果が得られる。
定義済みマクロ?
Makefileで、コンパイラやアセンブラなどのツールを何度も指定するのも面倒で流用しにくい。それを回避できるようGNU makeでは定義済みマクロが用意されている。いくつか紹介する。
AR | アセンブラ |
ARFLAGS | ARの引数 |
CC | Cコンパイラ |
CFLAGS | CCのオプションフラグ |
RM | ファイルの削除 |
(例)定義済みマクロを使ってMakefileを書き直したい
Makefileを以下のように書き直してみる(さっきまでと違って、beforeに中間ファイルを削除するcleanが追加されていることに注意)。
#Makefile (before) OBJS = hello.o thank.o hello: $(OBJS) gcc -o $@ $^ hello.o: hello.c gcc -c $< thank.o: thank.c gcc -c $< clean: rm -f $(OBJS) #Makefile (after) OBJS = hello.o thank.o CC = gcc hello: $(OBJS) $(CC) -o $@ $^ hello.o: hello.c $(CC) -c $< thank.o: thank.c $(CC) -c $< clean: $(RM) $(OBJS)
これをmakeしたりmake cleanするとbeforeのときと同じ結果が得られる。
サフィックスルール?
上のMakefileでは、cファイルを.oファイルに変換するコマンドをファイルごとに毎度書いていた。.しかし、cファイルから.oファイルを作るルールを決めてしまえば、何度も書く必要がなくなるはず。このルールをサフィックスルールという。サフィックスルールの定義の仕方は以下の通り(サフィックスルールは.cから.oへの変換だけでなく、任意の拡張子間の変換で定義できる)。
.SUFFIXES: .変換前の拡張子.変換後の拡張子
変換前の拡張子.変換後の拡張子:
コマンド
(例)サフィックスルールを使ってMakefileを書き直したい
Makefileを以下のように書き直してみる。
#Makefile (before) OBJS = hello.o thank.o CC = gcc hello: $(OBJS) $(CC) -o $@ $^ hello.o: hello.c $(CC) -c $< thank.o: thank.c $(CC) -c $< clean: $(RM) $(OBJS) #Makefile (after) OBJS = hello.o thank.o CC = gcc .SUFFIXES: .c.o .c.o: $(CC) -c $< hello: $(OBJS) $(CC) -o $@ $^ clean: $(RM) $(OBJS)
これで、「hello.oがない→依存ファイルはhello.cに違いない→hello.cから決められたルールでhello.oを作る」ということを自動でしてくるようになった。