ソースファイルとオブジェクトファイルを分離してMakefileを書き込もうとしていますが、これを実現する適切な方法がわからないようです。私には2つの方法がありますが、誰かがこれを行うための「正しい」方法を指摘できることを望んでいます。
私のプロジェクトはsrc
フォルダーとobj
フォルダーに分かれており、Makefileはこれらと同じレベルにあります。
最初の方法では、ワイルドカード関数を使用してsrc
内のソースファイルを検索し、次にテキスト置換を使用して対応するオブジェクトファイルを決定します。
SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
これは機能しているようですが、make prog
を実行するたびに、すべてのオブジェクトファイルが再コンパイルされます。 OBJ
変数はすべてのオブジェクトの前にsrc/
を持っている必要があります。そうしないと、「ターゲットを作成するルールがありません」というメッセージが表示されます。プラス面として、prog
ターゲットのpatsubstを使用して、オブジェクトファイルを簡単に指定できます。
2番目の方法も同様ですが、OBJ
変数でvpathとテキスト置換を使用します。
vpath = %.cpp src
vpath = %.o obj
SRC = $(wildcard src/*.cpp)
OBJ = $(subst src/,,$(SRC:.cpp=.o))
POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)
%.o: %.cpp
$(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)
これにより、オブジェクトファイルの再コンパイルが不要になりますが、POJB
ターゲットに別の変数prog
を追加する必要があります(basedirがないとオブジェクトファイルだけでpatsubstを実行できないため)。
どちらの方法も機能し、それぞれに利点がありますが、どちらが「正しい」アプローチであり、どちらでもない場合、このタイプの建物を実現するための適切な方法は何ですか?
あなたの最初の例はほとんどそこにあります:
SRC = $(wildcard src/*.cpp)
OBJ = $(patsubst src/%.cpp, obj/%.o, $(SRC))
prog: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o prog
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -c $< -o $@