web-dev-qa-db-ja.com

メイクファイルでの.PHONYの目的は何ですか?

Makefileで.PHONYとはどういう意味ですか? this を実行しましたが、複雑すぎます。

誰かが私に簡単な言葉でそれを説明できますか?

1398
Lazer

デフォルトでは、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ターゲットには、allinstallcleandistcleanTAGSinfocheckがあります。

1669
Eli Bendersky

あなたがinstallターゲットを持っていると仮定しましょう。これはmakefileで非常に一般的です。 .PHONY not に使用し、installという名前のファイルがMakefileと同じディレクトリに存在する場合、make install なし を実行します。これは、Makeがそのようなレシピを実行してinstallという名前のファイルを作成することを意味すると解釈するためです。ファイルはすでに存在し、その依存関係は変更されていないので、何もされません。

ただし、installターゲットをPHONYにすると、ターゲットが架空のものであることがmakeツールに伝えられ、makeは実際のファイルを作成することを期待するべきではありません。したがって、installファイルが存在するかどうかはチェックされません。つまり、a)ファイルが存在してもその動作は変更されず、b)余分なstat()は呼び出されません。

通常、ターゲットファイルと同じ名前の出力ファイルを生成しないMakefile内のすべてのターゲットはPHONYであるべきです。これには通常、allinstallcleandistcleanなどが含まれます。

682
George Y.

_ 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.
88
prerit jain
.PHONY: install
  • 「インストール」という単語がこのMakefileのファイル名を表していないことを意味します。
  • makefileが同じディレクトリ内の "install"というファイルとは関係がないことを意味します。
70
YourBestBet

ファイル名ではないビルドターゲットです。

38
JohnMcG

最良の説明はGNU makeマニュアル自身です: 4.6 Phony Targetsセクション

.PHONYはmakeの 特別な組み込みターゲット名の1つです 。あなたが興味を持っているかもしれない他のターゲットがあるので、それはこれらの参考文献を読み飛ばす価値があります。

.PHONYターゲットを考慮する時期になると、makeはその名前のファイルが存在するかどうか、または最終変更日時に関係なく、レシピを無条件に実行します。

allcleanのようなmakeの 標準ターゲット にも興味があるかもしれません。

26
James Wald

「.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

これで遊ぶことができます:

  • 最初に「ソースファイル」を準備するために「make prepare」を行います
  • 特定のファイルをタッチして、更新されたファイルを確認します

Fileallは、偽のターゲットを介して間接的にfile1に依存していることがわかりますが、この依存関係によりalwaysが再構築されます。 fileallの依存関係をfilefwdからfileに変更すると、毎回fileallは再構築されなくなりますが、依存ターゲットのいずれかがそれに対して古い場合のみファイル。

11
Ethouris

私はよくそれらを使用してデフォルトのターゲットに発砲しないように伝えます。

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

PHONYがないと、make supercleancleanandsomethingelse、およびcatcher supercleanを起動します。しかしPHONYでは、make supercleancatcher supercleanを起動しません。

cleanターゲットをPHONYにすると言っても心配する必要はありません。完全に偽物ではないからです。クリーンなファイルは生成されませんが、起動するコマンドがあるため、makeは最終的なターゲットと見なします。

しかし、supercleanターゲットは実際には偽物ですので、makeはsupercleanターゲットのためのdepsを提供する何か他のものとそれを積み重ねようとします - これは他のsupercleanターゲットと%ターゲットを含みます。

andsomethingelseblahについては何も言っていないので、それらは明らかにキャッチャーに行きます。

出力は次のようになります。

$ make clean
clean

$ make superclean
clean
catcher andsomethingelse

$ make blah 
clean
catcher andsomethingelse
catcher blah
1
jettero