ビルドして別のメイクファイルを呼び出すメイクファイルがあります。このmakefileは、作業を行うより多くのmakefileを呼び出すため、実際には変更されません。したがって、プロジェクトが構築され、最新の状態にあると考え続けます。
dnetdev11 ~ # make
make: `release' is up to date.
メイクファイルにターゲットを再構築させるにはどうすればよいですか?
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つ以上のターゲットを phony として宣言できます。
偽のターゲットとは、実際にはファイルの名前ではないターゲットです。むしろ、明示的な要求を行ったときに実行されるレシピの単なる名前です。偽のターゲットを使用する理由は2つあります。同じ名前のファイルとの競合を回避するためと、パフォーマンスを向上させるためです。
...
偽のターゲットは、実際のターゲットファイルの前提条件ではありません。そうである場合、そのレシピは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
コマンドがあるためです。 「リリース」と呼ばれるファイルまたはディレクトリが存在し、依存関係がなく、最新であることが原因である可能性があります。次に、実際の理由があります...
他の誰かが、間違いなく正しい.PHONYを提案しました。 .PHONYは、入力と出力の間の日付比較が無効であるルールに使用する必要があります。 output: input
という形式のターゲットはないため、それらすべてに.PHONYを使用する必要があります!
とはいえ、おそらく、さまざまなファイル名に対してmakefileの先頭にいくつかの変数を定義し、入力セクションと出力セクションの両方を持つ実際のmakeルールを定義して、makeの利点を活用できるようにする必要があります。つまり、実際にコンパイルするだけですコピーするために必要なもの!
編集:例を追加しました。未テストですが、これがあなたのやり方です。
.PHONY: clean
clean:
$(clean)
この単純な手法により、強制が望ましくない場合にメイクファイルが正常に機能するようになります。 makefileの最後にforceという新しいターゲットを作成します。 forceターゲットは、デフォルトのターゲットが依存するファイルにタッチします。以下の例では、touch myprogram.cppを追加しています。 makeへの再帰呼び出しも追加しました。これにより、make forceと入力するたびにデフォルトのターゲットが作成されます。
yourProgram: yourProgram.cpp
g++ -o yourProgram yourProgram.cpp
force:
touch yourProgram.cpp
make
正しく思い出せば、「make」はタイムスタンプ(ファイル変更時刻)を使用して、ターゲットが最新かどうかを判断します。再ビルドを強制する一般的な方法は、「touch」コマンドを使用してそのタイムスタンプを更新することです。 makefileで 'touch'を呼び出して、ターゲットの1つ(おそらくそれらのサブmakefileの1つ)のタイムスタンプを更新し、Makeにそのコマンドを強制的に実行させることができます。
私はこれを試してみましたが、うまくいきました
これらの行をMakefileに追加します
clean:
rm *.o output
new: clean
$(MAKE) #use variable $(MAKE) instead of make to get recursive make calls
保存して電話する
make new
そして、それは再びすべてを再コンパイルします
どうした?
1)「新規」はクリーンを呼び出します。 「clean」は「rm」を実行し、「。o」の拡張子を持つすべてのオブジェクトファイルを削除します。
2)「new」は「make」を呼び出します。 「make」は「.o」ファイルがないことを確認するため、すべての「.o」を再度作成します。その後、リンカはすべての.oファイルを1つの実行可能出力にリンクします
幸運を
すでに正常にコンパイルされた出力を保存する必要がない場合
nmake /A
すべてを再構築
Millerの 再帰的に有害と見なされる に従って、$(MAKE)
!を呼び出さないでください。示している場合、これは無害です。これは実際にはメイクファイルではなく、単なるラッパースクリプトであり、シェルで作成されている可能性があるためです。しかし、あなたはより深い再帰レベルでそのように続けると言うので、おそらくあなたはその目を見張るようなエッセイで示された問題に遭遇したでしょう。
もちろん、GNUを使用すると、避けるのが面倒です。そして、彼らはこの問題を認識していても、文書化された方法です。
OTOH、 makepp はこの問題の解決策として作成されました。メイクファイルはディレクトリごとに作成できますが、プロジェクトの完全なビューにまとめられます。
ただし、レガシーメイクファイルは再帰的に書き込まれます。そのため、$(MAKE)
がサブリクエストをメインのmakeppプロセスに戻す以外の何もしない回避策があります。サブメイク間で冗長な、またはさらに悪いことに矛盾することを行う場合にのみ、--traditional-recursive-make
を要求する必要があります(もちろんmakeppのこの利点を無効にします)。私はあなたの他のメイクファイルを知りませんが、それらがきれいに書かれていれば、makeppで必要な再構築が自動的に行われるはずです。
make clean
は、すでにコンパイルされているすべてのオブジェクトファイルを削除します。
すでに言及しましたが、touch
の使用に追加できると考えました
コンパイルするすべてのソースファイルをtouch
すると、touch
コマンドはファイルのタイムスタンプをtouch
コマンドが実行されたシステム時刻に変更します。
ソースファイルのtimstampは、make
がファイルが変更され、再コンパイルする必要があることを「知る」ために使用するものです
例:プロジェクトがc ++プロジェクトの場合、touch *.cpp
を実行してからmake
を再度実行すると、makeはプロジェクト全体を再コンパイルする必要があります。
実際にはターゲットが何であるかに依存します。それが偽のターゲットである場合(つまり、ターゲットがファイルに関連していない場合)、. PHONYとして宣言する必要があります。
ただし、ターゲットが偽のターゲットではなく、何らかの理由でそれを再構築する場合(例:__TIME__前処理マクロを使用する場合)、ここの回答で説明されているFORCEスキームを使用する必要があります。