単一のdefaultターゲットですべてを実行する代わりに、個別の出力ごとにターゲットを作成する必要があります。これにより、make は適切に機能し、一度に 1 つのものを正しい順序で (または依存関係グラフで許可されている場合は並行して) ビルドし、各ステップでエラーを適切に報告できます。また、非常に重要なことに、それぞれの個別のターゲットとそれらが依存するものについて make に伝えることで、依存関係が変更されたときに、変更された依存関係のために再構築する必要があるターゲットを make が正確に認識できるようになります。それがMakeの一番の特徴です。
あなたの場合、最終的なターゲットは、ターゲットがmainそれをビルドするようにするためです。これは、次の前提条件であるdefaultと言って行います。mainmain
default: main
次に、 のビルド方法を説明する必要がありますmain。これは、さまざまなオブジェクト ファイルに依存するため、次のように make に指示します。
main: main.o sample.o sample_2.o sample_3.o
これは、それらのオブジェクト ファイルに依存しているため (それらは前提条件です)、最初にビルドされることを示しています。これらの各オブジェクトは、個別にビルドされる別の make ターゲットです。
すべての前提条件が構築されると、レシピを使用してそれらを にリンクするmainため、上記のターゲットにレシピを追加する必要があります。
main: main.o sample.o sample_2.o sample_3.o
g++ main.o sample.o sample_2.o sample_3.o -o main
Make には物事を単純化するための省略形がたくさんあります。たとえば$(CXX)、C++ コンパイラ$@は現在のターゲットを$^意味し、現在のターゲットの前提条件を意味するため、そのルールを次のように単純化できます。
main: main.o sample.o sample_2.o sample_3.o
$(CXX) $^ -o $@
実際に必要なのはそれだけです.o。Make は、組み込みのルールを使用して前提条件を構築する方法を既に知っているため、呼び出されたファイルを見て、main.cppそれをコンパイルして作成できることを認識しmain.o、それを参照sample.cppしてコンパイルしてsample.oなどを作成します。ビルドするために必要なターゲットを決定するためのメイクファイルdefault(つまり、それが必要mainであり、その必要がmain.oあるsample.oなどを決定し、それらが必要main.cppであるなどを既に存在しているため、リンクにsample.cpp必要なすべてが揃うまで前提条件のビルドを開始できます。mainそれを実行して終了できます。)
変更sample_2.cppして再度実行makeすると、それが古くなっていることがわかり、sample_2.o再コンパイルする必要がありますが、他のファイルはまだ問題ありません (それらは依存するファイル.oよりも新しいため)、再コンパイルして再リンクし、すべてを再構築するわけではありませんそうでなければ。.cppsample_2.omain
実際、オブジェクトを実行可能ファイルにリンクするためのデフォルトのレシピを使用することで、さらに単純化できます。
LINK.o = $(CXX)
default: main
main: main.o sample.o sample_2.o sample_3.o
それだけです!ただし、多くの場合、特に初心者にとっては、より詳細なバージョンを使用する方が明確です。これは、Make の自動ルールと変数のすべてに精通していない場合でもカスタマイズしやすいためです。
ヘッダーが変更されたときに再構築されるように、ヘッダー ファイルの依存関係について make に伝えることも役立ちます。これは、コンパイラを使用して前提条件を生成することで自動的に実行できますが、単純なケースでは、makefile に直接追加するだけで済みます。
sample.o: sample.hpp sample.cpp