make は、複数のマクロをターゲット単位で動的に管理します。動的なマクロは、特に暗黙の規則の定義において頻繁に使用されます。マクロの意味を理解することは重要です。
動的なマクロは、メークファイルで明示的に定義されていないため、$ 記号を接頭辞として追加して (つまり、マクロ参照であることを示して) 記述します。
動的なマクロは、以下のとおりです。
現在のターゲットの名前です。
ターゲットよりも新しい依存関係のリストです。
make が暗黙の規則を使用するときの依存ファイル名を示します。
現在のターゲットのベース名 (接尾辞を除いたターゲット名) です。
処理されるライブラリメンバーの名前を示します。詳細は、「オブジェクトライブラリの構築」を参照してください。
暗黙の規則は、ターゲット名または依存ファイル名を規則内のコマンド行に指定するために、これらの動的なマクロを使用します。以下の .c.o の規則を例として示します。
.c.o: $(COMPILE.c) $< $(OUTPUT_OPTION)
$< は、現在のターゲットの依存ファイル (この場合は .c ファイル) の名前に置換されます。
OUTPUT_OPTION
というマクロは、デフォルトでは値が空です。このマクロは、CFLAGS
と同様の機能を持っていますが、引数を -o コンパイラオプションに渡してコンパイラの出力先ファイル名を指定するための独立したマクロとして提供されています。
この .c の規則では、$@ は現在のターゲット名に置換されます。
.c: $(LINK.c) $< -o $@
$< および $* のいずれのマクロも、接尾辞のリストでの順序に応じて値が異なるため、明示的なターゲットのエントリでこれらのマクロを使用すると予期しない結果になる場合があります。関連するファイル名からファイル名を正確に取得する方法については、「マクロ参照での接尾辞の置換」を参照してください。
F および D を参照に含めることによって動的なマクロを修飾できます。処理されるターゲットがパス名で指定されている場合は、$(@F) はファイル名部分、$(@D) はディレクトリ部分をそれぞれ示します。ターゲット名に / という文字が含まれていない場合は、$(@D) にドット (.) が値として割り当てられます。たとえば、/tmp/test という名前のターゲットでは、$(@D) の値は /tmp、$(@F) の値は test になります。
動的なマクロは、すべてのどのようなターゲットを処理する際にも割り当てられます。マクロは、ターゲットの規則ではそのまま、依存関係リストでは参照の先頭に $ を追加して使用できます。$$ で始まる参照を、マクロへの遅延参照と呼びます。以下に例を示します。
x.o y.o z.o: $$@.BAK cp $@.BAK $@
このエントリは、x.o.BAK、y.o.BAK、z.o.BAK からそれぞれ x.o、y.o、z.o を取得するために使用できます。
遅延マクロ参照を使用できるのは、make が、メークファイル全体を最初に読み込む際と、ターゲットの依存関係を処理する際の合計 2 回依存関係リストを読み込むためです。make は、リストを読み込むたびにマクロ展開を実行します。動的なマクロは、マクロへの参照が 2 回目の読み取りまで遅延される場合を除き、最初の読み取りではまだ定義されていないため、空の文字列に展開されます。
$$ という文字列は、定義済みマクロの '$
' への参照です。このマクロは値が '$' になっています。make が最初の読み取りでこのマクロを展開する際には、$$@ は $@ に展開されます。依存関係の検査では、その $@
というマクロ参照に動的に値が割り当てられるときに、make は参照をその値に展開します。
make は、最初の読み取りではターゲットのターゲット名部分だけを評価します。ターゲット名として遅延マクロ参照を使用すると、正しい結果が得られません。
NONE= none all: $(NONE) $$(NONE): @: this target's name isn't `none'
このメークファイルは、以下のような結果になります。
$ make make: Fatal error: Don't know how to make target `none'
make は、規則の実行時にそのコマンドの適用ごとに 1 回だけ、ターゲットエントリの規則部分を評価します。この場合も、make への遅延マクロ参照を使用すると誤った結果になります。
接尾辞の規則では、複数の規則の関係から自動的にそれらの中間の規則を生成するということはありません。たとえば、接尾辞が .X というファイルから接尾辞が .Y というファイルを構築する接尾辞の規則と、接尾辞が .Y というファイルから接尾辞が .Z というファイルを構築する規則がある場合に、make は .X ファイルから .Z ファイルを作成するという規則を、上記 2 つの規則から生成するということは行いません。中間の処理をターゲットとして指定する必要があります。中間の処理のエントリには空の規則を使用できます。
trans.Z: trans.Y:
この例では、trans.Y が存在していれば trans.Z はそのファイルから構築されます。trans.Y がターゲットエントリとして記述されていない場合は、使用する依存ファイルがないために make が "don't know how to build" というエラーを表示して失敗する場合があります。trans.Y がターゲットエントリとして記述されている場合は、trans.Y が最新でないまたは存在しないときに、make が trans.Y を構築します。メークファイルで規則が指定されていないため、make は適切な暗黙の規則を使用します。この場合は .X.Y の規則が使用されます。trans.X が存在する (または SCCS から取り出すことができる) 場合に、make は trans.Y および trans.Z の両方を必要に応じて再構築します。