標準的なターゲットファイル更新の手法の中にはかなり頻繁に使うものもあります。例えば、オブジェクトファイルを作成するにはcc
というCコンパイラを使ってCソースファイルから作るという方法が習慣的なものの一つです。
習慣的な技術の利用方法をわざわざ詳細に指定しなくてもいいようにmake
に伝えてくれるものが暗黙のルールです。例えばCコンパイル作業に働く暗黙のルールがあります。ファイル名でどの暗黙ルールが実行されるのかが決定されるのです。例えばCのコンパイル作業では典型的に`.c'ファイルを受け取り`.o'ファイルを作成します。だからこの二つで終わるファイル名の組を見つけるとmake
はCコンパイルを行う暗黙ルールを適用します。
暗黙ルールの連鎖が次々に適用されることもあります。例えば`.o'ファイルを更新するのに`.y'ファイルを使う場合それを`.c'のつもりで更新します。 これについては暗黙ルールの連鎖の項を見て下さい。
ビルトインの暗黙ルールではコマンドの実行に変数をいくつか使っているため、その変数の値を変更すれば暗黙ルールの動作を変更できます。例えばCFLAGS
という変数は暗黙ルールでのCコンパイル作業でCコンパイラに渡すフラグを制御しています。
これについては暗黙ルールで用いられる変数の項を見てください。
型ルールを書けば自分で暗黙ルールを定義することもできるようになります。これについては型ルールの定義と再定義の項を見て下さい。
サフィックスルールでも暗黙ルールを定義できますがこちらは前のものより限られた用途になります。型ルールのほうがきれいですし一般的なのですが、サフィックスルールは互換性のために残されています。 これについては古いタイプのサフィックスルールの項を見て下さい。
make
に習慣的なターゲットファイル更新方法を探させるにはただ自分でコマンドを書くのを控えるだけでいいのです。つまりコマンド行を全く書かないルールを記述するか、一つのルールについては少しもルールを書かないかのどちらかにして下さい。そうすればmake
がどの暗黙ルールを利用するかを、どういう種類のソースファイルがあるか、またはどのソースファイルが更新可能か、という事に基づいて識別してくれるでしょう。
例えばmakefileがこのような感じだったとすると…
foo : foo.o bar.o cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
`foo.o'について言及しているにもかかわらずそれについてのルールを与えていないため、make
が自動的に更新方法を指示する暗黙のルールを探すことになります。これは`foo.o'が存在するかどうかによらず動作します。
暗黙のルールが発見され次第、コマンドと一つ以上の依存関係(ソースファイル)に供給されます。`foo.o'についてコマンドなしのルールを書きたくなる場合というのは、ヘッダファイルのような暗黙ルールでは供給されない依存関係を追加指定する必要がある場合だと思います。
それぞれの暗黙ルールにはターゲットの型と依存関係の型があって、多くの暗黙ルールに同じターゲット型を持たせることも可能です。例えば`.o'ファイルを作成するルールが多数あり、一つはCコンパイラで`.c'ファイルから作成するもの、もう一つはPascalコンパイラで`.p'から作成するもの…というようになります。実際に適用されるルールはその依存関係が存在したり作成可能な一つだけです。だから`foo.c'というファイルがあればmake
はCコンパイラを実行しますし、そうでなくて`foo.p'というファイルがあるのならmake
が実行するのはPascalコンパイラ、そうでなければ同じターゲット型の次のルール、というようになります。
もちろんあなたがmakefileを記述する時はどの暗黙ルールをmake
に使わせたいかわかっていて、関係する依存関係が全部存在することになるのが分かっているのでその使わせたいものが選択されるかを知っていることでしょう。暗黙ルールのカタログの項を見れば予め定義された全ての暗黙ルールのカタログがあります。
上で言いたかったのは、ある暗黙ルールで要求される依存関係が「存在するか作成可能」であればそのルールが適用される、という事です。あるファイルがmakefileの中の明示的なターゲットか依存関係である場合、またはある暗黙ルールで再帰的にそのファイルの作成方法を示しているなら、そのファイルは「更新可能」になります。ある暗黙の依存関係が別の暗黙ルールの結果であるなら、連鎖と呼ばれるものが起こります。 これについては暗黙ルールの連鎖の項を見て下さい。
一般的にmake
はコマンドを持たない「ターゲットと二重コロンルール」のそれぞれに対して暗黙ルールを探します。依存関係でしか書かれていないファイルはルールのないターゲットとみなすので、これにも暗黙ルールの検索が行われます。どう検索をするのかの詳細は暗黙ルールの検索アルゴリズムの項にあります。
注意:明示的な依存関係は暗黙ルールの検索に影響しません。例えば次の明示ルールについて考える場合…
foo.o: foo.p
`foo.p'の依存関係はmake
がオブジェクトファイル(`.o'ファイル)をPascalソースファイル(`.p'ファイル)から作成させる暗黙ルールを使って`foo.o'を更新するということを示す必要はありません。例えばもし`foo.c'も存在するならCソースファイルからオブジェクトファイルを作成する暗黙ルールが代わりに利用されます。これはPascalルールよりもこちらのほうが前定義暗黙ルールのリストの中で先にあるためです(暗黙ルールのカタログの項を参照)。
コマンドのないターゲットに暗黙のルールを使わせないようにするにはセミコロンを使ってターゲットに空っぽのコマンドを与えて下さい(空のコマンドの利用の項を参照)。
makefileで明示的に上書きするかキャンセルさせない限り常に有効な前定義の暗黙ルール(Predefined Implicit Rules)のリストをここに示します。暗黙のルールのキャンセルや上書きについての情報は暗黙のルールをキャンセルするの項を見て下さい。`-r'オプションか`--no-builtin-rules'オプションで全ての前定義ルールをキャンセルします。
`-r'オプションが与えられていない場合でも全ての暗黙ルールが定義されるというわけではありません。前定義の暗黙ルールの多くはmake
の内部でサフィックスルールとしてインプリメント(履行)されているので、そういうものはサフィックスリスト(.SUFFIXES
という特別なターゲットの依存関係のリスト)によって定義されます。デフォルトのサフィックスリストは次のようになります。
.out
, .a
, .ln
, .o
, .c
, .cc
,
.C
, .p
, .f
, .F
, .r
, .y
,
.l
, .s
, .S
, .mod
, .sym
, .def
,
.h
, .info
, .dvi
, .tex
, .texinfo
,
.texi
, .txinfo
, .w
, .ch
.web
,
.sh
, .elc
, .el
。
これらサフィックスのうち一つを依存関係として持っている、以下に述べた暗黙のルールはどれも実際にはサフィックスルールです。サフィックスリストを修正した場合、前定義のサフィックスルールのうち有効なものは指定したリストにサフィックスが最低一つあるものだけになり、リストに一つもサフィックスがないルールは無効になります。サフィックスルールについての全詳細は古いタイプのサフィックスルールの項にあります。
as
というアセンブラを実行して`n .s'から作成する。正確なコマンドは`$(AS) $(ASFLAGS)'。
`n .s'を自動的にcpp
というCプリプロセッサを実行して`n .S'から作成する。正確なコマンドは`$(CPP) $(CPPFLAGS)'。
ld
という)リンカを実行して`n .o'から作成する。利用する正確なコマンドは`$(CC) $(LDFLAGS) n .o $(LOADLIBES)'。
このルールは一つのソースだけで一つのプログラムを作るのに見合うルールです。それに(多分種々多様なソースファイルから作成された)複数のオブジェクトファイルがあり、うち一つが実行可能なファイルの名前である場合も正しい事をやってくれるでしょう。だから、
x: y.o z.o…として、`x.c'と`y.c'と`z.c'のどれもが存在していれば次のものを実行することになります。
cc -c x.c -o x.o cc -c y.c -o y.o cc -c z.c -o z.o cc x.o y.o z.o -o x rm -f x.o rm -f y.o rm -f z.oさらに複雑なケースは、実行可能ファイル名に由来する名前を持つオブジェクトファイルがないような場合があげられます。この場合、リンクさせる明示的なコマンドを記述しなければなりません。 `.o'オブジェクトファイルに自動的に作成されるような類のファイルはそれぞれ`-c'オプションをつけずにコンパイラ(`$(CC)'、`$(FC)'、`$(PC)'の何れかで、`$(CC)'というCコンパイラは`.s'ファイルをアセンブルするのにも使います)を使って自動的にリンクされる事になるでしょう。`.o'オブジェクトファイルを中間ファイルとして使ってこの作業を行ったほうがコンパイルとリンクの作業が一歩速くなるため、こうされる事もあります。
make
は二つの言語のうちどちらを使っているか個々に自動的に判断する事ができません。make
を`.l'からオブジェクトファイルを更新するために呼び出す場合、どちらのコンパイラを使うか内部で推測しなければなりませんが、Cコンパイラのほうがより一般的であるためこちらであると推測することになります。Ratforを使っている場合、`n .r'とmakefileで書いてmake
にちゃんとこの事を知らせて下さい。またはCファイルではなくて専らRatforを使われる方は暗黙ルール・サフィックスのリストからこうやって`.c'を削除して下さい。
.SUFFIXES: .SUFFIXES: .o .r .f .l ...
lint
を実行して`n .c'から作成する。正確なコマンドは`$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i'。
同じコマンドが`n .y'か`n .l'から生成されたCコードにも利用されます。
普通は上の表でリストされた変数を変更したがると思います。この方法については後に続く項に述べています。
ですが、ビルトインの暗黙ルール中のコマンドというのは実際にはCOMPILE.c
やLINK.p
、PREPROCESS.S
のような変数を利用し、その値は上でリストしたコマンドを含むものになります。
make
は`.x 'ソースファイルをコンパイルするルールではCOMPILE.x
という変数を使う、という慣習に従っています。
同じく`.x 'ファイルから実行可能ファイルを生産するルールではLINK.x
を、`.x 'ファイルからプリプロセス処理するルールではPREPROCESS.x
を使います。
オブジェクトファイルを生産するルールはどれもOUTPUT_OPTION
という変数を使っています。make
はコンパイル時オプションによって`-o $@'を含めるか、空っぽかのどちらかで変数を定義します。ソースファイルが別のディレクトリにある時はVPATH
を利用する場合と同様に`-o'オプションをつけて出力ファイルが正しいファイルであることを確実にする必要があります(ディレクトリから依存ファイルを探すの項を参照)。ですがオブジェクトファイルを作成するのに`-o'スイッチを受け付けないシステムのコンパイラもあります。こういうシステムを利用していてVPATH
を使う場合、コンパイラ作業で間違った場所に出力してしまう事になるでしょう。この問題の代替手法としてOUTPUT_OPTION
に`; mv $*.o $@'という値を与えてください。
ビルトインの暗黙ルール中にあるコマンドを使えば前定義の変数を自由に利用できます。makefile中、make
の引数、環境のいずれかの方法で変数を変えれば暗黙のルールを再定義しなくても暗黙のルールの動作を変えることができます。
例えば、Cソースファイルのコンパイルに使われるコマンドでは実際は`$(CC) -c $(CFLAGS) $(CPPFLAGS)'と命令します。利用されている変数のデフォルトの値は`cc'と何もないものなので`cc -c'というコマンドを使います。`CC'を`ncc'で再定義すれば暗黙のルールで行われるどのCコンパイルでも`ncc'を実行するようになります。`CFLAGS'の中身がAMP>`-g'になるように再定義すれば各コンパイル作業で`-g'オプションを渡すようになります。`$(CC)'は全ての暗黙ルールでCのコンパイル作業でコンパイラプログラム名称を得るのに利用しており、また`$(CFLAGS)'は全ての暗黙ルールでCコンパイラに渡す引数としてインクルードされます。
暗黙のルールに用いられる変数は大別すると二種類に落ち着きます。うち一つは(CC
のような)プログラム名称、もう一つは(CFLAGS
のような)プログラムへの引数を格納するものです。(「プログラム名称」にコマンド引数がいくつか含まれる事もあり得ますが、必ず実際に実行可能なプログラム名称から始まっていなければいけません。)変数に一つ以上の引数を値として格納させるにはスペースで区切って下さい。
ここにビルトイン・ルールでプログラム名称として使われている変数の表を示します。
AR
AS
CC
CXX
CO
CPP
FC
GET
LEX
PC
YACC
YACCR
MAKEINFO
TEX
TEXI2DVI
WEAVE
CWEAVE
TANGLE
CTANGLE
RM
次に上のプログラムに追加の引数を渡すのに使う変数の表を示します。個別に書いていないものについては全ての変数のデフォルト値は空っぽの文字列です。
ARFLAGS
ASFLAGS
CFLAGS
CXXFLAGS
COFLAGS
co
というRCS用プログラムに与える追加フラグ。
CPPFLAGS
FFLAGS
GFLAGS
get
というSCCS用プログラムに与える追加フラグ。
LDFLAGS
LFLAGS
PFLAGS
RFLAGS
YFLAGS
暗黙ルールの連続実行でファイルを作成する場合が時折あります。例えば`n .o'というファイルを`n .y'から作成する場合、まずはじめにYaccを実行し、その次にcc
、となるでしょう。こういう連続実行を連鎖といいます。
`n .c'が存在するか、このことについてmakefileで書いている場合は特別な検索作業が要求される事がなく、make
は`n .c'をCコンパイルすればこのオブジェクトファイルが作成できるのに気づいて、その後`n .c'を作成する方法について模索した時にYaccを実行するルールを利用してくれます。それで最終的に`n .c'と`n .o'の両方が更新されることになります。
ですが`n .c'が存在せずそれについて何も書かれていない場合でさ、え、`n .o'と`n .y'の処理間のつながりが欠落した部分(ミッシングリンク)を想定する術をmake
は知っているのです! この場合は`n .c'は中間ファイルと呼ばれます。ひとたび中間ファイルの用途を決めてしまえばmake
はそれがmakefileで書かれていた場合と同じように、作成方法を指示する暗黙ルールと一緒にデータベースに格納します。
中間ファイルに対しては、他のどのファイルとも全く同じように、作成させるルールを用意して更新します。ただし中間ファイルの扱いについては相違点が二点あります。
第一に中間ファイルが存在しない時には他のファイルと違う動作になります。b という普通のファイルが存在しない時にb に依存するターゲットを処理する場合、make
は相変わらずにb を作成してb からターゲットを更新します。ところがb が中間ファイルの場合make
は処理を実行しなくてもいいのです。b を更新しなくても良い場合というのはb の依存関係が最終目標のターゲットより新しくなく、ターゲットを更新するような理由が他にない場合です。
第二にmake
が他の何かを更新するためにb を作成する場合に、b が必要でなくなり次第削除されるという点が違います。そのため、make
実行前に存在していなかった中間ファイルはmake
実行後も存在しない事になります。どのファイルを削除したか、というのはmake
が`rm -f'コマンドを出力して報告してくれます。
普通はmakefileでターゲットか依存関係として書かれているファイルは中間ファイルになり得ませんが、.INTERMEDIATE
という特別なターゲットの依存関係として中間ファイルとさせたいファイルを明示的にリストしておけばmakefileに書かれているファイルについても中間ファイルにできます。この手法は他の方法で明示的に述べられたファイルについても効果があります。
派生(secondary)ファイルとしてマークしておけばその中間ファイルの自動削除を防ぐ事が可能です。マークするには.SECONDARY
という特別なターゲットの依存関係として記述して下さい。ファイルが派生である場合、既存のファイルではないからという理由だけでファイルを作成しなくなり、make
が自動削除することもなくなります。派生ファイルとしてマークしたファイルは同時に中間ファイルとしても扱われることになります。
(`%.o'のような)暗黙ルールのターゲットの型を.PRECIOUS
という特別なターゲットの依存関係に記述すると、ターゲットの型が一致するファイル名を持つ中間ファイルが暗黙ルールで作成された場合に保存するようになります。これについては
make
を邪魔するか中断させるの項を見て下さい。
3つ以上の暗黙ルールが一度に連鎖発動する事もあります。たとえば`RCS/foo.y,v'から`foo'を作ることもできますがこの場合はRCS、Yacc、cc
を実行します。`foo.y'と`foo.c'の二つは中間ファイルなので最後に削除されます。
一度の連鎖で一つの暗黙ルールが何度か起こるという事はありえません。なぜなら`foo.o.o'から`foo'を作るのにリンカを二度も実行するような馬鹿げた事をmake
は考えないからです。これを強制させているお蔭で暗黙ルールの連鎖の検索において無限ループが起こる事がない、という利点があります。
別の方法によってルールの連鎖で処理しているものを最大限に利用するための特別な暗黙ルール、というのもあります。例えば`foo.c'から`foo'を作るにはコンパイルとリンクを二つのわけ隔てられたルールを`foo.o'を中間ファイルとして使って連鎖させて処理することが可能ですが、実際にはこのケースのための特別なルールでcc
コマンドを一つ使うだけでコンパイルとリンクを行ってくれます。オプティマイズ(最大限に利用する)ルールを使えばルールを順番に連鎖するよりも速くなるので、オプティマイズルールが優先的に使われます。
型ルールを書けば暗黙のルールをあなた自身で定義する事ができます。型ルールはターゲット(のうち、正確には一つ)が`%'という文字を含んでいるという事意外は普通のルールと同じです。この文字を含んだターゲットはファイル名を一致させるための型として認識され、`%'の部分は空っぽでなければどんな部分文字列にも一致し、かつ一方でその他の文字は全く一致していなければなりません。同様に`%'を使った依存関係ではターゲット名にどういう名前が関連しているか、という事を示します。
だから`%.o : %.c'という型ルールは`語幹 .c'という全てのファイルから`語幹 .o'という別のファイルを作成する方法を命令します。
注意:型ルールの`%'の展開は、makefile読み込み時の変数・関数の展開が全部終わった後に行われます。これについては変数の利用法の項とテキスト変形関数の項を見て下さい。
型ルールではターゲット(のうちの一つ…正確には。)に`%'という文字を含んでいて、これを含んでいなければ普通のルールと全く同じになってしまいます。型ルールのターゲットはファイル名に一致させる型で、普通の文字の部分はそれ自身と同じ文字を一致させなければなりませんが、`%'には空っぽでさえなければどういう部分文字列にも当てはまります。
例えば`%.c'は、`.c'で終わるどのファイル名にも一致する型です。また`s.%.c'は、`s.'で始まり`.c'で終わり、長さが5文字以上の全てのファイル名に一致する型です。(`%'に一致させるのは一文字以上でなければならない。) `%'に一致する部分の文字列を語幹(stem)といいます。
型ルールの依存関係に`%'を使うと、ターゲットの`%'で一致した語幹と同じものを表すようになります。型ルールを適用するには、ターゲット型に当てはまるファイル名があり、さらに依存関係の型で(ターゲット一致の結果)命名されるファイルが存在しているか作成できるものでなければならず、それにも当てはまる場合そのファイルがターゲットの依存関係になります。
だから次のようなルールでは…
%.o : %.c ; command ...
依存関係にある`n .c'というファイルが存在するか作成可能な場合に`n .c'から`n .o'というファイルを作成する方法を指定しています。
型ルールで作成する全てのファイルに対して依存関係を添付したいような場合は`%'を使わない依存関係があっても構いません。そういう不変の依存関係が便利なこともありますから。
型ルールを書く上で`%'を含む依存関係を書く必要はありませんし、実際のところ依存関係自体必要ではなく、そういうルールは一般的なワイルドカードのようになります。つまりターゲット型に一致するどのファイルについても作成する方法を提供するようになる、という事です。これについては最後の手段を定義するデフォルトルールの項を見て下さい。
型ルールに一つ以上のターゲットを与えると、普通のルールとは違い「同じ依存関係とコマンドを適用するたくさんの異なるルール」のような振る舞いはしません。型ルールに複数のターゲットがある場合、make
は全てのターゲットについてそのコマンドがターゲット作成について重要なものだとわかっているので、全てのターゲットをまとめて一度にそのコマンドを使って作成します。あるターゲットに一致する型ルールを検索するとき、そのターゲットに一致するターゲット型を持つルールが他に持っている型ルールは付随扱いになります。つまりmake
は現在問題になっているファイルに対してのみコマンドと依存関係を与えるのですが、そのファイルのコマンドが実行される時に他のターゲットについてもそれ自身更新されている、という扱いになります。
makefileにある他の型ルールについても書かれている順番が判断の順番になるため重要なものです。等しく適用できるルールが見つかった場合最初のものだけを採用し、ビルトインと重複する場合あなたが書いたものを優先させますが、ここで注意しておいてほしいのは、他の場所で明記しているか実際に存在している依存関係のルールは常に暗黙ルールの連鎖で構成される依存関係のルールより優先扱いになります。
ここにmake
で実際に前定義されている型ルールの例を示します。まず始めに`.c'を`.o'ファイルにコンパイルするルールは、
%.o : %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
…であり、`x .o'というファイルは全て`x .c'から作成が可能である、と定義するルールです。コマンドに`$@'と`$<'という自動変数を使っているのはターゲットファイルの名前とソースファイルの名前をルールが適用されるそれぞれの箇所で読み替えさせるためです(自動変数の項を参照)。
二つ目のビルトインルールは…
% :: RCS/%,v $(CO) $(COFLAGS) $<
…というもので、`x ,v'というファイルが`RCS'というサブディレクトリ内にあればそのxに相当する`x 'というファイルを作成できるルールを定義します。`%'がターゲットなのでこのルールは充当する依存関係ファイルが存在するという条件に合いさえすればどんなファイルにも適用されます。二重コロンで書かれたルールなのでこのルールが終着点(terminal)になり、そのためこのルールの依存関係が中間ファイルになることはありません(「何でも一致」型のルールの項を参照)。
次の型ルールには二つのターゲットがあります。
%.tab.c %.tab.h: %.y bison -d $<
このルールでは`bison -d x .y'というコマンドが`x .tab.c'と`x .tab.h'の両方を作成するコマンドだと伝えます。`foo'というファイルが`parse.tab.o'と`scan.o'に依存していて、`scan.o'というファイルは`parse.tab.h'というファイルに依存している、という場合、`parse.y'が変更されると`bison -d parse.y'というコマンドを一度だけ実行して`parse.tab.o'と`scan.o'に対する処理を完了する事になります。(`foo'が`parse.tab.o'、`scan.o'や他の依存関係からリンクされる時に、おそらく`parse.tab.o'は`parse.tab.c'から、`scan.o'は`scan.c'から再コンパイルされ、以降適切に処理すべき事をやってくれるでしょう。)
`.c'ファイルから`.o'ファイルにコンパイルする型ルールを記述する際、正しいソースファイルに対して`cc'コマンドを実行するにはどう書けば良いのでしょうか? 暗黙ルールが実行される時々で名前が異なるため、コマンドに対しては名前を書けません。
自動変数というmake
の特別な機能を使えばそれが可能になります。この変数ではルールが実行されるその都度、ルールのターゲットと依存関係に基づいて値を計算します。上の問題では`$@'をオブジェクトファイル名に、`$<'をソースファイル名に利用します。
ここに自動変数の表を示します。
$@
$%
make
を利用するの項を見て下さい。例えば`foo.a(bar.o)'がターゲットの場合、`$%'は`bar.o'になり、`$@'は`foo.a'になります。ターゲットがアーカイブメンバではない場合`$%'は空っぽになります。
$<
$?
make
を利用するの項を参照)。
$^
make
を利用するの項を参照)。依存するファイルのそれぞれについて、依存関係として何度ファイルが並べられても一つのターゲットにつき一つだけの依存関係になります。だから、あるターゲットに対して一度以上以上依存関係として挙げても$^
の値にはその名前は一つしかコピーされません。
$+
$*
make
がこんな奇妙な動作をするのは他のmake
製品との互換性のためで、普通は暗黙ルールと静的な型ルールだけで`$*'を使うべきです。有効なサフィックスで終わらないターゲットを持つ明示ルールでは`$*'が空っぽになります。
変更のあった依存関係だけに作用させたい場合は明示ルールでも`$?'が便利です。例えば`lib'という名前のアーカイブにいくつかのオブジェクトファイルの複製版を格納させたいとすると、次のルールを使えば変更があったファイルだけをアーカイブにコピーしてくれます。
lib: foo.o bar.o lose.o win.o ar r lib $?
上で列挙した変数群のうち4つは一つのファイル名を値とするもので、2つはファイル名のリストを値としています。これら6つの変数にはファイルのディレクトリ名だけやディレクトリ内のファイル名だけを取得する変形版(バリアント)が存在します。それぞれの変数名に`D'か`F'を付加したものが変形版の変数名になります。実はGNU make
ではこれらの変形版というのはdir
とnotdir
という関数(ファイル名のための関数の項を参照)を使えば似たような効果を得られるのでやや時代遅れなのですが、ここで注意。変形版にする`F'を使った場合はdir
関数の出力で現れる全部の最後のスラッシュが省略される事を覚えておいて下さい。ここに変形版の表を示します。
注意:自動変数について述べる場合、objects
やCFLAGS
のような普通の変数の事を書くように「<
という変数」と書くのではなくて「`$<'の値」としたほうが自然に感じると思うので特別なケースとしてこういう特別な慣習に従っています。ですがくれぐれも`$(CFLAGS)'がCFLAGS
という名前の変数を参照するのと全く同じように`$<'が<
という名前の変数を参照しているのだ、というような深い意味があるとは考えないで下さい。`$<'の代わりに`$(<)'とするのは構いません。
ターゲット型はプリフィックス(接頭語)とサフィックス(接尾語)の間に`%'を挟んだもので構成され、両端が空っぽであっても構いません。型が一致するのは対象のファイル名が型のプリフィックスで始まり、同サフィックスで終わり、かつその二つが重複しない場合です。プリフィックスとサフィックスの間の文字列は語幹(stem)といいます。だから`%.o'という型に`test.o'というファイル名が引っかかった時は`test'が語幹になります。型ルールの依存関係は語幹が`%'という文字に代入されて実際のファイル名になります。つまり先の例で依存関係の一つが`%.c'と書かれていた場合は`test.c'が展開されます。
ターゲット型にスラッシュが含まれなければ(というか普通は含まれませんが)、ファイル名のディレクトリ名部分はターゲットのプリフィックスとサフィックスの比較が行われる前に削除されます。そのディレクトリ名は後で末尾のスラッシュと一緒に、ファイル名をターゲット型に比較する作業が終わってから型ルールの依存関係の型から生成されたファイル名と依存関係にもとからあるファイル名に付加されます。利用する暗黙のルールを検索する際だけはディレクトリ名が無視されますが、ルールを使用する時に無視されるわけではありません。つまり`e%t'は`src/eat'というファイル名に`src/a'という語幹で一致します。依存関係がファイル名に変わる時には語幹のディレクトリ部分は一番前に付加されて、一方残りの部分は`%'に代入します。`src/a'という語幹を`c%r'という依存関係の型に充てる場合はファイル名は`src/car'になります。
型ルールのターゲットがただ`%'だけの場合はファイル名が何であろうと一致するため、こういうルールを「なんでも一致(match-anything)」ルールと呼んでいます。こういうルールはとても便利ですがターゲットとして並んでいるファイルも依存関係として並んでいるファイルもとにかく全てのファイルについてこのルールが当てはまるか判断しなければならないため、make
の処理時間が増える事になってしまいます。
`foo.c'について書かれたmakefileを想定すると、このターゲットに対して`foo.c.o'というオブジェクトファイルからリンクして作成できるか、`foo.c.c'から一気にCコンパイルとリンクができないか、`foo.c.p'からPascalコンパイルとリンクができないか、などなどmake
はたくさんの可能性を考慮しなければならなくなるでしょう。
`foo.c'はCソースファイルであって実行可能ファイルではないのでこういう可能性は全く馬鹿げたものだということはわかり切っています。make
がこれらの可能性を調べても`foo.c.o'やら`foo.c.p'というファイルが存在しないはずなので最終的にその可能性を拒否することになるのですが、その可能性が非常に多数であるためそれをmake
が判断しなければならないと実行速度がかなり遅くなってしまいます。
速度向上のため、make
に「何でも一致」ルールを判断させる上でさまざまな事を強制させるようにしました。適用され得る強制は毛色の異なるものが二つ存在し、「何でも一致」ルールを定義する時は必ずそのルールに対してどちらか一つを選ばなければなりません。
一つ目の選択は「何でも一致」ルールを二重コロンで定義して終点(terminal)にしてしまう事です。ルールがそれで終点なら実在しない依存関係には適用されなくなり、別の暗黙ルールから作成できる依存関係には不適になります。言い換えればターミナル(終点)ルールではそれ以上の連鎖が許されません。
例えばRCSとSCCSファイルからソースを取り出すというビルトインの暗黙ルールは終点なので、結果として`foo.c,v'が存在しなければmake
はそれが中間ファイルとして作成しようとせず、そのため`foo.c,v.o'や`RCS/SCCS/s.foo.c,v'があっても関係ありません。RCSとSCCSは一般的に他のファイルからは作成されるべきではない最終的なソースファイルなので、make
はそれらを更新する方法を探さないようにして時間を節約できるのです。
「何でも一致」ルールを終点というしるしをつけなかった場合、それが終点ではなくなります。終点ではない「なんでも一致」ルールでは特定の形式のデータをさすファイル名は適用できません。特定な形式のデータをさすファイル名、とは「何でも一致」ではない暗黙ルールのターゲットに一致するファイル名の事で、そういうファイルには適用できません。
例えば、`foo.c'というファイル名は(Yaccを実行するルールである)`%.c : %.y'という型ルールのターゲットに一致します。(`foo.y'というファイルがある場合にのみ実行される)このルールが実際に適用できるかという事にかかわらず、ターゲットが一致するという事実だけで`foo.c'というファイルは終点ではない「何でも一致」ルールでは判断対象にならなくなります。だからmake
は`foo.c'が`foo.c.o'、`foo.c.c'、`foo.c.p'などから作成できる実行ファイルかという事を判断しなくて済むのです。
終点ではない「何でも一致」ルールでこの強制をさせるのは(実行可能ファイルのような)特定の形式のデータを含むファイルを作成するのには利用し、かつ(Cソースファイルのような)別の特定の形式のデータだと認識できるサフィックス(接尾語)を持つファイル名のファイル判別させる、という意図からです。
終点ではない「なんでも一致」ルールで判断対象とさせたくない種類のファイル名をただ識別させたいがために存在するダミー用の特別なビルトインの型ルールもあります。ダミーのルールでは依存関係もコマンドもなく、他の用途に際しては完全に無視されます。例えば次のビルトイン暗黙ルール…
%.p :
…は、`foo.p'のようなPascalソースファイルが特定のターゲット型であり、`foo.p.o'や`foo.p.c'を探す手間を省くために存在します。
`%.p'に対するようなダミーの型ルールは、サフィックスルール(古いタイプのサフィクスルールの項を参照)で使われる有効なサフィックス全てに対して作成されています。
ビルトインの暗黙ルール(または自分で定義したルール)を、同じターゲットと依存関係でコマンドだけ違う新しい型ルールを定義して上書きすることができます。新しいルールが定義されると暗黙のルールは置き換えられることになり、暗黙のルールの中のどの位置に新しいルールが入るのか、というのはどこに新しいルールを書いたかで決まります。
ビルトインの暗黙ルールをキャンセルするには同じターゲットと依存関係を持ち、コマンドが全くない型ルールを定義して下さい。例えば次のものはアセンブラを実行させるルールをキャンセルしてくれるでしょう。
%.o : %.s
最後の手段を示す暗黙のルールを定義するには、終点になる「なんでも一致」ルール(「何でも一致」型のルールの項を参照)を依存関係なしで書きます。他の型ルールとの唯一の相違点は、どんなターゲットにも一致する、という事だけですが、この相違点のためにこのルールのコマンドは、コマンドを持たないルールだが暗黙のルールに適用されないターゲットと依存関係の全てについて利用されるものになります。
例えばmakefileを実行する際ソースファイルがちゃんと中身があるかという事はどうでもよく存在していれば良いなら次のようにできます。
%:: touch $@
こうすると(依存関係として)必要とされる全てのソースファイルを自動的に作成します。
そうする代わりに「全くルールのないターゲットだけでなくコマンドを指定しないターゲットでも使うコマンド」を、.DEFAULT
というターゲットに対するルールで書いて定義する事もできます。このルールのコマンドは明示ルールでも暗黙ルールでも全くターゲットとして出て来ない依存関係全部に対して利用します。記述しない標準状態では.DEFAULT
ルールは全く存在しません。
次に示す通りコマンドや依存関係なしで.DEFAULT
を使うと…
.DEFAULT:
….DEFAULT
でそれ以前に保管されているコマンドがクリアされ、make
の動作は.DEFAULT
を全く定義しなかったのと同様になります。
あるターゲットでコマンドを実行させたくはないが、「なんでも一致」の型ルールや.DEFAULT
のコマンドもターゲットに取得させたくないという場合、空のコマンドをそのターゲットに与えればそのようにできます(空のコマンドの利用の項を参照)。
別のmakefileの一部を上書きするのに最後の手段を定義するルールを使う事もできます。これについては別のMakefileを部分的に無効にするの項を見てください。
make
で暗黙のルールを定義する古い手法としてサフィックスルールというものがありますが、型ルールのほうが一般的で明瞭なので、サフィックスルールは時代遅れとなりました。GNU make
では古いmakefileとの互換性のためにサフィックスルールをサポートしています。サフィックスルールはダブルサフィックスとシングルサフィックスという二種類の役目があります。
ターゲットサフィックスとソースサフィックスという一対のサフィックスで定義されたのがダブルサフィックスルールで、ターゲットサフィックスで終わる名前のファイルすべてに一致して、これに対応する暗黙の依存関係はそのファイル名のターゲットサフィックス部分をソースサフィックスに置換した名前のファイルになります。ターゲットサフィックスとソースサフィックスが`.o'と`.c'である二重サフィックスルールは`%.o : %.c'という型ルールと同等です。
ソースサフィックスひとつで定義されたのがシングルサフィックスルールで、こちらはどんなファイル名にも一致して対応する暗黙の依存関係の名前はそれにソースサフィックスを添えたものになります。ソースサフィックスが`.c'のシングルサフィックスルールは`% : %.c'という型ルールと同等です。
サフィックスルール定義は各ルールのターゲットを既知のサフィックスの定義済みリストと比較するという方法でmake
に認識されます。あるルールのターゲットが既知のサフィックスであれば、そのルールはmake
にシングルサフィックスルールとして扱われます。また既知のサフィックス二つがターゲットで一続きになっているなら、そのルールはダブルサフィックスになります。
たとえば`.c'と`.o'は両方とも既知のサフィックスのリストにデフォルトで載っているため、`.c.o'というターゲットのルールを定義すれば、make
ではこれを`.c'というソースサフィックスと`.o'というターゲットサフィックスを持つダブルサフィックスルールとして受け取ります。Cソースファイルをコンパイルするルールを定義する古い手法を次に示します。
.c.o: $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
サフィックスルール自身に依存関係を与える事はできません。そうしてしまうと、サフィックスルールとして扱われるのではなく、おかしな名前のファイルとして扱うことになります。だから、次のルールは…
.c.o: foo.h $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
`foo.h'という依存関係ファイルから`.c.o'というファイルを作成する方法を指示するようになって、次のような型ルールとはかけ離れたものになってしまいます。
%.o: %.c foo.h $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
これは`.c'ファイルから`.o'ファイルを作成する方法を支持するもので、`.o'はすべてこの型ルールを用いて作成し、どれも`foo.h'に依存している、と指示します。
その上、コマンドのないサフィックスルールは無意味で、コマンドのない型ルールのようにその前のルールを削除してはくれず(暗黙のルールをキャンセルするの項を参照)、ただ単にデータベース中のターゲットとしてひとつのサフィックスあるいは一対のサフィックスが一続きになったものを加えるだけです。
.SUFFIXES
という特別なターゲットの依存関係になっている名前が既知のサフィックスになるだけなので、次のように依存関係を増やしてくれる.SUFFIXES
に対するルールを書けば独自のサフィックスを追加できます。
.SUFFIXES: .hack .win
…とすると、`.hack'と`.win'をサフィックスのリストの最後に追加します。
追加する代わりにデフォルトの既知のサフィックスを削除したいなら、依存関係なしで.SUFFIXES
に対するルールを書くと特別な動作として.SUFFIXES
の依存関係をすべて消去します。こうしておけば所望のサフィックスを追加するルールを書く事ができるようになります。たとえば、
.SUFFIXES: # デフォルトサフィックスの削除する .SUFFIXES: .c .o .h # 好きなサフィックスリストを定義する
`-r'フラグか`--no-builtin-rules'フラグかを使えばサフィックスのデフォルトリストを空っぽにできます。
make
はmakefileを読み込む前にサフィックスのデフォルトリストとしてSUFFIXES
という変数を定義します。このサフィックスのリストを変更するのは.SUFFIXES
という特別なターゲットに対するルールで変更しますが、この変数を改変する、というわけではありません。
ここではmake
というプロシージャが如何にしてt というターゲットに対する暗黙のルールの検索を行うかを示します。コマンドのない二重コロンルールと、コマンドを持たない普通のルールの各ターゲットと、ルールのターゲットになっていない依存関係のそれぞれにこのプロシージャは従い、暗黙ルールの連鎖の検索でルールにある依存関係にも再帰的に従います。
サフィックスルールはmakefileが読み込まれた時に一度だけ型ルールと同じになるように変換されるので、このアルゴリズムではサフィックスルールについて述べません。
`archive(member)'という形式のアーカイブメンバーターゲットに対しては以下のアルゴリズムは二度実行されます。つまり、一度目はt という完全なターゲット名に利用し、二度目は第一の実行でルールが見つからない場合に`(member)'をt というターゲットとして利用します。
.DEFAULT
に対するルールが適用される。この場合はt に.DEFAULT
にあるのと全く同じコマンドを与える。もしくはt にはコマンドがないことになる。
一旦見つかったものをルールに適用してしまえば、t やn に一致するターゲット型とは別に、ルールのターゲット型それぞれに対して型にある`%'の部分がs に置換されて、その結果のファイル名はt というターゲットファイルを更新するコマンドが実行されるまでは保管されます。コマンド実行終了後、保管されていたファイル名はどれも、更新されたファイルやt というファイルと同じ更新ステータスを持つファイルのデータベースに格納されます。
型ルールのコマンドがt に対して実行される時、ターゲットと依存関係に相当する自動変数がセットされます。これについては自動変数の項を見てください。