Предпринял попытку получить объектные файлы в другом каталоге, но этот каталог в противном случае отражал бы исходное дерево каталогов. Получилось, но в строке отсутствует часть $(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_O вместо OBJ.
Во-вторых, ваша цель для построения 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)