質問
ビルドして別のメイクファイルを呼び出すメイクファイルがあります。このメイクファイルは、作業を行うより多くのメイクファイルを呼び出すため、実際には変更されません。したがって、プロジェクトが構築され、最新のものであると考え続けます。
dnetdev11 ~ # make
make: `release' is up to date.
どのようにしてmakefileにターゲットを再構築させるのですか?
clean = $(MAKE) -f ~/xxx/xxx_compile.workspace.mak clean
build = svn up ~/xxx \
$(clean) \
~/cbp2mak/cbp2mak -C ~/xxx ~/xxx/xxx_compile.workspace \
$(MAKE) -f ~/xxx/xxx_compile.workspace.mak $(1) \
release:
$(build )
debug:
$(build DEBUG=1)
clean:
$(clean)
install:
cp ~/xxx/source/xxx_utility/release/xxx_util /usr/local/bin
cp ~/xxx/source/xxx_utility/release/xxxcore.so /usr/local/lib
注:無実の人を保護するために削除された名前
編集:最終修正バージョン:
clean = $(MAKE) -f xxx_compile.workspace.mak clean;
build = svn up; \
$(clean) \
./cbp2mak/cbp2mak -C . xxx_compile.workspace; \
$(MAKE) -f xxx_compile.workspace.mak $(1); \
.PHONY: release debug clean install
release:
$(call build,)
debug:
$(call build,DEBUG=1)
clean:
$(clean)
install:
cp ./source/xxx_utillity/release/xxx_util /usr/bin
cp ./dlls/Release/xxxcore.so /usr/lib
解決
ターゲットの1つ以上をとして宣言できます偽物。
偽のターゲットとは、実際にはファイルの名前ではないターゲットです。むしろそれ 明示的に指定したときに実行されるレシピの名前です 要求。偽のターゲットを使用する理由は2つあります。 同じ名前のファイルと競合し、パフォーマンスを向上させます。
...
偽のターゲットは、実際のターゲットファイルの前提条件ではありません。もし それは、makeがそれを更新するたびにそのレシピが実行されます ファイル。偽のターゲットが本物の前提条件にならない限り ターゲット、偽のターゲットレシピは、偽の ターゲットは指定された目標です
他のヒント
makeの -B
スイッチ(長い形式は-always-make
)は、 make
にタイムスタンプを無視して指定されたターゲット。これはmakeを使用する目的に反する場合がありますが、必要な場合があります。
make
のSunマニュアルに記載されていたトリックの1つは、(存在しない)ターゲット '.FORCE'を使用することです。これを行うには、以下を含むファイルforce.mkを作成します。
.FORCE:
$(FORCE_DEPS): .FORCE
次に、既存のメイクファイルの名前が makefile
であると仮定すると、次のコマンドを実行できます。
make FORCE_DEPS=release -f force.mk -f makefile release
.FORCE
は存在しないため、それに依存するものはすべて古くなって再構築されます。
これはすべてのバージョンの make
で機能します。 Linuxでは、GNU Makeがあるため、前述のように.PHONYターゲットを使用できます。
make
がリリースを最新であると考える理由も考慮する価値があります。これは、実行されたコマンドの中に touch release
コマンドがあるためです。 「release」と呼ばれるファイルまたはディレクトリが存在し、依存関係がなく、最新であるためです。次に、実際の理由があります...
他の誰かが、間違いなく正しい.PHONYを提案しました。 .PHONYは、入力と出力の間の日付比較が無効なルールに使用する必要があります。 output:input
という形式のターゲットはないため、すべてのターゲットに.PHONYを使用する必要があります!
とはいえ、おそらく、さまざまなファイル名に対してmakefileの先頭にいくつかの変数を定義し、入力セクションと出力セクションの両方を持つ実際のmakeルールを定義して、makeの利点を活用できるようにする必要があります。実際にコピーするために必要なものだけをコンパイルします!
編集:例が追加されました。テストされていませんが、これはあなたが行う方法です。PHONY
.PHONY: clean
clean:
$(clean)
正しく思い出すと、「make」はタイムスタンプ(ファイル変更時間)を使用して、ターゲットが最新かどうかを判断します。再ビルドを強制する一般的な方法は、「touch」コマンドを使用してそのタイムスタンプを更新することです。 makefileで 'touch'を呼び出して、ターゲットの1つ(おそらくそれらのサブmakefileの1つ)のタイムスタンプを更新し、Makeにそのコマンドを強制的に実行させることができます。
この単純な手法により、強制が望ましくない場合にメイクファイルが正常に機能します。 makefile の最後に force という新しいターゲットを作成します。 force ターゲットは、デフォルトのターゲットが依存するファイルにタッチします。以下の例では、 touch myprogram.cpp を追加しています。また、 make への再帰呼び出しを追加しました。これにより、 make force と入力するたびにデフォルトのターゲットが作成されます。
yourProgram: yourProgram.cpp
g++ -o yourProgram yourProgram.cpp
force:
touch yourProgram.cpp
make
これを試してみましたが、うまくいきました
これらの行をMakefileに追加
clean:
rm *.o output
new: clean
$(MAKE) #use variable $(MAKE) instead of make to get recursive make calls
保存して呼び出し
make new
そして、すべてを再コンパイルします
何が起こったのですか?
1) 'new'はcleanを呼び出します。 「clean」は「rm」を実行し、「。o」の拡張子を持つすべてのオブジェクトファイルを削除します。
2) 'new'は 'make'を呼び出します。 「make」は「.o」ファイルがないことを確認するため、すべての「.o」を再度作成します。その後、リンカーはすべての.oファイルを1つの実行可能出力にリンクします
幸運
Millerの再帰的で有害と見なされるによると、 $(MAKE)
!あなたが示す場合、これは無害です。なぜなら、これは実際にはメイクファイルではなく、単なるラッパースクリプトであり、シェルで作成されている可能性があるからです。しかし、あなたはより深い再帰レベルでそのように続けていると言うので、おそらくあなたはその目を見張るようなエッセイに示されている問題に遭遇したでしょう。
もちろん、GNUでは回避するのは面倒です。そして、彼らはこの問題に気付いていても、文書化された方法です。
OTOH、 makepp は、この問題の解決策として作成されました。 。メイクファイルはディレクトリごとに作成できますが、プロジェクトの完全なビューにまとめられます。
ただし、レガシーメイクファイルは再帰的に書き込まれます。そのため、 $(MAKE)
がサブリクエストをメインのmakeppプロセスに戻す以外の何もしない回避策があります。サブメイク間で冗長な、さらに悪いことに矛盾することを行う場合にのみ、-traditional-recursive-make
を要求する必要があります(もちろんmakeppのこの利点を無効にします)。私はあなたの他のメイクファイルを知りませんが、それらがきれいに書かれていれば、makeppで必要な再構築が自動的に行われ、他の人がここで提案するハックの必要はありません。
すでに正常にコンパイルされた出力を保存する必要がない場合
nmake /A
すべてを再構築
実際には、ターゲットが何であるかによって異なります。偽のターゲットである場合(つまり、ターゲットがファイルに関連していない場合)、. PHONYとして宣言する必要があります。
しかし、ターゲットが偽のターゲットではないが、何らかの理由でそれを再構築したい場合(例:__TIME__前処理マクロを使用する場合)、こちらの回答で説明されているFORCEスキームを使用する必要があります。
既に述べたが、 touch
コンパイルするすべてのソースファイルを touch
する場合、 touch
コマンドはファイルのタイムスタンプを touch
のシステム時間に変更しますコマンドが実行されました。
ソースファイルのtimstampは、 make
が「知る」ために使用するものです。ファイルが変更されたため、再コンパイルする必要があります
例:プロジェクトがc ++プロジェクトの場合、 touch * .cpp
を実行し、 make
を再度実行すると、makeはプロジェクト全体を再コンパイルします。
make clean
は、すでにコンパイルされているすべてのオブジェクトファイルを削除します。
Linuxシステム(Centos 6.2)では、ルールが実際にターゲットに一致するファイルを作成する場合、ターゲット.PHONYを宣言することとFORCEに偽の依存関係を作成することには大きな違いがあります。ファイルを毎回再生成する必要がある場合、両方が必要でした ファイルの偽の依存関係FORCE、および偽の依存関係の.PHONY。
間違った:
date > $@
右:
FORCE
date > $@
FORCE:
.PHONY: FORCE