2012-12-13 26 views
10

がここに私のMakefileの縮小版である偽のターゲットでは動作しません。しかし、それは私がmakeを実行するたびに再コンパイル:Makefileの依存関係が

$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 
$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 

私は偽のターゲットを使用しないように、私のMakefileを変更する場合は、期待どおりに動作します。新しいメイクファイル:

bin/server.js: src/server.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin src/server.coffee 

結果:

$ make 
mkdir -p bin 
./node_modules/.bin/coffee -c -o bin src/server.coffee 
$ make 
make: `bin/server.js' is up to date. 

は、なぜそれが偽のターゲットと私の依存関係を尊重しないのだろうか?私が尋ねる理由は、実際には単一のファイルを他の単一のファイルにコンパイルするだけでなく、すべての出力ファイルの名前をターゲットとして使用する必要がないためです。

答えて

8

ではなく偽のターゲット(それが必要として@cmotleyが指摘するように、正確に働いている)あなたは余分な作業を避けたい"empty target"次のとおりです。

空のターゲットはAです偽のターゲットの変形。あなたは時々明示的に要求するアクションのレシピを保持するために使用されます。偽のターゲットとは異なり、このターゲットファイルは実際に存在することができます。ファイルの内容は重要ではなく、通常は空です。

空のターゲットファイルの目的は、ルールのレシピが最後に実行されたときの最終変更時刻を記録することです。これは、レシピ内のコマンドの1つがターゲットファイルを更新するためのタッチコマンドであるためです。

しかしが、この場合には、余分な空の出力ファイルを追加する必要は本当にありません - あなたはすでにあなたのCoffeeScriptのコンパイルの出力を持っています!あなたの質問ですでに実証したように、より典型的なMakefileパターンに適合します。あなたは何ができることは、このアプローチにリファクタリングです:正しく偽のですが、余分な作業を行うことはありません素敵な従来の「すべて」のターゲット:

.PHONY: all 
all: bin/server.js 

bin/server.js: src/server.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin src/server.coffee 

は今、次の2つのものを持っています。言及した他の人のよう

.PHONY: all 
all: bin/server.js bin/other1.js bin/other2.js 

bin/%.js: src/%.coffee 
    mkdir -p bin 
    ./node_modules/.bin/coffee -c -o bin $< 
+3

**空のターゲット**はファイルでなければならず、実際にはタイムスタンプとしてのみ使用されていますか?ターゲットルールにレシピ本体(実行されたコマンド付き)を持たせることができる他の種類の '.PHONY 'はありますか?*依存関係の更新が必要なときにのみ実行されます。 '.PHONY'はレシピ本体を持っているかどうかによって違うことをするようになっているので、かなり壊れているようです。 – jozxyqk

4

server.coffeeファイルの変更時刻と比較するには、いくつかのターゲットファイルが必要です。あなたが具体的なターゲットを持っていないので、makeは、出力が新しいかどうかを知ることができません依存関係かどうか、それは常にallをビルドします。

+0

ああ、ありがとう。私は、どのファイルを再コンパイルする必要があるかを計算する方法はわかりませんでした。非常に役に立ちました –

9

メイクのドキュメントによると: - 前提条件重要ではありません

The prerequisites of the special target .PHONY are considered 
to be phony targets. When it is time to consider such a target, 
make will run its recipe unconditionally, regardless of whether 
a file with that name exists or what its last-modification time is. 

http://www.gnu.org/software/make/manual/html_node/Special-Targets.html

メイクは無条件で偽のターゲットのレシピを実行します。あなたが使用する可能性のあるものを

+0

これはかなり簡単です。あなたは、一連のソースファイルに依存する出力ファイルを明示的に宣言する必要がないという目標を達成するための良い回避策を知っていますか? –

+0

いくつかの変数を宣言して、ソースファイルとオブジェクトファイルを追跡することができます。たとえば、SRC = $(ワイルドカード./src/*.c)およびOBJECTS = $(patsubst%.c、%.o、$(SRC))などです。そうすれば$(OBJECTS)がターゲットの前提条件となります。私はそれがあなたがやろうとしていることだと思います。 – cmotley

1

、依存関係が変更されているかどうかを把握するために、ファイルのタイムスタンプでルックスを行います。また、あなたは簡単に複数のファイルを追加することができますので、これは、より汎用的にするよりよい位置にあります。

依存関係のある偽のターゲットを「エミュレート」する場合は、その名前の実際のファイルを作成し、touchコマンドを使用する必要があります(UNIXシステムの場合)。

メイクファイルが変更された場合(つまり、コンパイラフラグが変更されたため、オブジェクトファイルを再コンパイルする必要があるため)、ディレクトリをクリーニングするだけの解決策が必要でした。ここで

は、私が使用したものだ(とあらゆるコンパイルの前に実行されます)makefile_cleanという名前のファイルを持つ:

makefile_clean: makefile 
    @rm '*.o' 
    @sudo touch makefile_clean 

touchコマンドは、現在の時刻に最後に変更されたタイムスタンプを更新します。