Habe versucht, die Objektdateien in ein anderes Verzeichnis zu verschieben, aber dieses Verzeichnis würde sonst den Quellverzeichnisbaum widerspiegeln. Das hat geklappt, aber in der $(OBJ):
Zeile fehlt ein Teil (richtig?), sodass es neu kompiliert wird, egal ob Sie die Quelle ändern oder nicht. Sehen Sie es sich an.
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)
Bearbeiten
Das funktioniert wie vorgesehen: Es wird nicht neu kompiliert. Außerdem ist es ohne die komplizierten Suffixe hin und her viel einfacher zu lesen. Siehe Antworten und Kommentare unten.
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)
Antwort1
Es gibt mehrere Probleme:
Erstens bezieht sich Ihre OBJ-Variable nicht auf eine Liste der erstellten Dateien. Wenn Sie beispielsweise die Quelldateien src/a.cpp und src/b.cpp haben, enthält OBJ obj/a und obj/b. Verwenden Sie also OBJ_O statt OBJ.
Zweitens gibt Ihr Ziel zum Erstellen der OBJ-Dateien keine Abhängigkeiten zwischen den .cpp- und .o-Dateien an. Es ist ein Problem, dass Sie Ihre Regel zum Erstellen der .o-Dateien auf diese Weise schreiben, da Sie in dieser Zeile keine Abhängigkeitsinformationen angeben können. Ich würde diese Regel zum Erstellen von .o-Dateien komplett neu schreiben:
../obj/%.o: ../src/%.cpp
$(CC) $(CFLAGS) $(INCL) -o "$@" "$<"
Dadurch wird jede O-Datei separat erstellt und jede O-Datei hängt von der entsprechenden CPP-Datei ab.
Dies ist eine Regel zum Erstellen einer ../obj/**.o
Datei aus jeder Datei, die übereinstimmt ../src/**.cpp
.
Antwort2
Um es klarer zu machen:
Das Hauptproblem ist genau die Linie$(OBJ):
Das Problem besteht darin, dass, wenn es eine Quelldatei gibt, ../src/a.cpp
die die Variable OBJ
enthält ../obj/a
, die Regel $(OBJ):
bedeutet: „Verwende das folgende Rezept, um die Datei zu erstellen ../obj/a
.“ Aber das ist nicht, was das Rezept tut! (Stattdessen erstellt es eine Datei ../obj/a.o
.)
Deshalb wird make dieses Rezept immer ausführen, da es unbedingt die Datei erstellen möchte ../obj/a
, da dieser Dateiname als Abhängigkeit aufgeführt ist in$(EXE): $(OBJ)