Makefileは変更されていないファイルをコンパイルします

Makefileは変更されていないファイルをコンパイルします

オブジェクト ファイルを別のディレクトリに取得しようとしましたが、そのディレクトリはソース ディレクトリ ツリーを反映します。これで動作しましたが、行に欠落部分があります$(OBJ):(そうですよね?)。そのため、ソースを変更するかどうかに関係なく、再コンパイルされます。確認してください。

SRC_PATH=../src/
CC=g++
CFLAGS=-c -Wall
LDFLAGS=-lSDL -lSDL_gfx
INCL=-I $(SRC_PATH)include/
EXE=run

SRC=$(wildcard $(SRC_PATH)*.cpp $(SRC_PATH)game/*.cpp $(SRC_PATH)player/*.cpp)
OBJ=$(subst ../src, ../obj, $(SRC:.cpp=))
OBJ_O=$(addsuffix .o, $(OBJ))

all: $(SRC) $(EXE)

$(EXE): $(OBJ)
    $(CC) $(LDFLAGS) $(OBJ_O) -o $@

$(OBJ):
    $(CC) $(CFLAGS) $(INCL) -o $(addsuffix .o, $@) $(subst ../obj, ../src, $@).cpp

clean:
    rm -rf run $(OBJ_O)

編集

これは意図したとおりに動作します。再コンパイルされません。また、複雑なサフィックスが前後にないので、読みやすくなります。以下の回答とコメントを参照してください。

SRC_PATH=../src/
CC=g++
CFLAGS=-c -Wall
LDFLAGS=-lSDL -lSDL_gfx
INCL=-I $(SRC_PATH)include/
EXE=run

SRC=$(wildcard $(SRC_PATH)*.cpp $(SRC_PATH)game/*.cpp $(SRC_PATH)player/*.cpp)
OBJ=$(subst ../src, ../obj, $(SRC:.cpp=.o))

all: $(SRC) $(EXE)

$(EXE): $(OBJ)
    $(CC) $(LDFLAGS) $(OBJ) -o $@

../obj/%.o: ../src/%.cpp
    $(CC) $(CFLAGS) $(INCL) -o $@ $<

clean:
    rm -rf run $(OBJ)

答え1

いくつかの問題があります:

まず、OBJ 変数はビルドされるファイルのリストを参照しません。たとえば、ソース ファイル src/a.cpp と src/b.cpp がある場合、OBJ には obj/a と obj/b が含まれます。したがって、OBJ の代わりに OBJ_O を使用します。

2 番目に、OBJ ファイルをビルドするためのターゲットでは、.cpp ファイルと .o ファイル間の依存関係が指定されていません。その行では依存関係情報を指定できないため、.o ファイルを作成するためのルールをそのように記述するのは問題です。.o ファイルを作成するためのルールを完全に書き直します。

../obj/%.o: ../src/%.cpp
    $(CC) $(CFLAGS) $(INCL) -o "$@" "$<"

これにより、各 .o ファイルが個別にビルドされ、各 .o ファイルは対応する .cpp ファイルに依存します。

../obj/**.oこれは、一致するすべてのファイルからファイルを作成するためのルールです../src/**.cpp

答え2

わかりやすく言うと:

主な問題はまさにそのラインである$(OBJ):

問題は、../src/a.cpp変数OBJに含まれるソース ファイルがある場合../obj/a、ルールは$(OBJ):「次のレシピを使用してファイルを構築する../obj/a」という意味になります。しかし、レシピはそうしません。(代わりにファイルを作成します../obj/a.o。)

そのため、makeは常にそのレシピを実行します。なぜなら、../obj/aそのファイル名は依存関係としてリストされているため、ファイルを作成する必要があるからです。$(EXE): $(OBJ)

関連情報