Makefileで.PHONY
とはどういう意味ですか? this を実行しましたが、複雑すぎます。
誰かが私に簡単な言葉でそれを説明できますか?
デフォルトでは、Makefileターゲットは「ファイルターゲット」です。他のファイルからファイルを構築するために使用されます。 Makeは、ターゲットがファイルであると想定しているため、Makefileの作成が比較的簡単になります。
foo: bar
create_one_from_the_other foo bar
ただし、ファイルシステム内の物理ファイルを表さないコマンドをMakefileで実行したい場合があります。この良い例は、一般的なターゲット「クリーン」と「すべて」です。これはそうではない可能性がありますが、あなたはmayメインディレクトリにclean
という名前のファイルを持っている可能性があります。そのような場合、デフォルトではclean
ターゲットがこのファイルに関連付けられ、Makeはその依存関係に関してファイルが最新のように見えない場合にのみ実行されるため、Makeは混乱します。
これらの特別なターゲットはphonyと呼ばれ、それらがファイルに関連付けられていないことを明示的に伝えることができます、例えば:
.PHONY: clean
clean:
rm -rf *.o
これで、clean
という名前のファイルがある場合でも、make clean
は期待どおりに実行されます。
Makeに関しては、偽のターゲットは常に最新ではない単なるターゲットであるため、make <phony_target>
を要求するたびに、ファイルシステムの状態に関係なく実行されます。しばしば偽物である一般的なmake
ターゲットには、all
、install
、clean
、distclean
、TAGS
、info
、check
があります。
あなたがinstall
ターゲットを持っていると仮定しましょう。これはmakefileで非常に一般的です。 .PHONY
を not に使用し、install
という名前のファイルがMakefileと同じディレクトリに存在する場合、make install
は なし を実行します。これは、Makeがそのようなレシピを実行してinstall
という名前のファイルを作成することを意味すると解釈するためです。ファイルはすでに存在し、その依存関係は変更されていないので、何もされません。
ただし、install
ターゲットをPHONYにすると、ターゲットが架空のものであることがmakeツールに伝えられ、makeは実際のファイルを作成することを期待するべきではありません。したがって、install
ファイルが存在するかどうかはチェックされません。つまり、a)ファイルが存在してもその動作は変更されず、b)余分なstat()
は呼び出されません。
通常、ターゲットファイルと同じ名前の出力ファイルを生成しないMakefile内のすべてのターゲットはPHONYであるべきです。これには通常、all
、install
、clean
、distclean
などが含まれます。
_ note _ :makeツールはmakefileを読み込み、規則内の ':'記号の両側にあるファイルの変更タイムスタンプをチェックします。
ディレクトリ 'test'には、以下のファイルがあります。
prerit@vvdn105:~/test$ ls
hello hello.c makefile
Makefileでは、規則は次のように定義されています。
hello:hello.c
cc hello.c -o hello
ここで、ファイル 'hello'が、 'hello.c'ファイルの後に作成されたデータを含むテキストファイルであるとします。そのため、「hello」の修正(または作成)タイムスタンプは、「hello.c」よりも新しくなります。そのため、コマンドラインから 'make hello'を呼び出すと、次のように出力されます。
make: `hello' is up to date.
ここで 'hello.c'ファイルにアクセスし、その中にいくつかの空白を入れてください。これはコードの構文やロジックに影響を与えず、保存して終了します。これで、hello.cの修正タイムスタンプは、 'hello'の修正タイムスタンプよりも新しくなりました。さて、あなたが 'make hello'を呼び出すと、それは以下のようにコマンドを実行します。
cc hello.c -o hello
そして、ファイル 'hello'(テキストファイル)は新しいバイナリファイル 'hello'で上書きされます(上記のコンパイルコマンドの結果)。
次のようにmakefileで.PHONYを使用するとします。
.PHONY:hello
hello:hello.c
cc hello.c -o hello
その後、 'make hello'を呼び出すと、pwdに 'hello'という名前のファイルが存在する場合は無視され、毎回コマンドが実行されます。
Makefileにtargetの依存関係がないとしましょう。
hello:
cc hello.c -o hello
そして 'hello'ファイルはすでにpwdの 'test'に存在し、 'make hello'は常に以下のように表示されます。
make: `hello' is up to date.
.PHONY: install
ファイル名ではないビルドターゲットです。
最良の説明はGNU makeマニュアル自身です: 4.6 Phony Targetsセクション 。
.PHONY
はmakeの 特別な組み込みターゲット名の1つです 。あなたが興味を持っているかもしれない他のターゲットがあるので、それはこれらの参考文献を読み飛ばす価値があります。
.PHONYターゲットを考慮する時期になると、makeはその名前のファイルが存在するかどうか、または最終変更日時に関係なく、レシピを無条件に実行します。
all
やclean
のようなmakeの 標準ターゲット にも興味があるかもしれません。
「.PHONY」の重要な扱い方も1つあります。物理ターゲットが、別の物理ターゲットに依存する偽のターゲットに依存している場合です。
TARGET1-> PHONY_FORWARDER1-> PHONY_FORWARDER2-> TARGET2
TARGET2を更新した場合、TARGET1がTARGET1に対して失効していると見なされるため、TARGET1を再構築する必要があります。 そして、このように実際に機能します。
トリッキーな部分は、TARGET2 is't TARGET1に対して古くなっている場合です。この場合、TARGET1を再構築しないことを期待する必要があります。
偽のターゲットはとにかく(偽のターゲットが通常行うように)実行された、つまり偽のターゲットは更新されたと見なされたであるため、これは驚くほど機能しません。そしてそのためTARGET1は偽のターゲットに対して古いと見なされます。
考慮してください:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
これで遊ぶことができます:
Fileallは、偽のターゲットを介して間接的にfile1に依存していることがわかりますが、この依存関係によりalwaysが再構築されます。 fileall
の依存関係をfilefwd
からfile
に変更すると、毎回fileall
は再構築されなくなりますが、依存ターゲットのいずれかがそれに対して古い場合のみファイル。
私はよくそれらを使用してデフォルトのターゲットに発砲しないように伝えます。
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
PHONYがないと、make superclean
はclean
、andsomethingelse
、およびcatcher superclean
を起動します。しかしPHONYでは、make superclean
はcatcher superclean
を起動しません。
clean
ターゲットをPHONYにすると言っても心配する必要はありません。完全に偽物ではないからです。クリーンなファイルは生成されませんが、起動するコマンドがあるため、makeは最終的なターゲットと見なします。
しかし、superclean
ターゲットは実際には偽物ですので、makeはsuperclean
ターゲットのためのdepsを提供する何か他のものとそれを積み重ねようとします - これは他のsuperclean
ターゲットと%
ターゲットを含みます。
andsomethingelse
やblah
については何も言っていないので、それらは明らかにキャッチャーに行きます。
出力は次のようになります。
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah