26

これが私の Makefile の縮小版です。

.PHONY: all 

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

make実行して、変更されたときにのみ再コンパイルしたいsrc/server.coffee。ただし、実行するたびに再コンパイルされますmake

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

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

4

5 に答える 5

20

余分な作業を避けたいときに使用できるのは、偽のターゲット (@cmotley が指摘しているように、正確に機能しています) ではなく、「空のターゲット」です。

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

空のターゲット ファイルの目的は、ルールのレシピが最後に実行されたときの最終変更時刻を記録することです。これは、レシピ内のコマンドの 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

これで、必要なものの両方が得られました。適切に偽物である従来型の "all" ターゲットと、余分な作業を行わないビルド ルールです。また、これをより一般的なものにして、ファイルを簡単に追加できるようにすることもできます。

.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 $<
于 2013-12-21T18:11:43.693 に答える
19

Makeのドキュメントによると:

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

Make は PHONY ターゲットのレシピを無条件に実行します - 前提条件は関係ありません。

于 2012-12-13T03:48:49.200 に答える
5

server.coffee ファイルの変更時間と比較するには、ターゲット ファイルが必要です。具体的なターゲットmakeがないため、出力が依存関係よりも新しいかどうかを判断できないため、常にビルドされallます。

于 2012-12-13T03:47:27.883 に答える
4

他の人が述べたように、 make はファイルのタイムスタンプを調べて、依存関係が変更されたかどうかを判断します。

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

Makefile が変更された場合 (つまり、コンパイラ フラグが変更されたため、オブジェクト ファイルを再コンパイルする必要があった場合) にのみディレクトリをクリーンアップするソリューションが必要でした。

という名前のファイルで使用したもの(およびすべてのコンパイルの前に実行)は次のmakefile_cleanとおりです。

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

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

于 2015-02-13T15:50:47.433 に答える