目次 3
1.1. 準備作業 3
1.2. Makefile の概要 4
1.5. 簡単なコマンド 6
1.7.スタイル 6
1.8. クリーンアップ 7
2. Makefile 7
2.1. Makefile 名 7
2.2. Makefile を再生成する方法 8
2.5.
3.ルール 9
3.1.例 9
3.2.ルール構文 9
3.3.ワイルドカード 10
3.3.1.ワイルドカードの欠点 10
3.3.2.ワイルドカード関数 11
3.4.ディレクトリ検索 11
3.4.1.'VPATH' 11
3.4.2. 選択的検索 12
3.4.3. 自動変数の使用 12
3.4. ディレクトリ検索と暗黙的ルール 12
3.5. FORCE ターゲット 14
3.7. 構築-特別な目標 14
3.9. 複数の目標を持つ 1 つのルール 15
3.11. 静的モードのルール 16
3.11.2. 静的モードのルールと暗黙のルール 17
3.12. ダブルコロンルール 17
3.13. 依存関係を自動生成する 18
4.2. 実行する 19
4.5. 中断する再帰的20
4.6.1. 「MAKE」変数を使用する 20
4.6.2. submake に変数を渡す 21
6. 参照 25
6.1. 関数 26
6.3.
6.4. 特殊な変数 29
GNU Make の用途
Make プログラムは元々、不必要な再コンパイルを防ぐために C プログラム ファイルを維持するように設計されました。コマンド ライン コンパイラを使用する場合、プロジェクト内のヘッダー ファイルが変更されます。このヘッダー ファイルを含むすべてのファイルがコンパイルされていることを確認するにはどうすればよいですか?現在の 10 マシン バージョンの世代では、これらのファイルのコンパイルはプログラムの管理者に依存しており、モジュールが相互にヘッダー ファイルを参照する場合、再コンパイルが必要なファイルをすべて見つけるのは面倒です。これらのファイルをコンパイルするためにバッチ プロセスを変更します。実際、これらのタスクは make プログラムによって自動的に実行できます。make ツールは、ファイルとコマンド (他のファイルを更新するために呼び出されるプログラム) 間の関係を管理するのに非常に役立ちます。ファイルが変更されたとき)。 Make ツールの基本的な概念は、PRoglog 言語に似ています。make に何を実行する必要があるかを指示し、いくつかのルールを指定すると、残りは make が実行します。
1. はじめに
make ジョブは、プロジェクトのどの部分を再コンパイルする必要があるかを自動的に判断し、それらをコンパイルするコマンドを実行します。 make は主に C プログラムに使用されますが、コマンドライン コンパイラが提供されている限り、どの言語でも使用できます。実際、make ツールの適用範囲はプログラミングに限定されません。これを使用して、任意のタスクを記述したり、他のファイルを自動的に更新する必要がある一部のファイルを変更したりすることができます。
1.1. 準備作業
make を使用する場合は、「makefile」というファイルを作成し、プロジェクト内のファイル間の関係を記述し、各ファイルを更新するためのコマンドを記述します。典型的なプロジェクトは次のようなものです。実行可能ファイルはターゲット ファイルによって更新され、ターゲット ファイルはソース ファイルをコンパイルすることによって更新されます。
Makefile を作成した後は、ソース ファイルが変更されるたびに make を実行するだけで十分であり、必要な再コンパイルはすべて実行されます。 Make プログラムは、makefile 内のデータベースとファイルの最終変更時刻を使用して、どのファイルを更新する必要があるかを判断します。更新する必要があるファイルに対して、make はデータベースに記録されているコマンドを実行します。
どのファイルを再コンパイルする必要があるかを制御するために、コマンド ライン パラメーターを指定できます。
1.2. Makefile の概要
Makefile は、make に何を行うか、ほとんどの場合、プログラムをコンパイルしてリンクする方法を指示します。
これは、8 つの C ファイルと 3 つのヘッダー ファイルで構成されるエディターをコンパイルおよびリンクする方法を説明する簡単な Makefile です:
edit: main.o kbd.o command.o display.o
insert.o serach.o files .o utils .o
cc –o edit main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc –c main.c
kdb.o : kbd.c defs.h command.h
cc –c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h バッファ.h
cc -c display.c
insert.o : insert.c defs.h バッファ.h
cc -c insert.c
search.o : search.c defs.h バッファ。 -c search.c
files.o : files.c defs.hbuffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
読みやすくするために長い行を区切ります。これは、 の長い 1 行を使用するのと同じ効果があります。この makefile を使用して実行可能ファイル「edit」を作成する場合は、make を実行するだけです。実行可能ファイルとターゲット ファイルを削除する場合は、このエディターを再コンパイルするときに make clean
make を実行します。ヘッダー ファイルの場合は、変更された各 C ファイルを再コンパイルする必要があります。変更された場合は、ヘッダー ファイルを含む各 C ファイルを再コンパイルする必要があります。コンパイルごとに、元のファイルに対応するオブジェクト ファイルが生成されます。最終的に、オブジェクト ファイルはリンクされて新しい実行可能ファイルが生成されます。
1.3. ルールの紹介
Makefile 内のルールは次のとおりです:
TARGET … : DEPENDENCIES …
COMMAND
…
ターゲット (TARGET) は、実行可能ファイルやターゲット ファイルなど、プログラムによって生成されるファイルです。ターゲットは、「クリーン」など、実行されるアクションにすることもできます。
依存関係 (DEPENDENCIES) は、ターゲットを生成するために使用される入力ファイルです。通常、ターゲットは複数のファイルに依存します。
コマンド (COMMAND) は、make によって実行されるアクションであり、それぞれが 1 行を占める複数のコマンドを持つことができます。注: 各コマンド ラインの開始文字は TAB 文字である必要があります。
依存関係ルール内のコマンドは、通常、依存ファイルが変更されたときにターゲット ファイルを生成する役割を果たします。これらのコマンドは、ターゲットを更新または生成するために実行されます。ターゲット「clean」を含むルールなど、ルールには依存関係を含めることはできません。
ルールは、ルール内のファイルをいつどのように再実行するか、依存関係に基づいてターゲットを生成または更新するために実行するかを説明します。ルールは、アクションをいつどのように実行するかについても説明します。一部のルールは複雑に見えるかもしれませんが、すべて上記のパターンに当てはまります。
1.4. make の仕組み
デフォルトでは、make は最初のターゲット (「.」で始まらない最初のターゲット) から開始され、これはデフォルト ターゲットと呼ばれます。上記の Makefile では、デフォルトの目標はエグゼキュータ「edit」を更新することなので、この目標を先頭に置きます。 make が実行されると、make プログラムは現在のディレクトリから makefile を読み取り、最初のルールの処理を開始します。この例では、このルールは、make がこのルールを処理する前に「edit」を再リンクすることになっています。ファイルのルール (この場合はターゲット ファイル) に依存します。これらのファイルは独自のルールに従って処理されます。依存関係にあるソース ファイルまたはヘッダー ファイルがターゲット ファイルより新しい場合、またはターゲット ファイルが存在しない場合、各 '.o' ファイルはソース ファイルをコンパイルすることによって更新されます。再コンパイルする必要があります。
他のルールは、ターゲットがターゲットの依存関係にあるため処理されます。ターゲットに依存関係がないルールは、make 処理 (make clean など) が指定されない限り処理されません。
ターゲット ファイルを再コンパイルする前に、make はその依存関係 (ソース ファイルとヘッダー ファイル) を更新しようとします。この例の makefile では、ソース ファイルとヘッダー ファイルに対する操作は指定されていません。「.c」ファイルと「.h」ファイルはルールの対象ではありません。すべてのオブジェクト ファイルが最新であることを確認した後、make は 'edit' を再リンクするかどうかを決定します。'edit' が存在しない場合、またはオブジェクト ファイルがそれよりも新しい場合は、リンク作業が続行されます。
このように、insert.c を変更して make を実行すると、make はこのファイルをコンパイルして 'insert.o' を更新し、次に 'edit' をリンクします。 '、'command.o'、'files.o' が再生成され、'edit' にリンクされます。
1.5. 変数の使用
この例では、ルール「edit」内にターゲットファイルが 2 回リストされています:
edit : main.o kbd.o command.o display.o
insert.o search.o files.o utils .o
cc -o edit main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
このような繰り返しは簡単にエラーにつながる可能性があります。新しいターゲット ファイルがproject では、それをリストに追加するだけかもしれませんが、このリスクは変数を使用することで排除されます。変数を使用すると、事前定義された文字列を複数の場所で置き換えることができます。
makefile で、次の行を記述して「object」変数を定義できます:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
つまり、ターゲットファイルが必要です。リストに名前を付ける場合は、変数の値の代わりに $(object) を使用します。以下は変数を使用した後の makefile です:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $ (オブジェクト)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.hbuffer.h
cc -c display.c
insert.o : insert.c defs.hbuffer.h
cc -c insert.c
search.o : search.c defs.hbuffer.h
cc -c search.c
files.o : files.c defs.hbuffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
1.6. 簡略化されたコマンド
make で実行できるため、各ファイルのコンパイル コマンドを記述する必要はありません。単独で実行するには、「.o」ファイルを「.c」ファイルで更新するための暗黙のルールがあり、「cc -c」コマンドを使用します。 Make は 'cc -c main.c -o main.o' を使用して main.c を main.o にコンパイルするため、このコマンドはオブジェクト ファイルの生成規則で省略できます。
このように「.c」ファイルを使用すると、自動的に依存関係に追加されるため、コマンドを省略することを前提として、「.c」ファイルを依存関係から省略することができます。以下は簡略化された makefile です:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o edit : $(objects)
cc -o edit $(objects) main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.hbuffer.h
insert.o : defs.hバッファ。 h
search.o : defs.hbuffer.h
files.o : defs.hbuffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
-rm edit $(objects)
1.7. 別のスタイル
Makefile 内のターゲットがすべて暗黙的なルールによって生成されている場合、ルールは依存関係に従ってグループ化できます:
objects = main.o kbd.o command.o display.o
insert.o search.o files.o utils.o edit : $(objects)
cc -o edit $(objects) $(objects) : defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o :buffer.h
ここで、「defs.h」はすべてのターゲットファイルの依存関係として使用されます。このスタイルが良いか悪いかは個人の好みになりますが、非常にコンパクトではありますが、各ターゲットの依存情報がまとめられている方が少しわかりやすくなります。
1.8. クリーンアップ
ルールを記述するとプログラムはコンパイルされません。通常、Makefile には、ディレクトリ内のオブジェクト ファイルや実行可能ファイルを削除してディレクトリをクリーンアップするなど、他のことを行う方法が記述されています。例は次のように書かれています:
clean:
rm edit $(objects)
実際の状況では、いくつかの予期せぬイベントを処理する必要があります。rm がエラーを起こした場合、'clean' というファイルがあります。 make プロセスを停止させたい場合、変更されたバージョンは次のとおりです:
.PHONY : clean
clean :
-rm edit $(objects)
これはそうではないため、このようなルールを makefile の先頭に置くことはできません。デフォルトでそうします。 「clean」は「edit」に依存していないため、引数なしで make を実行する場合、このルールは実行されません。このルールを実行するには、「make clean」を実行する必要があります。
2.Makefile
Makefileには、明示的なルール、暗黙的なルール、変数定義、ディレクティブ、コメントの5種類のコンテンツが含まれています。
1. 明示的なルールは、ルールのターゲットを生成する方法を記述し、ターゲットを生成または更新するためのコマンドを指定します。
2. 暗黙的なルールは、ルールのターゲットを生成する方法を記述します。ファイル名は、対象となる可能性があることを示します。 ファイル名が似ているファイルに応じて、対応するコマンドが指定されます。
3. 命令は、次のようなコンパイラの疑似命令に似ています。
4. make に別の makefile を読み取るように命令します
6. 変数の先頭を定義します
7.行継続文字が出現しない限り、行は行末までコメントになります。 「define」およびコマンドにはコメントを含めることはできません。それ以外の場合、コメントはどこにでも記述できます。
2.1.makefile 名
デフォルトでは、make は次の名前の makefile を検索します: 'GNUmakefile'、'makefile'、および 'Makefile' (大文字と小文字に注意)。通常、メイクファイルは「makefile」または「Makefile」と呼ばれる必要があります。 「GNUmakefile」は、メイクファイルが GNU make 用にカスタマイズされていない限り、他の make ではその名前がメイクファイルの名前とはみなされないため、推奨されません。
非標準の名前付き makefile を使用する場合は、コマンド スイッチ '-f' または '--file' を使用する必要があります。引数「-f NAME」または「--file NAME」は、make に NAME を makefile として読み取るように指示します。複数のスイッチが使用されている場合、すべてのファイルが順番に連結されます。このオプションを使用すると、標準のメイクファイル名は自動的に検出されません。
2.2. 残りのコンテンツの処理を一時停止し、他の Makefile を読み取るように make に指示する
'include' ディレクティブが含まれています。構文は次のとおりです:
include FILENAMES...
この行の先頭にスペースを含めることはできますが、TAB 文字は許可されません。ファイル名に変数または関数が含まれている場合、それらは展開されます。
2.3. ‘MAKEFILE’ 変数
環境変数 ‘MAKEFILE’ が定義されている場合、make はその値をスペースで区切られた一連のファイル名とみなし、他の Makefile を処理する前に make プログラムによって読み込まれます。これは include ディレクティブと似ており、これらのファイル内のターゲットはデフォルトのターゲットに影響を与えず、ファイルが見つからない場合でも make はそれをエラーとはみなしません。
この変数の主な目的は、make プログラムを再帰的に参照するときに通信することです
2.4. makefile を再生成する方法
makefile は、RCS または SCCS ファイルなどの他のファイルから生成される場合があります。 Makefile が他のファイルから生成された場合、make は最新バージョンの Makefile を読み取る必要があります。
すべての Makefile を読み取った後、make は各 Makefile をターゲットとみなして更新を試みます。Makefile に更新方法に関するルールがある場合、または適用される暗黙的なルールがある場合は、必要な更新が実行されます。すべての makefile がチェックされた後、変更されているものがあれば、make は読み取りを再開します (make は再度更新を試みますが、通常はそれがすでに最新であるため、それ以上変更されません)。
ファイルが二重コロン ルールを使用し、コマンドを提供するが依存関係を提供しない場合、ファイルは常に更新されます。 makefile の場合、makefile の 2 つのコロン ルールがコマンドを提供するが依存関係を提供しない場合、makefile は常に再生成されるため、サイクルが発生します。make は makefile を常に更新するだけで、何も処理しません。この状況を回避するために、make は、依存関係のないコマンドのみを含む二重コロン規則を使用したメイクファイルを再生成しません。
「-f」または「--file」オプションが使用されていない場合、make はデフォルトの makefile ファイル名を試行します。 「-f」または「--file」オプションを指定する場合とは異なり、make はこれらのファイルが存在すべきかどうかを判断できません。ただし、デフォルトのメイクファイルが存在しないが、メイク ルールを実行することで生成できる場合は、メイクファイルを使用できるようにこれらのルールを実行することができます。
そのため、デフォルトの Makefile がない場合は、成功するか名前がなくなるまで、Make ファイル名が検索された順序で Make ファイルの生成を試みます。 make が makefile を見つけられない、または生成できない場合はエラーではないことに注意してください。makefile は必ずしも必要ではありません。
「-t」または「--toUCh」オプションを使用する場合、どのターゲットにアクセスするかを決定するために古いメイクファイルを使用することは望ましくありません。したがって、「-t」オプションはメイクファイルの更新には影響しません。「-q」(または「--question」)や「-n」(または「--just-print」)はメイクファイルの更新を妨げません。古い Makefile を使用すると、誤った出力が生成されます。このように、「make -f mfile -n foo」は「mfile」を更新し、それを読み込み、「foo」の更新に必要なコマンドを出力しますが、実行はしません。 「foo」に関連するコマンドは、更新された「mfile」の内容です。
ただし、メイクファイルを更新したくない場合は、コマンドラインでメイクファイルをターゲットとして使用できます。メイクファイルがターゲットとして明示的に指定されている場合、「-t」オプションもそれらに適用されます。
このように、「make -f mfile -n mfile foo」は「mfile」を読み取り、実行する更新されたコマンドを出力します。「foo」のコマンドは現在の「mfile」の内容です。
2.5. makefile のオーバーロード
「include」ディレクティブを使用して、他の makefile をインクルードし、ターゲット変数定義を追加できます。ただし、make では同じターゲットに対して異なるコマンドを使用することはできません。目的を達成するには他の方法があります。
「makefile」と「mfile」があるとします。「makfile」には「mfile」が含まれている必要がありますが、どちらもターゲット「foo」に対するルールがあります。これは、任意のパターンに一致するように「makefile」に記述することができるルールで、make が「makefile」でターゲットを見つけられない場合に「mfile」を検索することを示します。 @$( MAKE) -f mfile $@
force: ;
「make foo」を実行すると、make は「makefile」を見つけ、コマンド「frobnicate >」を実行しました。「make bar」を実行すると、対応する応答が見つかりませんでした。 in 'makefile' ルールが適用され、モード ルールが適用され、コマンド 'make -f mfile bar' が実行されます。'makefile' で言及されていない他のターゲットも同様です。
このメソッドは、パターン ルールのパターンが「%」であり、任意のターゲットに一致するため、すべて機能します。このルールは、ターゲットが存在する場合でもコマンドが確実に実行されるようにする「force」に依存します。 「force」ルールが空であると、「make」がその暗黙的なルールを検索できなくなります。これにより、依存関係の循環が発生します。
3. ルール
Makefile 内のルールは、ルールのターゲットである特定のファイルを生成する方法を記述します。ルールはターゲットの依存関係ファイルをリストし、ターゲットを構築または更新するコマンドを指定します。
デフォルトのターゲットを決定することを除いて、ルールの順序は重要ではありません。デフォルトのターゲットは最初のメイクファイルの最初のルールです。最初のルールに複数のターゲットがある場合、最初のターゲットがデフォルトになります。 2 つの例外があります。「.」で始まるターゲットはデフォルトのターゲットではありません。デフォルトのターゲットには影響しません。
通常、私たちが作成するルールの 1 つは、プログラム全体、またはメイクファイルで指定されたすべてのプログラムをコンパイルすることです。
3.1. 例
foo.o : foo.c defs.h # frobs をいじるモジュール
cc -c -g foo.c
これは 'foo.o' をターゲットにしており、'foo.c' と ' defs に依存します。 h」には、「cc -c -g foo.c」というコマンドがあります。コマンド ラインは、コマンドとして識別するために TAB 文字で始まります。
このルールは 2 つのことを意味します:
8. 「foo.o」が古いかどうか、つまり「foo.c」または「defs.h」がそれよりも新しいかどうかを判断する方法。
9. 「foo.o」ファイルを更新する方法: 「cc」プログラムを実行します。このコマンドには 'defs.h' が記載されていないため、'foo.c' にそれが含まれていると推測できます。そのため、'defs.h' が依存関係に配置されます。
3.2. ルールの構文
構文は次のとおりです:
TARGETS : DEPENDENCIES
COMMAND
...
または
TARGETS : COMMAND
COMMAND
...
TARGETS はスペースで区切られたファイル名です。ワイルドカード文字を使用できます。通常、ルールには目標が 1 つだけありますが、複数の目標がある場合もあります。
コマンドラインはTABキーで始まります。最初のコマンドは、依存関係に続く次の行に置くことも、同じ行のセミコロンの後に置くこともできます。どちらのメソッドも同じ効果があります。
「$」記号は変数参照として使用されるため、ルールで「$」記号を使用したい場合は、「$$」を 2 つ記述する必要があります。長い行を分割するには '' 記号を使用できますが、make には行の長さに制限がないため、これは必要ありません。
3.3. ワイルドカード文字
ルール内のファイル名には、「*」、「?」などのワイルドカード文字を含めることができます。
ファイル名の前の文字「~」には特別な意味があります。単独で使用するか、「/」を続けると、ユーザーのホーム ディレクトリを表します。たとえば、「~」の後に単語が続く場合、「~/bin」は /home/you/bin に展開されます。たとえば、「~john/bin」は「/home/john/bin」に展開されます。
ワイルドカードは、ターゲット、依存関係、およびコマンドで自動的に展開されます。その他の場合、「ワイルドカード」関数が明示的に使用されない限り、ワイルドカードは展開されます。ワイルドカード文字の特別な意味は、'' 記号を使用して閉じることができます。
例:
clean:
rm -f *.o
および
print: *.c
lpr -p $?
touch print
変数を定義する場合、ワイルドカード文字は展開されません。例:
objects = *.o
then オブジェクトの値は文字列 '*.o' ですが、ターゲット、依存関係、またはコマンドでオブジェクトを使用すると、展開が発生します。オブジェクトを拡張コンテンツに設定するには、
objects := $(wildcard *.o)
3.3.1 ワイルドカードの欠陥
を使用します。これはワイルドカードを使用した例ですが、結果は期待どおりではありません。実行可能ファイル「foo」が現在のディレクトリ内のすべての「.o」ファイルから生成されると仮定します。
objects = *.o foo : $(objects)
cc -o foo $(CFLAGS) $(objects)
objects 変数 値文字列「*.o」です。ワイルドカード展開はルール 'foo' で行われるため、既存のすべての '.o' ファイルは 'foo' に依存し、必要に応じて再コンパイルされます。
しかし、すべての「.o」ファイルが削除されたらどうなるでしょうか?ワイルドカードがどのファイルにも一致しない場合は、すべてがそのままになります。その場合、「foo」は「*.o」というファイルに依存します。このファイルは存在しない可能性が高いため、「make」プログラムは「*.o」を生成できないと報告します。 o' 'ファイルにエラーがあります。これは予期した結果ではありません。
実際には、ワイルドカードを使用して目的の結果を得ることが可能ですが、「ワイルドカード」関数や文字列置換関数などの複雑なテクニックが必要です。
3.3.2.wildcard 関数
ワイルドカードはルール内で自動的に実行されます。ただし、変数の代入や関数の引数ではワイルドカードは展開されません。このような場合にワイルドカードの展開が必要な場合は、「ワイルドカード」関数を使用する必要があります。構文は次のとおりです:
$(wildcard PATTERN...)
Makefile 内の任意の場所にあるこの文字列は、任意のファイル名形式に一致する既存のファイルのスペースで区切られたリストに置き換えられます。パターンに一致するファイルがない場合、そのパターンは「ワイルドカード」の出力から無視されます。これは上記のワイルドカード処理とは異なることに注意してください。
「ワイルドカード」関数の機能の 1 つは、ディレクトリ内のすべての「.c」ファイルを検索することです:
$(wildcard *.c)
サフィックス '.c を置き換えることで、C ファイル リストからターゲット ファイルを取得できます。 ' with '.o' リスト:
$(patsubst %.c,%.o,$(wildcard *.c))
このようにして、前のセクションの makefile は次のように書き換えられます:
objects := $( patsubst %.c,%.o,$ (wildcard *.c)) foo: $(objects)
cc -o foo $(objects)
この Makefile は C プログラムのコンパイルに暗黙のルールを使用するため、コンパイル用の明示的なルールを記述します。 (「:=」は「=」の変形です)
注: 「PATTERN」では大文字と小文字が区別されます。
3.4. ディレクトリ検索
大規模システムの場合、通常、ソース ファイルとターゲット ファイルは異なるディレクトリに配置されます。ディレクトリ検索機能を使用すると、ファイルを再配布するときに、ルールを変更する必要はなく、検索パスを変更するだけで、複数のディレクトリ内の依存ファイルを自動的に検索できます。
3.4.1. ‘VPATH’
make 変数 ‘VPATH’ は、make が検索するディレクトリリストをリストします。多くの場合、現在のディレクトリには依存ファイルが含まれておらず、「VPATH」には、ルールのターゲットであるファイルを含むすべてのファイルの検索リストが記述されます。
ターゲット ファイルまたは依存ファイルが現在のディレクトリに見つからない場合、「make」は「VPATH」にリストされているディレクトリで同じ名前のファイルを検索します。見つかった場合、そのファイルは依存ファイルとなり、ルールはそのファイルを現在のディレクトリにあるかのように使用できます。
「VPATH」変数では、ディレクトリ名はコロンまたはスペースで区切られます。ディレクトリのリストの順序によって、make の検索順序が決まります。 (注: pSOSystem 2.5 で Win32 に移植された GNU make ディレクトリ名はセミコロンで区切る必要があります。以降、Win32 GNU make と呼びます)。例: VPATH = src:../headers の場合、ルール
foo.o : foo.c
は、「foo.c」が現在のディレクトリに存在しないと仮定して、
foo.o : src/foo.c
として解釈されます。 、「 src 」ディレクトリ内。
3.4.2. 選択的検索
「VPATH」変数に似ていますが、より選択的なのは「vpath」ディレクティブ (小文字であることに注意してください) で、特定のパターンに一致するファイルの検索パスを指定できます。これにより、ファイルの種類ごとに異なる検索パスを指定できます。
「vpath」ディレクティブには 3 つの形式があります:
10.'vpath PATTERN DirectorIES'
PATTERN に一致するファイル名の検索パス DIRECTORIES を指定します。ディレクトリの分離は 'VPATH' の場合と同じです。
11.'vpath PATTERN'。
PATTERN のファイル名で指定された検索パスとの一致をクリアします
12.'vpath'
以前に 'vpath' で指定されたすべての検索パスをクリアします
'vpath' のパターンは '%' を含む文字列です: この文字列は一致する必要があります検索パス ファイル名に応じて、「%」文字は 0 個以上の任意の文字と一致します。例: '%.h' は、'.h' で終わる任意のファイルに一致します (% がない場合、PATTERN は依存ファイルとまったく同じである必要があり、これは一般的に使用されません)。
現在のディレクトリに依存ファイルがない場合、「vpath」の PATTERN が依存ファイル名と一致する場合、コマンドの DIRECTORIES にリストされているディレクトリは「VPATH」と同じように処理されます。例:
vpath %.h ../headers
は、現在のディレクトリに見つからない ../headers ディレクトリ内の '.h' ファイルを探すように make に指示します。
複数の 'vapth' パターンの一致がファイル名に依存する場合、make はそれらを 1 つずつ処理し、指定されたすべてのディレクトリを検索します。 make プロセス「vapth」は、makefile に現れる順序で作成します。同じモードの複数の「vapth」は互いに独立しています。
vpath %.c foo
vpath % blish
vpath %.c bar
は、「foo」、「blish」、「bar」の順で「.c」ファイルを検索します。そして
vpath %.c foo:bar
vpath % blish
は、'foo'、'bar'、'blish' の順に検索します。
3.4.3. 自動変数の使用
ディレクトリ検索の結果によってルール内のコマンドは変更されません。コマンドはそのまま実行されます。したがって、ディレクトリ検索機能に適したコマンドを作成する必要があります。これは、「$^」などの自動変数を使用して実行できます。 「$^」は、ルール内のすべての依存ファイルを表します。これには、ファイルが存在するディレクトリ名も含まれます (「ディレクトリ検索」を参照)。例:
foo.o : foo.c
cc -c $(CFLAGS) $^ -o $@
通常、依存ファイルにはヘッダー ファイルも含まれますが、これらのファイルはコマンドでは言及されません。 ' は最初の依存ファイルを表します:
VPATH = src:../headers
foo.o : foo.c defs.h hack.h
cc –c $(CFLAGS) $< -o $@
3.4.ディレクトリ検索と暗黙のルール
「VPATH」と「vpath」を使用してディレクトリ検索を指定すると、暗黙のルールにも影響します。たとえば、ファイル「foo.o」には明示的なルールがありません。make は暗黙のルールを考慮します。「foo.c」が存在する場合はそれをコンパイルし、ファイルが存在しない場合は対応するディレクトリを検索します。 c' ' が任意のディレクトリに存在する場合、C コンパイルの暗黙のルールが適用されます。
暗黙のルールを持つコマンドでは、多くの場合、ディレクトリ検索で取得したファイル名を追加の労力なしで使用できるように、自動変数を使用する必要があります。
3.5.PHONY ターゲット
Phony ターゲットは実際のファイル名ではなく、明示的に要求されたときに実行されるコマンドの名前にすぎません。偽のターゲットを使用する理由は 2 つあります。同じ名前のファイルとの競合を避けるため、もう 1 つはパフォーマンスを向上させるためです。
ターゲットファイルを生成しないルールを記述すると、ターゲットが作成されるたびにそのコマンドが実行されます。例:
clean:
rm *.o temp
「rm」コマンドは「clean」ファイルを生成しないため、このコマンドは「make clean」が実行されるたびに実行されます。 「clean」ファイルがディレクトリにある場合、ルールは無効です。依存ファイルはなく、「clean」ファイルは常に最新であり、コマンドは決して実行されません。この問題を回避するには、「.PHONY」を使用してください。ターゲットを指定します。例:
.PHONY: clean
この方法で「make clean」を実行すると、「clean」ファイルが存在するかどうかは無視されます。
偽のターゲットは他のファイルによって生成された実際のファイルではないことがわかっており、make は暗黙のルール検索をスキップします。実際のファイルが存在するかどうかを気にしなくても、偽のターゲットを宣言するとパフォーマンスが向上するのはこのためです。完全な例は次のとおりです。
.PHONY : clean
clean :
rm *.o temp
phony ターゲットは実際のターゲット ファイルに依存すべきではありません。そうであれば、make がこのファイルを更新するたびにコマンドが実行されます。偽のターゲットが実際のターゲットに依存していない限り、ルールのコマンドは、このターゲットが指定されている場合にのみ実行されます。
偽のターゲットには依存関係がある可能性があります。ディレクトリ内に複数のプログラムがある場合、それらをメイクファイルに入れると便利です。デフォルトのターゲットはメイクファイルの最初のターゲットであるため、この偽のターゲットは通常「all」と呼ばれ、その依存ファイルは各プログラムです:
all : prog1 prog2 prog3
.PHONY : all
prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
prog2 : prog2.o
cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o ユーティリティ。 o
このように、「make」を使用すると、3 つのプログラムすべてが生成されます。
ある偽のターゲットが別の偽のターゲットの依存関係である場合、その関数はサブルーチンと同等になります。例:
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm Program
cleanobj :
rm *.o
cleandiff :
rm *. diff
3.6.FORCE target
ルールに依存関係もコマンドもなく、そのターゲットが既存のファイル名ではない場合、make はルールの実行時にこのターゲットが常に更新されると想定します。これは、ルールがこのターゲットに依存する場合、そのコマンドは常に実行されることを意味します。
clean: FORCE
rm $(objects)
FORCE:
この例では、ターゲット 'FORCE' がこの異常な条件を満たしているため、それに依存するターゲット 'clean' はそのコマンドの実行を強制されます。 「FORCE」という名前には特別な意味はなく、単に一般的に使用されているだけです。この方法で「FORCE」を使用すると、「.PHONY : clean」と同じ効果があります。 「.PHONY」を使用する方が明確で効率的ですが、すべての「make」がこれをサポートしているわけではないため、多くの makefile は「FORCE」を使用します。
3.7. 空のターゲット
空のターゲットは偽のターゲットの一種であり、明示的なリクエストを実行するために使用されるアクションです。偽のターゲットとの違いは、このターゲット ファイルが実際に存在する可能性があることです。ターゲット ファイルの内容は無関係で、通常は空です。空のターゲット ファイルの目的は、その最終変更時刻を使用して、コマンドが最後に実行された時刻を記録することです。これは、「touch」コマンドを使用してターゲット ファイルを更新することで実現されます。
print: foo.c bar.c
lpr -p $?
touch print
このルールを使用すると、「make print」を実行するときに、最後の「make print」以降にファイルが変更されている場合、「lpr」コマンドが実装されます。 。自動変数「$?」は、変更されたファイルのみを出力するために使用されます。
3.8. 組み込まれた特別な目標
いくつかの名前は、目標として存在する場合、特別な意味を持ちます。
13..PHONY このターゲットの依存関係は、ファイル名が存在するかどうか、または最終変更時刻に関係なく、無条件に実行されます。このターゲットはサフィックスとみなされ、サフィックス ルールをチェックするときに使用されます
15..DEFAULT このターゲットのルールは、(明示的または暗黙的) ルールのないターゲットで使用されます。 「DEFAULT」コマンドが定義されている場合、この一連のコマンドは、通常のターゲットではないすべての依存ファイルに対して実行されます
16..PRECIOUS このターゲットの依存ファイルは特別な処理を受けます: make が強制終了された場合、またはコマンドが中断された場合、これらのターゲットは削除されません。また、ターゲットが中間ファイルの場合は、必要がなくなっても削除されません。暗黙的ルールのターゲット パターン (%.o など) を '.PRECIOUS' の依存ファイルとして使用できるため、これらのルールによって生成された中間ファイルを保存できます。
17..INTERMEDIATE ターゲットの依存ファイルは中間ファイルとみなされます。ターゲットに依存ファイルがない場合は、メイクファイル内のすべてのターゲット ファイルが中間ファイルとみなされます。
18..IGNORE このターゲットのルールに依存するコマンドを実行する場合、make はこのルールのコマンド自体は無意味です。ルールに依存関係がない場合は、すべてのコマンド実行のエラーが無視されることを意味します。この使用法はすべてのコマンドに影響するため、特に有用ではありません。エラー。
19..SILENT このターゲットに対してルール依存のコマンドを実行する場合、make はコマンド自体を出力しません。ルールのコマンドは意味がありません。 「.SILIENT」に依存関係がない場合、実行時にメイクファイル内のすべてのコマンドが出力されないことを意味します。このルールは下位互換性のためにのみ提供されています。
20..EXPORT_ALL_VARIABLES は単にターゲットとして存在し、すべての変数を子プロセスに出力するように make に指示します。
定義された暗黙的ルールのサフィックスがターゲットとして使用される場合、それは例外的なターゲットとみなされます。これは、「.c.o」などの 2 つのサフィックスの接続にも当てはまります。これらのターゲットはサフィックス ルールであり、暗黙的なルールを定義する時代遅れの (しかし依然として広く使用されている) 方法です。通常、サフィックスは「.」で始まるため、特別なターゲットも「.」で始まります。
3.9. 複数の目標を持つ 1 つのルール
複数の目標を持つルールは、それぞれが 1 つの目標を持つ複数のルールを記述するのと同じ効果があります。同じコマンドがすべてのターゲットに適用されますが、その有効性は実際のターゲットを「$@」に置き換えることによって異なります。ルール内のすべてのターゲットの依存関係は同じです。
これは 2 つの状況で役立ちます:
★ 依存関係のみで、コマンドは必要ありません。例:
kbd.o command.o files.o: command.h
21。すべてのターゲットに同じコマンドがあります。次のコマンドで「$@」を使用できるため、これらのコマンドはまったく同じである必要はありません。および
bigoutput : text. g
generate text.g -big > bigoutput : text.g
generate text.g -little > と同等です。ここでは、プログラム 'generate' が 2 つの出力を生成すると仮定します。1 つは '-big' オプションを使用し、もう 1 つは '-little' オプションを使用します。 '$@' 変更コマンドを使用して依存関係を変更することを想像すると、通常の多目的ルールでは実現できませんが、パターン ルールでは実現できます。
3.10. 複数のルールを持つ 1 つのターゲット
1 つのファイルを複数のルールのターゲットにすることができ、すべてのルールの依存関係がマージされます。ターゲットが依存ファイルのいずれよりも古い場合、コマンドが実行されます。
1 つのファイルで実行できるコマンドのセットは 1 つだけです。複数のルールで同じファイルに対するコマンドが指定されている場合、 make は最後のグループを使用してエラー メッセージを出力します (例外: ファイル名が '.' で始まる場合、エラー メッセージは出力されません。これは他の make との互換性のためです)。このように makefile を記述する必要はないため、make でエラー メッセージが表示されます。
依存関係のみを含む追加ルールは、一度に多くのファイルに追加の依存関係ファイルを与えることができます。たとえば、「objects」変数はシステム内のコンパイラのすべての出力を表します。「config.h」が変更されたときにすべてのファイルを再実行する必要があることを示す簡単な方法は次のとおりです:
objects = foo.o bar.o
foo.o : defs. h
bar.o : defs.h test.h
$(objects) : config.h
このルールは、実際のターゲット ファイル生成ルールを変更する必要はありません。さらに依存関係を追加または削除する必要があります。もう 1 つのトリックは、追加の依存関係を変数で表すことができることです。make が実行されると、変数に値を割り当てることができます。
extradeps=
$(objects) : $(extradeps)
コマンド `make extradeps=foo.h' が実行されるとき。 「foo.h」はすべてのオブジェクト ファイルの依存ファイルとみなされますが、これは単純な「make」コマンドの場合には当てはまりません。
3.11. 静的パターン ルール
静的パターン ルールは複数のターゲットを指定でき、依存関係が同じである必要がないため、ターゲット名を使用して依存ファイルの名前を提案できます。関係 類似している必要がありますが、必ずしも同一である必要はありません。
3.11.1. 構文
TARGETS ...: TARGET-PATTERN: DEP-PATTERNS ...
COMMANDS
...
TARGETS リストはルール適用のターゲットを示し、ワイルドカードを含めることができます。通常ルールの対象。 TARGET-PATTERN と DEP-PATTERNS は、ターゲットの依存関係がどのように計算されるかを示します。TARGET-PATTERN に一致するターゲットは、ステム (ステム) と呼ばれる名前の一部を抽出し、ステムは DEP-PATTERNS に置き換えられて、依存関係ファイル名。
通常、各パターンには「%」文字が含まれます。 TARGET-PATTERN がターゲットと一致する場合、「%」文字はターゲット名の任意の部分と一致する可能性があり、この部分は語幹であり、パターンの残りの部分は正確に一致する必要があります。たとえば、「foo.o」はステムである「%.o」に一致しますが、ターゲット「foo.c」と「foo.out」はこのパターンに一致しません。
ターゲットの依存関係ファイル名は、DEP-PATTERNS の '%' を語幹に置き換えることによって形成されます。依存関係パターンが '%.c' の場合、語幹 'foo' を置き換えると 'foo.c' になります。依存関係パターンに「%」が含まれていない場合も正当であり、この依存関係ファイルはすべてのターゲットに対して有効です。
パターン ルールで '%' 文字を使用する必要がある場合は、その前に '' 文字を追加する必要があります。 '%' の前の '' 文字に意味がある場合は、その前に '' を追加する必要があります。他の '' 文字はこのように扱う必要はありません。たとえば、「the%weird%pattern」は、有効な「%」の前は「the%weird」、その後は「pattern」です。最後の '' は、「%」文字には影響しないため、そのまま残ります。
次の例では、対応する '.c' ファイルから 'foo.o' と 'bar.o' をコンパイルします。
objects = foo.o bar.o
$(objects): %.o: %.c
$( CC ) -c $(CFLAGS) $< -o $@
各ターゲットはターゲット パターンと一致する必要があり、一致しないターゲットについては警告が表示されます。リスト内の一部のファイルのみがパターンに一致する場合は、フィルター関数を使用して、一致しないファイル名を削除できます:
files = foo.elc bar.o loss.o $(filter %.o,$(files)): % .o : %.c
$(CC) -c $(CFLAGS) $< -o $@
$(フィルター %.elc,$(files)): %.elc: %.el
emacs -f バッチ-byte -compile $<
この例では、`$(filter %.o,$(files))' の結果は `bar.o loss.o' になります。 $(files))' は `foo.elc' です。次の例は、'$*' の使用例を示しています。
bigoutput littleoutput : %output : text.g
generate text.g -$* > $@
コマンド `generate' が実行されると、'$*' は語幹は「大きい」または「小さい」です。
3.11.2. 静的パターン ルールと暗黙的ルール
静的パターン ルールと暗黙的ルールには、どちらもターゲット パターンがあり、ファイル名に依存するパターンを構築するという点が異なります。ルールを適用します。
暗黙的ルールは、そのパターンに一致する任意のターゲットに適用できますが、適用できる暗黙的ルールが複数ある場合は、ルールの順序に応じて 1 つだけが使用されます。
逆に、静的モード ルールは、他のターゲットではなく、ルール内の明示的なターゲット リストに適用され、指定された各ターゲットに常に適用されます。 2 つの競合するルールがあり、両方のルールにコマンドがある場合、これはエラーになります。
暗黙的ルールに対する静的モード ルールの利点は次のとおりです:
22. 構文的に分類できないが、明示的にリストすることができる一部のファイルについては、暗黙的ルールをオーバーライドできます。
23. ディレクトリの正確な内容を決定することはできません。一部のファイルは無関係なファイルであるため、make が間違った暗黙的なルールを適用する可能性があり、最終結果は暗黙的なルールの順序に依存する可能性があります。静的パターン ルールを適用する場合、この不確実性は存在しません。ルールは明確に指定された目標に適用されます。
3.12. ダブルコロンルール
ダブルコロンルールのターゲットの後には「:」ではなく「::」が続きます。ターゲットが複数のルールに含まれる場合、その処理は通常のルールとは異なります。
ターゲットが複数のルールに出現する場合、すべてのルールは同じタイプである必要があります (すべてプレーンまたはすべて二重コロン)。二重コロンの場合、ルールは相互に独立しています。ターゲットを更新する必要がある場合、ルールのコマンドが実行されないか、一部またはすべてが実行される可能性があります。ルールが実行されます。
同じターゲットの二重コロン ルールは完全に分離されており、異なるターゲットのルールと同様に、各ルールは個別に処理され、メイクファイルに出現する順序で処理されます。このタイプの本当に意味のあるルールは、コマンドの実行順序は関係ありません。
この種のルールは不明瞭な場合もありますが、あまり役に立ちません。ファイルの更新に依存してターゲットを異なる方法で処理するメカニズムを提供しますが、これはまれです。このような各ルールはコマンドを提供する必要があります。そうでない場合は、該当する暗黙的なルールが使用されます。
3.13. 依存関係を自動的に生成する
Makefile では、一部のターゲット ファイルが一部のヘッダー ファイルに依存するというルールが多くあります。例: 「main.c」は「#include」経由で「defs.h」を使用するため、ルール:
main.o: defs.h
は、「defs.h」が変更されたときに「main.o」を更新するように make に指示します。プログラムが比較的大きい場合は、このようなルールを多数記述する必要があり、「#include」が追加または削除されるたびにメイクファイルを注意深く更新する必要があります。最近のコンパイラの多くは、通常はコンパイラの '-M' オプションを使用してこれらのルールを作成できます。たとえば、次のコマンドを実行します。
cc -M main.c
次を出力します:
main.o : main.c defs。
この方法では、これらのルールを記述する必要はなく、コンパイラーが自動的に作成します。
このような依存関係で言及されている「main.o」は、暗黙のルールにより中間ファイルとみなされないことに注意してください。つまり、make は使用後に削除しません。古い「make」プログラムを使用する場合、通常は「make depend」コマンドを使用してコンパイラの関数を使用して依存関係を生成します。このコマンドは、自動的に生成されたすべての依存関係を含む「depend」ファイルを生成し、「include」を使用します。 'で読み込んでください。
GNU の make を使用する場合、メイクファイルを再生成できるため、この慣行は廃止されます。古いメイクファイルは常に再生成されるため、依存関係を更新するための明示的な要求はありません。
依存関係の自動生成に推奨されるアプローチは、ソース ファイルごとに Makefile を作成することです。各ソース ファイル「NAME.c」には、メイクファイル「NAME.d」があり、ターゲット ファイル「NAME.o」が依存するすべてのファイルがリストされているため、ソース ファイルが更新されるときに、新しい依存関係を生成するためにスキャンされます。例は、「NAME.c」から依存関係ファイル「NAME.d」を生成するパターン ルールです。
%.d: %.c
$(SHELL) -ec '$(CC) -M $(CPPFLAGS) $< ;
sed '''s/($*).o[ :]*/1 $@/g''' > $@'
-e オプションは、$(CC) コマンドが失敗した場合に使用されます (終了ステータス) 0) 以外の場合、シェルは直ちに終了します。通常、シェルの戻り値はパイプラインの最後のコマンド (sed) の戻り値であるため、make はコンパイラ エラーに気づきません。
GNU C コンパイラ (gcc) を使用する場合、「-M」オプションの代わりに「-MM」オプションを使用できるため、システム ヘッダー ファイルへの依存関係を省略できます。 「sed」コマンドの目的は、各「.d」ファイルが「 o' ファイルはソース ファイルとヘッダー ファイルに対応し、元のテキストまたはヘッダー ファイルが変更されたときに make は依存関係ファイルを更新できます。
「.d」ファイルを生成するためのルールが定義されている場合は、「include」ディレクティブを使用してすべてのファイルを読み取ることができます:
sources = foo.c bar.c
include $(sources:.c=.d)
例 置換変数を使用して、ソース ファイル 'foo.c bar.c' のリストを依存関係ファイルのリストに変換します。 「.d」ファイルは他のファイルと同様で、それ以上の作業は必要ないため、必要に応じて make がファイルを再生成します。
4. コマンドを書く
ルールのコマンドは、一つずつ実行されるシェルコマンドで構成されています。セミコロンで区切られた依存関係の後にコマンドを記述するだけでなく、各コマンド ラインはタブ文字で始まる必要があります。コマンド ラインには空白行とコメント行が表示されますが、処理中に無視されます (注: タブ文字で始まる空白行は)。 「空」行は空のコマンドです)。
コマンドでは任意のプログラムを使用できますが、これらのプログラムは $(SHELL) によって実行されます。
4.1. Echo
通常、make は実行するコマンドを出力します。これは、自分でコマンドを入力した場合と同じ現象です。行の前に「@」文字がある場合、コマンドはエコーされなくなり、「@」文字はシェルに渡される前に破棄されます。一般的な使用法は、'echo' コマンドなどの印刷コマンドにのみ有効です:
@echo 配布ファイルを作成しようとしています
make が '-n' または '--just-print' オプションを使用する場合、作成されるすべての内容を表示します発生しますが、注文は実行されません。この場合に限り、コマンドが「@」で始まっている場合でもコマンド ラインが表示されます。このオプションは、make が実際に何を行っているかを確認するのに役立ちます。
「-s」または「--silent」オプションは、「@」で始まるすべてのコマンドと同様に、すべてのエコーを防止します。依存関係のない「.SILENT」ルールも同じ効果がありますが、「@」の方がより柔軟です。
4.2. 実行
ターゲットを更新するためにコマンドを実行する必要がある場合、make は実行する各行のサブシェルを作成します。これは、プロセスのローカル変数を設定する (プロセスの現在のディレクトリを変更する) 'cd' などのシェル コマンドが、後続のコマンドに影響を与えないことを意味します。次のコマンドに影響を与えるために 'cd' が必要な場合は、それらをセミコロンで区切って 1 行に記述します。そうすることで、make はそれがシェル プログラムに渡されるコマンドであると認識します (注: これにはシェルのサポートが必要です):
foo : bar/lose
cd bar ; gobble loss > 別の形式では行継続文字を使用します:
foo : bar/lose
cd bar;
gobble loss >の「SHELL」変数。
(*UNIX) ほとんどの変数とは異なり、「SHELL」環境は個人的な選択であり、異なる人々の選択であるため、「SHELL」変数は環境を通じて設定されません(つまり、メイクファイルで設定する必要があります)。メイクファイルの機能に影響を与える可能性がある場合、これは問題です。
4.3. 並列実行
GNU make は一度に複数のコマンドを実行できます。通常、make は一度に 1 つのコマンドを実行し、そのコマンドが返されるのを待ってから、次のコマンドを実行します。複数のコマンドを同時に実行するには、「-j」または「--jobs」を使用します。 「-j」の後に正の数値がある場合は、一度に実行できるコマンドの数を示します。「-j」の後にパラメータがない場合は、実行できるコマンドの数に制限はありません。 。デフォルトの数は 1 です。
厄介な問題の 1 つは、複数のコマンドが同時に実行されると、その出力が混在してしまうことです。もう 1 つの問題は、2 つのプロセスが同じデバイスから入力を取得できないことです。
4.4. エラー
各シェルコマンドが返されると、make はその戻りステータスを確認します。コマンドが正常に実行されると、最後のコマンドが実行された後、次のコマンドが実行され、ルールの実行が終了します。
エラーが発生した場合 (ゼロ以外のステータスが返された場合)、make は現在のルールを破棄し、場合によってはすべてのルールを破棄します。
「mkdir」コマンドを使用してディレクトリが存在することを確認するなど、コマンド実行エラーが問題にならない場合があります。ディレクトリが存在する場合、「mkdir」はエラーを報告しますが、それでも make を続行したい場合があります。
コマンドのエラーを無視するには、コマンドの前に「-」文字を使用します。「-」文字はシェルに渡される前に破棄されます:
clean:
-rm -f *.o
「-i」を使用する場合。または '--ignore' -errors' オプションを使用すると、make はすべてのコマンドによって生成されたエラーを無視します。依存関係のない '.IGNORE' ルールも同じ効果がありますが、'-' の方がより柔軟です。
エラーを無視する場合、make はエラーを成功とみなし、コマンドの終了ステータスを通知するだけで、エラーは無視されます。 make がエラーを無視するように指示しない場合、エラーが発生したときにターゲットを正常に更新できず、それに直接的または間接的に依存するターゲットは確実に正常に実行されません。前提条件が満たされていないため実行されます。
通常、make はゼロ以外のステータスですぐに終了します。ただし、「-k」または「-keep-running」オプションが指定されている場合、make は終了する前に他の依存関係を処理し、必要な更新を行います。たとえば、1 つのオブジェクト ファイルのコンパイル中にエラーが発生した場合、「make -k」は他のオブジェクト ファイルのコンパイルを続行します。
一般に、指定されたターゲットを更新することが目的であると考えられていますが、これが不可能であると make が認識すると、'-k' オプションは、本当の目的がプログラムの更新の可能性をテストすることであることを示します。 : コンパイルする前に、より多くの可能性を調べてください。
コマンドが失敗した場合、ターゲット ファイルを更新すると仮定すると、ファイルは不完全で使用できません。少なくとも完全には更新されていません。ただし、ファイルの最終変更時刻は、そのファイルがすでに最新であることを示しており、次回 make を実行するときにはファイルは更新されません。この状況は、コマンドが強制終了された場合と同じです。通常、コマンドが失敗したときにターゲットを削除するのが正しいです。「.DELETE_ON_ERROR」がターゲットの場合は、make がこれを実行します。 make にこれを実行させたいと常に思っていますが、これは習慣的ではないため、明示的に make にこれを実行するように要求する必要があります (他の make はこれを自動的に実行します)。
4.5. make の中断
コマンドの実行中に make でエラーが発生した場合、コマンドによって更新されたターゲット ファイルが削除される可能性があります。make はファイルの変更時刻が変更されたかどうかを確認します。ターゲットを削除する目的は、次回の make 実行時にターゲットが確実に再生成されるようにすることです。どうしてこれをやったの?コンパイラの実行中に「Ctrl-c」を押すと、コンパイラはオブジェクト ファイル「foo.o」を書き込み、生成します。 「Ctrl-c」はコンパイラを強制終了し、不完全なファイルを残しますが、その変更時刻はソースファイル「foo.c」よりも新しいため、make はこの不完全なファイルを削除するための「Ctrl-c」シグナルも受け取ります。 make がこれを行わないと、次回 make を実行するときに「foo.o」を更新する必要がないと判断され、リンク中に奇妙なエラーが発生します。
「.PRECIOUS」ルールを使用して、ターゲットファイルが削除されるのを防ぐことができます。 make はターゲットを更新するときに、それが '.PRECIOUS' の依存関係であるかどうかを検出し、コマンド エラーまたは中断が発生したときにターゲットを削除するかどうかを決定します。ターゲットへの更新をアトミックにしたい場合、変更時刻を記録したい場合、または他の種類のエラーを防ぐために永続化したい場合は、これを行う必要がある理由は次のとおりです。
4.6. 再帰的使用
make の再帰的使用とは、makefile 内で make コマンドを使用することです。この手法は、大規模なシステムを複数のサブシステムに分割し、各サブシステムにメイクファイルを提供する場合に役立ちます。たとえば、独自の makefile を持つサブディレクトリ 'subdir' があり、そのディレクトリ内で make を実行したい場合は、次のようにすることができます:
subsystem:
cd subdir; または
subsystem:
$ (MAKE) -C subdir
これをコピーして、再帰的に make を使用することができます
4.6.1. 'MAKE' 変数
再帰的な make では、明示的な make コマンドではなく、'MAKE' 変数を使用する必要があります:
subsystem:
cd subdir; $(MAKE)
変数の値は、呼び出される make の名前です。コマンドで 'MAKE' を使用すると、何か特別なことが行われます。それは、`-t' (`--touch')、`-n' (`--just-print')、および `-q' (`--question') を変更します。 ') オプションの意味。上記の例を使用して、「make –t」コマンドを考えてみましょう (「-t」オプションはターゲットを最新としてマークしますが、コマンドは実行しません)。また、「-t」オプションは「サブシステム」を作成します。 ' 実際に必要なファイルを指定するには、'cd subdir; make –t' を実行します。これは、'-t' の本来の意味と矛盾します。
この並外れた機能は期待どおりの働きをします。コマンド ラインに変数 'MAKE' が含まれている場合、オプション '-t'、'-n'、および '-q' は適用されません。コマンドを実行しない原因となるこれらのフラグに関係なく、「MAKE」変数を含むコマンドは常に実行されます。通常の「MAKEFLAGS」メカニズムはこれらのフラグをサブメイクに渡し、印刷コマンドの要求がサブシステムに伝播されるようにします。
4.6.2. サブ make に変数を渡す
上位 (トップレベル) make の変数は、環境を通じて明示的にサブ make に渡すことができます。サブメイクでは、これらの変数はデフォルトで定義されますが、「-e」オプションが使用されない限り、サブメイクファイル内の定義はオーバーライドされません。
変数を渡す、つまり出力するには、コマンド sub-make の実行時にそれらを環境変数に追加します。環境変数を使用して変数テーブルを初期化できます。明示的に要求されない限り、make は初期環境またはコマンドラインで設定された変数のみを出力し、変数名は文字、数字、およびアンダースコアのみで構成されます。一部のシェルでは、他の文字では環境変数を処理できません。
特殊変数「SHELL」と「MAKEFLAGS」は常に出力されます。「MAKEFILE」変数に値がある場合は、それも出力されます。 Make は、「MAKEFLAGS」を通じてコマンドラインで定義された変数を自動的に出力します。
特定の変数をエクスポートしたい場合は、'export' コマンドを使用します:
export VARIABLE...
変数がエクスポートされないようにしたい場合は、'unexport' コマンドを使用します:
unexport VARIABLE...
便宜上、エクスポート時に変数を定義できます:
export VARIABLE = value
と
VARIABLE = value
export VARIABLE
は同じ効果があります。
すべての変数をエクスポートしたい場合は、「export」コマンド自体を使用してください。
変数「MAKELEVEL」はレベルごとに渡されると変化します。この変数の値は、ネストされたレベルの数を示す文字列です。変数の値は「0」です。サブメイクの値は '1 '、サブメイクの値は '2' などとなります。
「MAKELEVEL」の目的は、条件付きディレクティブでテストすることにより、再帰的に実行した場合と直接実行した場合で動作が異なる Makefile を作成することです。
以下の内容は GNU Make マニュアルからコピーされています
5. コマンドラインパラメータ
`-b'
`-m'
これらのオプションは、
`make' の他のバージョンとの互換性のために無視されます。 --directory =DIR'
makefile を読み取る前にディレクトリ DIR に変更します。複数の `-C' オプションが指定されている場合、それぞれは
前のオプションを基準として解釈されます。 `-C / -C etc' は `- と同等です。 C /etc '。これは通常、`make' の再帰呼び出しで使用されます (*注意: `-d'
`--debug'
通常のデバッグ情報に加えてデバッグ情報を出力します)。
デバッグ情報には、どのファイルが再作成の対象として考慮されているか、どのファイル時間がどのような結果と比較されているか、どのファイルが実際に再作成される必要があるか、どの暗黙的なルールが考慮され、どのルールが適用されているか、すべてが示されます。 `-e'
`--environment-overrides'
環境から取得した変数を makefile からの変数に優先させます。*環境からの変数:
環境に注意してください。 f FILE'
`--file=FILE'
`--makefile=FILE'
FILE という名前のファイルを makefile として読み込みます `-h'
`--help'
`make' が理解するオプションを思い出させます。そして終了します。
`-i'
`--ignore-errors'
ファイルを再作成するために実行されるコマンドのエラーをすべて無視します。`-I DIR'
`--include-dir=DIR'
検索するディレクトリ DIR を指定します。複数の `-I' オプションを使用して複数のディレクトリを指定すると、指定された順序でディレクトリが検索されます
--jobs=[JOBS]' を指定します。同時に実行するジョブ (コマンド) の数です。
引数なしの場合、`make' は可能な限り多くのジョブを同時に実行します
複数の `-j' オプションがある場合、最後のオプションが有効です。
`-k'
`- -keep-going'
失敗したターゲットとそれに依存するターゲットは再作成できませんが、これらのターゲットの他の
依存関係は同様に処理できます。 `-l [LOAD]'
`--load-average[=LOAD]'
`--max-load[=LOAD]'
他のジョブが実行中である場合、新しいジョブ (コマンド) を開始しないことを指定します
負荷平均は少なくとも LOAD (
浮動小数点数) です。引数なしでは、以前の負荷
制限が削除されます。 * 並列実行: `-n'
`--just-print'
`-。 -dry- run'
`--recon'
実行されるコマンドを出力しますが、実行はしません。
`-o FILE'
`--old-file=FILE'
`--assume-old= FILE'
ファイル FILE が
依存関係より古い場合でも、ファイルを再作成しないでください。また、
FILE 内の変更を理由に何も再作成しないでください。基本的に、ファイルは非常に古いものとして扱われ、そのルール
は無視されます。 p'
`--print-data-base'
Makefile の読み取り結果のデータベース (ルールと変数値) を出力し、通常どおりに実行するか、指定されたとおりに実行します。
`-v' スイッチ (以下を参照)。ファイルを再作成せずにデータベースを出力するには、`make -p -f /dev/null' を使用します。`-q'
`--question'
"Questionコマンドを実行したり、何も表示したりしないでください。指定されたターゲットが既に最新の場合は 0、再作成が必要な場合は 1、エラーが発生した場合は 2 の終了ステータスを返すだけです。 ` -r'
`--no-builtin-rules'
組み込みの暗黙的なルールの使用を排除します。
パターン ルールを記述することで独自のルールを定義することもできます。 `-r' オプションは、接尾辞ルールのデフォルトの接尾辞リスト
もクリアします。しかし、`.SUFFIXES' の
ルールを使用して独自の接尾辞を定義し、独自の接尾辞ルールを定義することもできます。 `-s'
`--silent'
`--clean'
サイレント操作。実行時にコマンドを出力しません。
`-S'
`--no-keep-going'
`--stop'
`-k' オプションの効果をキャンセルします。これは決して必要ではありません
、再帰的 `make' では、`-k' が `MAKEFLAGS' を介して最上位の `make' から継承される可能性がある
場合、または環境の `MAKEFLAGS' で `-k' を設定した場合を除きます。 `-t'
`--touch'
コマンドを実行する代わりに、ファイルをタッチします (実際には変更せずに最新のマークを付けます)
。これは、将来の make の呼び出しを欺くために、コマンドが完了したように装うために使用されます。 `-v'
`--version'
`make' プログラムのバージョンに加えて、著作権、作成者のリスト
、および保証がないことを示す通知を出力します。
`-w'
`--print-directory'
メイクファイルの実行前と
後の両方で、作業ディレクトリを含むメッセージを出力します。これは、再帰的な `make' コマンドの複雑なネストからエラーを追跡
するのに役立つかもしれません。 `--no-print-directory'
`-w' の下の作業ディレクトリの印刷を無効にします。このオプション
は、`-w' が自動的にオンになっているが、余分なメッセージを表示したくない場合
に便利です。 `-W FILE'
`--what-if=FILE'
`--new-file=FILE'
`--assume-new=FILE'
ターゲット FILE が変更されたばかりであるとみなします。 `-n' フラグと一緒に
使用すると、そのファイルを変更した場合に何が起こるかを示します。 `-n' を指定しないと、`make' を実行する前に指定されたファイルに対して `touch' コマンドを実行するのとほぼ同じです
、変更時刻が `make' の想像内でのみ変更される点が異なります。 `--warn-unknown-variables'
未定義変数への参照を `make' が検出するたびに警告メッセージを発行します。これは、変数を複雑な方法で使用するメイクファイルをデバッグしようとする場合に役立ちます。 6. 参考
6.1.命令
`define VARIABLE'
`endef'
複数行の再帰的に展開される変数を定義します。
*シーケンス:: に注意してください。 `ifdef VARIABLE'
`ifndef VARIABLE'
`ifeq (A,B)'
`ifeq "A" "B"'
`ifeq 'A' 'B''
`ifneq (A,B)'
`ifneq "A" "B"'
`ifneq 'A' 'B''
`else'
`endif'
Makefile の一部を条件付きで評価します。 `include FILE'
別の Makefile をインクルードします。 `override VARIABLE = VALUE'
`override VARIABLE := VALUE'
`override VARIABLE += VALUE'
`override define VARIABLE'
`endef'
コマンドラインから以前の定義をオーバーライドして変数を定義します
。
`export'
デフォルトですべての変数を子プロセスにエクスポートするように `make' に指示します。 `export VARIABLE'
`export VARIABLE = VALUE'
`export VARIABLE := VALUE'
`export VARIABLE += VALUE'
`unexport VARIABLE'
特定の変数を子プロセスにエクスポートするかどうかを `make' に指示します。
`vpath PATTERN PATH'
`%' パターンに一致するファイルの検索パスを指定します。
*注 `vpath' ディレクティブ: 選択的検索。 `vpath PATTERN'
以前に PATTERN に指定した検索パスをすべて削除します。 `vpath'
`vpath'
ディレクティブで以前に指定されたすべての検索パスを削除します。
6.2.関数数
`$(subst FROM,TO,TEXT)'
TEXT 内の FROM を TO に置き換えます。 `$(patsubst PATTERN,REPLACEMENT,TEXT)'
PATTERN に一致する単語を TEXT 内の REPLACEMENT に置き換えます。 `$(strip STRING)'
STRING から余分な空白文字を削除します。 `$(findstring FIND,TEXT)'
TEXT 内で FIND を見つけます。 `$(filter PATTERN...,TEXT)'
PATTERN 単語の 1 つに一致する TEXT 内の単語を選択します。 `$(filter-out PATTERN...,TEXT)'
どの PATTERN 単語にも *一致しない * TEXT 内の単語を選択します。 `$(sort LIST)'
LIST 内の単語を辞書順に並べ替え、重複を削除します。 `$(dir NAMES...)'
各ファイル名のディレクトリ部分を抽出します。 `$(notdir NAMES...)'
各ファイル名のディレクトリ以外の部分を抽出します。 `$(suffix NAMES...)'
各
ファイル名のサフィックス(最後の`.'以降の文字)を抽出します。 `$(basename NAMES...)'
各ファイル名のベース名(接尾辞のない名前)を抽出します。 `$(addsuffix SUFFIX,NAMES...)'
NAMES の各単語に SUFFIX を追加します。 `$(addprefix PREFIX,NAMES...)'
NAMES の各単語の先頭に PREFIX を追加します。 `$(join LIST1,LIST2)'
2 つの単語の並列リストを結合します。 `$(単語 N,TEXT)'
TEXT の N 番目の単語 (1 つの起点) を抽出します。 `$(words TEXT)'
TEXT内の単語数を数えます。 `$(firstword NAMES...)'
NAMES の最初の単語を抽出します。 `$(wildcard PATTERN...)'
シェルのファイル名パターン (`%'
パターンではありません) に一致するファイル名を検索します。 `$(shell COMMAND)'
シェルコマンドを実行し、その出力を返します。 `$(origin VARIABLE)'
`make' 変数 VARIABLE がどのように定義されたかを説明する文字列を返します
。 `$(foreach VAR,WORDS,TEXT)'
WORDS 内の各単語にバインドされた VAR で TEXT を評価し、
結果を連結します。
6.3.自動变量
`$@'
ターゲットのファイル名。 `$%'
ターゲットがアーカイブ メンバーの場合のターゲット メンバー名。 `$最初の依存関係の名前。 `$?'
ターゲットより新しいすべての依存関係の名前
間にスペースを入れます。アーカイブ
メンバーである依存関係の場合は、間にスペースを入れて指定されたメンバーのみが使用されます
。アーカイブ
メンバーである依存関係の場合、指定されたメンバーのみが使用されます
`$^'
`$+'
すべての依存関係の名前 (間にスペースを入れます)。アーカイブメンバーである
依存関係の場合、
という名前のメンバーのみが使用されます。 `$^' の値は重複した依存関係を省略しますが、`$+' は重複した依存関係を保持し、その順序を維持します。 `$*'
暗黙のルールが`$(@D)'
`$(@F)'
に一致する語幹。`$@'のディレクトリ部分とディレクトリ内ファイル部分。 `$(*D)'
`$(*F)'
`$*' のディレクトリ部分とディレクトリ内ファイル部分。 `$(%D)'
`$(%F)'
`$%' のディレクトリ部分とディレクトリ内ファイル部分 `$(
`$(^F)'
`$^'のディレクトリ部分とディレクトリ内ファイル部分 `$(+D)'
`$(+F)'
ディレクトリ`$+' の部分とディレクトリ内ファイル部分 `$(?D)'
`$(?F)'
`$?' のディレクトリ部分とディレクトリ内ファイル部分
6.4.非凡变量
`MAKEFILES'
`make' が呼び出されるたびに読み取られる Makefile。 `VPATH'
現在のディレクトリに見つからないファイルのディレクトリ検索パス。 `SHELL'
システムのデフォルトのコマンドインタープリタの名前、通常は
`/bin/sh'。 Makefile で `SHELL' を設定すると、コマンドの実行に使用される
シェルを変更できます。
`MAKE'
`make' が呼び出された名前。
コマンドでこの変数を使用することには特別な意味があります。 `MAKELEVEL'
再帰 (サブ `make') のレベルの数。 `MAKEFLAGS'
`make'に与えられるフラグ。これを環境内で設定することも、
メイクファイルでフラグを設定することもできます。 `SUFFIXES'
`make' がメイクファイルを読み取る前のデフォルトのサフィックスのリスト。