Fiz um esforço para obter os arquivos de objeto em outro diretório, mas esse diretório refletiria a árvore de diretórios de origem. Fiz isso funcionar, mas falta uma peça na $(OBJ):
linha (certo?), então, quer você altere a fonte ou não, ele recompila. Dar uma olhada.
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)
Editar
Isso funciona conforme o esperado: não recompila. Além disso, é muito mais fácil de ler sem sufixos complicados. Veja respostas e comentários abaixo.
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)
Responder1
Existem vários problemas:
Primeiro, sua variável OBJ não se refere a uma lista de arquivos criados. Por exemplo, quando você tem arquivos fonte src/a.cpp e src/b.cpp, OBJ conterá obj/a e obj/b. Então use OBJ_O em vez de OBJ.
Segundo, seu objetivo para construir os arquivos OBJ não fornece dependências entre os arquivos .cpp e .o. É um problema você escrever sua regra para criar os arquivos .o dessa maneira, porque você não pode fornecer informações de dependência nessa linha. Eu reescreveria completamente essa regra para a criação de arquivos .o:
../obj/%.o: ../src/%.cpp
$(CC) $(CFLAGS) $(INCL) -o "$@" "$<"
Isso cria cada arquivo .o separadamente e cada arquivo .o depende do arquivo .cpp correspondente.
Esta é uma regra para criar um ../obj/**.o
arquivo a partir de cada arquivo que corresponda a ../src/**.cpp
.
Responder2
Para deixar mais claro:
O principal problema é justamente a linha$(OBJ):
O problema é que se houver um arquivo fonte ../src/a.cpp
a variável OBJ
contém ../obj/a
e a regra $(OBJ):
significa "use a seguinte receita para construir o arquivo ../obj/a
". Mas não é isso que a receita faz! (Em vez disso, ele cria um arquivo ../obj/a.o
.)
É por isso que o make sempre executará essa receita porque está desesperado para criar o arquivo, ../obj/a
pois o nome do arquivo está listado como uma dependência em$(EXE): $(OBJ)