Makefile kompiliert unveränderte Dateien

Makefile kompiliert unveränderte Dateien

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/**.oDatei 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.cppdie die Variable OBJenthä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)

verwandte Informationen