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


1739

.PHONYMakefileで何を意味しますか?私はこれを経験しましたが、複雑すぎます。

誰かが簡単に説明してくれますか?

回答:


1947

デフォルトでは、Makefileターゲットは「ファイルターゲット」です。他のファイルからファイルをビルドするために使用されます。Makeはターゲットがファイルであることを前提としているため、Makefileの作成が比較的簡単になります。

foo: bar
  create_one_from_the_other foo bar

ただし、ファイルシステム内の物理ファイルを表さないコマンドをMakefileで実行したい場合があります。この良い例は、「クリーン」と「すべて」という共通のターゲットです。おそらくそうではありませんが、メインディレクトリに名前の付いたファイルがある可能性がありますclean。このような場合、デフォルトではcleanターゲットがこのファイルに関連付けられ、Makeは依存関係に関してファイルが最新のように見えない場合にのみ実行するため、Makeは混乱します。

これらの特別なターゲットはと呼ばれ、ファイルに関連付けられていないことをMakeに明示的に伝えることができます。例:

.PHONY: clean
clean:
  rm -rf *.o

今、make clean期待どおりという名前のファイルを持っている場合でも実行されますclean

Makeに関して言えば、偽のターゲットは常に古くなっているターゲットにすぎないためmake <phony_target>、に問い合わせると、ファイルシステムの状態とは関係なく実行されます。いくつかの一般的なmake多くの場合、偽のある標的であります:allinstallcleandistcleanTAGSinfocheck


49
@eSKay:「なぜ「偽」と呼ばれるのですか?」-それは本当の目標ではないからです。つまり、ターゲット名は、そのターゲットのコマンドによって生成されるファイルではありません。
バーナード

96
@Lazer:英語のネイティブスピーカーかどうかはわかりません。私は違います。偽という言葉は、それがどのように聞こえるかを意味するものではありません。en.wiktionary.org/wiki/phonyは言う:詐欺; 偽; 誤解を招く外観を持っています。
バーバー

57
この回答は完全には完全ではありませんが、リンクされたチュートリアルで対処することができます。.PHONYは、ターゲットがトポロジーソートの一部である場合、Makefile内のラベル/ファイルを強制的に構築します。つまり、偽に設定された 'cleanup:'ラベルがあり、インストールラベルがクリーンアップを前提条件として定義されている場合、つまり、 'install:cleanup'の場合、Makefileがビルドしようとすると常にクリーンアップが実行されます。 'インストール'。これは、成功したかどうかに関係なく、常に実行したいステップに役立ちます。タイムスタンプを無視して、強制的に実行します。
synthesizerpatel

9
タスクと同じ名前のファイルがない限り、.PHONYを使用する必要がないことに注意してください。とにかく常にタスクが実行され、Makefileが読みやすくなります。
バーナード

15
「偽のターゲットは、常に時代遅れのターゲットである」-素晴らしい説明!
Danijel

730

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

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

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


6
@PineappleUndertheSea受け入れられた回答は、最初の無価値のレベルから大幅に改善され、今ではこれと同じくらい良いです。私はあなたのコメントを理解するためにその改訂履歴を調べなければなりませんでした。
Mark Amery 14

2
コードベースに「install」などの名前のファイルを含めることはないので、これはちょっと無意味なようです。ほとんどのファイルにはファイル拡張子が付き、ファイル拡張子のないファイルは通常「README」のようにすべて大文字になります。次に、「install.sh」ではなく「install」という名前のbashスクリプトがある場合、時間が悪くなります。
核兵器

6
@JasonTuこれは必ずしも正しいとは限りません。Bashスクリプトの規則では、main関数のように実行される「プログラム」の.shor .bash拡張子を省略し、含めるライブラリの拡張子の追加を予約するように求められます(source mylib.sh)。実際、私がこのSOの質問にたどり着いたのは、自分のMakefileと同じディレクトリにスクリプトがあったためですinstall
Kyle

10
@カイルはい、自分の過去の意味がよくわかりません。最近、私は.PHONYいつも使用しています...
2016

2
@JasonTuここでの解決策は簡単です。タイムマシンを構築し、過去の自分を「置き換える」ことです。自分が.PHONYバージョンであることをだれも気付かないように、シャベルを一緒に持って行くことをお勧めします。
Mateen Ulhaq

120

: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 'test'に存在するファイルはすべて無視され、毎回コマンドが実行されます。

ここで、「hello」ターゲットに依存関係が宣言されていないとします。

hello:
    cc hello.c -o hello

「hello」ファイルがpwdの「test」にすでに存在している場合、「make hello」は常に次のように表示されます。

make: `hello' is up to date.

3
これは、実行するコマンドが意味をなすだけでなく、最終的にmake全体として意味をなすようになります。それはすべてファイルについてです!この回答をありがとうございます。
Kzqai 2016

80
.PHONY: install
  • 「インストール」という単語がこのMakefile内のファイル名を表していないことを意味します。
  • Makefileは、同じディレクトリにある「install」と呼ばれるファイルとは何の関係もありません。

45

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


33

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

.PHONYmakeの特別な組み込みターゲット名の1つです。あなたが興味を持っているかもしれない他のターゲットがあるので、これらの参照を通してざっと見る価値があります。

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

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


11

「.PHONY」には、1つの重要なトリッキーな扱いもあります。物理ターゲットが別の物理ターゲットに依存している偽のターゲットに依存している場合です。

TARGET1-> PHONY_FORWARDER1-> PHONY_FORWARDER2-> TARGET2

TARGET2を更新した場合、TARGET1はTARGET1に対して古くなっていると見なす必要があるため、TARGET1を再構築する必要があります。そして、それは本当にこのように機能します。

トリッキーな部分は、TARGET2 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に依存していることがわかりますが、この依存関係のために常に再構築されます。あなたが依存関係を変更した場合fileallからfilefwdfile、今fileallたびに再構築されませんが、ときにのみ依存ターゲットのいずれかがファイルとしてに対して古くなっています。


5

特別なターゲットを.PHONY:使用すると、偽のターゲットを宣言できるため、make実際のファイル名としてチェックされません。このようなファイルがまだ存在する場合でも、常に動作します。

あなたはあなたにいくつか.PHONY:を置くことができますMakefile

.PHONY: all

all : prog1 prog2

...

.PHONY: clean distclean

clean :
    ...
distclean :
    ...

偽のターゲットを宣言する別の方法があります。単に「::」と入力します。

all :: prog1 prog2

...

clean ::
    ...
distclean ::
    ...

「::」は特別な意味を持ちます。ターゲットは偽ですプラス、彼らは数回表示されることがあります。

clean ::
    rm file1

...


clean ::
    rm file2

コマンドブロックは次々と呼び出されます。


3

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

superclean: clean andsomethingelse

blah: superclean

clean:
   @echo clean

%:
   @echo catcher $@

.PHONY: superclean

偽なければ、make superclean解雇だろうcleanandsomethingelsecatcher superclean。PHONYを使用make supercleanすると、は起動しませんcatcher superclean

私たちは作ることを言うことについて心配する必要はありません clean完全に偽物ではないためターゲットをPHONYにはありません。クリーンなファイルを生成することはありませんが、起動するコマンドがあるため、makeは最終的なターゲットであると考えます。

ただし、supercleanターゲットは実際には偽物であるため、makeはsupercleanターゲットにdepを提供する他のものと積み重ねようとします—これには他のsupercleanターゲットとターゲットが含まれ%ます。

andsomethingelseor については何も言わないblahので、キャッチャーのところに行きます。

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

$ make clean
clean

$ make superclean
clean
catcher andsomethingelse

$ make blah 
clean
catcher andsomethingelse
catcher blah
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.