소스 디렉터리 트리를 반영하는 다른 디렉터리에서 대상 파일을 얻으려고 노력합니다. 잘 작동하지만 해당 줄에 일부가 누락되어 $(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 대신 OBJ_O를 사용하세요.
둘째, 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
.)
../obj/a
그 파일 이름이 종속성으로 나열되어 있기 때문에 긴급하게 해당 파일을 생성해야 하기 때문에 make가 항상 해당 레시피를 실행하는 이유입니다.$(EXE): $(OBJ)