다른 디렉터리에 개체 파일을 가져오려고 노력했지만 그렇지 않으면 해당 디렉터리가 소스 디렉터리 트리를 반영하게 됩니다. 제대로 작동했지만 해당 $(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)