S-JIS[2006-05-29/2012-11-18] 変更履歴

make(ちょっと発展した内容)

makeコマンドおよびmakefileの書き方の中級編。


makeの実行方法

$ make -f ファイル

「makefile」でない名前のファイルも使える。


makefileの対象の指定

makefileの中には、複数のターゲットを指定できる。
そしてmakeコマンドの引数で、特定のターゲットだけを実行できる。

makefile:
all: a.out

a.out: test.c

install:
	cp -p a.out /usr/bin/hoge

clean:
	rm a.out
実行例:
$ make
$ make install
$ make clean

別のmakefileの読み込み

makefileの中から、さらに別のmakefileを読み込める。

include ../common.mk

変数の加工

変数の内容の一部分を変更できる。

文法 説明
$(name:old=new) $(name)の各語の末尾のoldnew置き換えるoldに一致しない場合は何もしない。
SRCS = foo.c zzz.c head.h
OBJS = $(SRCS:.c=.o)

OBJS = foo.o zzz.o head.h
$(name:op%os=np%ns) $(name)の各語に対し、先頭のopと末尾のosを削除して、先頭にnp, 末尾にnsを付加する。
(old, new, prefix, suffix)それぞれは省略可能。
NAME = sample
FILE = $(NAME:%=/tmp/%.txt)

FILE = /tmp/sample.txt

テキスト変形関数

makefileでは、文字列を加工する関数が用意されている。[2012-11-18]

$(関数 引数)
${関数 引数}

参考: ecoop.netのテキスト変形関数

テキスト変形関数の例
関数名 説明
wildcard ワイルドカードを展開する(ファイル一覧を取得する)。
SRCS = ${wildcard $(SRC)/*.c}
変数SRCSに、SRCの下の拡張子cのファイル一覧が入る。
shell make外部のコマンドを実行する。
EXAMPLE = ${shell cat zzz.txt}
変数EXAMPLEにzzz.txtの中身が入る。

動的マクロ(Dynamic Macros)

以下のような文法に対し、自動的に設定される変数(自動変数)がある。

ターゲット: 生成元
	コマンド
変数 説明
$@ ターゲット
ターゲットが複数指定されている場合はコマンドが複数回実行されるので、そのときの作業対象のターゲットになる。
target1 target2 : dependency
	echo $@

1回目の$@は「target1」、2回目は「target2

$* ターゲットと生成元に「%」を使った場合の、「%」に一致した部分。
%.o: %.c
	echo $*

test.o: test.c」ならば、$*は「test

$< ターゲットと生成元に「%」を使った場合の、それに一致した生成元。
%.o: %.c hoge.h
	echo $<

test.o: test.c hoge.h」ならば、$<は「test.c

生成元に複数の「%」が使われていた場合は、最初の1つ。
%.dst: hoge.src0 %.src1 %.src2
	echo $<

test.dst: hoge.src0 test.src1 test.src2」ならば、$<は「test.src1

$? 生成元のうち、ターゲットより新しいもの全て。  

これらの動的マクロでは、末尾にD,Fを付けて一部分だけを取り出すことが可能。
複数の値を持っている変数の場合は、それぞれの値に適用される。

記号 説明
D ディレクトリ部分
ディレクトリ部分が無い場合は「.
コマンド $(@D)

$@のディレクトリ部分

F ファイル部分
コマンド $(@F)

$@のファイル名部分

参考: ecoop.netの自動変数 [2012-11-18]


変数の加工も組み合わせると、かなり複雑に出来る(苦笑)

$(OBJPATH)/%.o : %.c $(HEAD)
	$(CC) $(CFLAGS) -c $(@F:.o=.c) -o $@

$(@F:.o=.c)」は、$@(ターゲット)ファイル名部分拡張子.o.cに置き換えたもの。

$(OBJPATH)が「/tmp」で %が「test」だったとすると 、
$@は「/tmp/test.o
$(@F)は「test.o
:.o=.cによって「test.c
となる。

なお、この例の場合は素直に$<(ソース)と同じ。


デフォルトのコンパイル方法

ターゲット・生成元やコマンドを指定しなくても、デフォルトで拡張子を元にコンパイル方法が規定されている。

これは、C言語関連の場合、以下のような指定が自動的に定義されているということ。

.SUFFIXES: .c .o

CC	 = cc
CFLAGS	 =
CPPFLAGS	 =
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
LINK.c	 = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)

.c.o:	$(COMPILE.c) $(OUTPUT_OPTION) $<
定義 内容 備考
.SUFFIXES 自動で処理を行う拡張子を列挙する。  
CC Cコンパイラのコマンド。COMPILE.cで使用。  
CFLAGS Cコンパイラのオプション。 上記のデフォルトでは空。
CPPFLAGS C言語のプリプロセッサのオプション(たぶん) 上記のデフォルトでは空。
COMPILE.c C言語のコンパイルコマンド。 この変数の場合、「.c」はソースの拡張子ではなく、C言語を意味している。
.c.o ソースの拡張子と変換後の拡張子の組。
この右側のコロン以降にコマンドを書く。
いわば、「%.o: %.c/コマンド」と同等。

したがって これらの一部を書き換えてやれば、定義を全て書かなくても自分の好きなように変更できる。
例えばCCを「gcc」にしてやれば、コンパイラがgccになる。


実行コマンドの接頭辞

実行するコマンドの先頭に、どうコマンドを実行するかを指定することが出来る。

定義 内容
@ 実行するコマンドを表示しない。
ターゲット: 生成元
	@echo 実験

「実験」だけ表示される。

- 実行したコマンドがエラー(0以外のエラーコードを返した)でもmakeを続行する。
ターゲット: 生成元
	-rm hoge
	@cp src hoge
	@-echo end

rmが失敗しても、cpを実行する。

コマンドの先頭が「@-」であれば、両方の指定が有効。


初心者向けmakeへ戻る / UNIXコマンドへ戻る / 技術メモへ戻る
メールの送信先:ひしだま