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_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)

Связанный контент