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”。但這不是recipie所做的! (相反,它創建一個文件../obj/a.o。)

這就是為什麼 make 將始終執行該 recipie,因為它迫切需要創建該文件,../obj/a因為該文件名被列為依賴項$(EXE): $(OBJ)

相關內容