回答:
デフォルトでは、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
多くの場合、偽のある標的であります:all
、install
、clean
、distclean
、TAGS
、info
、check
。
install
makefileで非常に一般的なターゲットがあるとします。を使用せず.PHONY
、という名前のファイルinstall
がMakefileと同じディレクトリに存在する場合、何もmake install
実行されません。これは、Makeが「そのようなレシピを実行して名前のファイルを作成する」という意味のルールを解釈するためinstall
です。ファイルは既に存在し、依存関係は変更されなかったため、何も行われません。
ただし、install
ターゲットをPHONYにすると、ターゲットが架空のものであり、makeが実際のファイルを作成することをmakeが期待してはならないことをmakeツールに伝えます。したがって、install
ファイルが存在するかどうかはチェックされません。つまり、a)ファイルが存在しても動作は変更されず、b)extra stat()
は呼び出されません。
通常、ターゲット名と同じ名前の出力ファイルを生成しないMakefile内のすべてのターゲットは、PHONYである必要があります。これは、一般的に含まれall
、install
、clean
、distclean
、など。
.sh
or .bash
拡張子を省略し、含めるライブラリの拡張子の追加を予約するように求められます(source mylib.sh
)。実際、私がこのSOの質問にたどり着いたのは、自分のMakefileと同じディレクトリにスクリプトがあったためですinstall
.PHONY
いつも使用しています...
.PHONY
バージョンであることをだれも気付かないように、シャベルを一緒に持って行くことをお勧めします。
注: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.
make
全体として意味をなすようになります。それはすべてファイルについてです!この回答をありがとうございます。
.PHONY: install
最良の説明は、GNU makeマニュアル自体です:4.6 Phony Targetsセクション。
.PHONY
makeの特別な組み込みターゲット名の1つです。あなたが興味を持っているかもしれない他のターゲットがあるので、これらの参照を通してざっと見る価値があります。
.PHONYターゲットを検討する時期になると、makeは、その名前のファイルが存在するかどうか、またはその最終変更時刻に関係なく、無条件にレシピを実行します。
やなどのmakeの標準ターゲットにも興味があるかもしれませんall
clean
。
「.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
これで遊ぶことができます:
fileallが偽のターゲットを介して間接的にfile1に依存していることがわかりますが、この依存関係のために常に再構築されます。あなたが依存関係を変更した場合fileall
からfilefwd
のfile
、今fileall
たびに再構築されませんが、ときにのみ依存ターゲットのいずれかがファイルとしてに対して古くなっています。
特別なターゲットを.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
コマンドブロックは次々と呼び出されます。
私はよくそれらを使用して、デフォルトのターゲットに発砲しないように伝えます。
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
偽なければ、make superclean
解雇だろうclean
、andsomethingelse
とcatcher superclean
。PHONYを使用make superclean
すると、は起動しませんcatcher superclean
。
私たちは作ることを言うことについて心配する必要はありません clean
完全に偽物ではないためターゲットをPHONYにはありません。クリーンなファイルを生成することはありませんが、起動するコマンドがあるため、makeは最終的なターゲットであると考えます。
ただし、superclean
ターゲットは実際には偽物であるため、makeはsuperclean
ターゲットにdepを提供する他のものと積み重ねようとします—これには他のsuperclean
ターゲットとターゲットが含まれ%
ます。
andsomethingelse
or については何も言わないblah
ので、キャッチャーのところに行きます。
出力は次のようになります。
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah