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 대신 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)

관련 정보