1

我創建了一個基於GNU的makefile製作教程:https://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/index.html#SEC_Contents製作:循環依賴刪除C++

make文件在初始make中工作正常,但是如果文件被更改並且make運行,則會出現循環依賴關係被刪除的消息,並且不會生成已更改的文件。丟棄的依賴項是bin/main.o < -bin/main.o。這是有道理的,因爲main.o不應該依賴main.o.我搜索了幾個網站,包括stackoverflow,並找到了一些有用的答案,但我一直無法解決我的問題。這兩個環節是最相關的,以我的問題: Makefile export .o file to a different path than .cppMakefile circular dependency error

基於我編輯我的makefile和至少現在我可以更容易調試上述信息。依賴問題可能與通配符擴展後的目標和先決條件有關,但我只是沒有看到它。

這裏是我的makefile:

#For compilation 

CC=g++ 
CC_FLAGS= -g -Wall -Werror -ansi -pedantic 

#make[1]: main.o all <- all 

#Folder structure 
BIN_DIR:=bin 
SRC_DIR:=src 
H_DIR:=src/header 

all:rshell 

#VPATH = $(SRC_DIR) 

H_FILES:=$(wildcard $(H_DIR)/*.h) 
DEPS:$(wildcard $(BIN_DIR)/*.d) 


CPP_FILES:=$(wildcard $(SRC_DIR)/*.cpp) 

OBJECTS := $(CPP_FILES:$(SRC_DIR)/%.cpp=$(BIN_DIR)/%.o) 

$(BIN_DIR)/%.o: $(SRC_DIR)/%.cpp $(H_DIR)/%.h 
    mkdir -p $(BIN_DIR) 
    $(CC) -I$(H_DIR) -o [email protected] -c $< $(CC_FLAGS) 

$(BIN_DIR)/main.o:$(SRC_DIR)/main.cpp $(OBJECTS) $(H_FILES) 
    $(CC) -I$(H_DIR) -o [email protected] -c $(SRC_DIR)/main.cpp $(CC_FLAGS) 

rshell: $(OBJECTS) 
    $(CC) -o $(BIN_DIR)/[email protected] $(OBJECTS) $(CC_FLAGS) 

include $(DEPS) 

$(MAKEFILE_LIST): ; 
%:: %,v 
%:: RCS/%,v 
%:: RCS/% 
%:: s.% 
%:: SCCS/s.% 

.PHONY: clean 

clean: 
    rm -rf $(BIN_DIR) 

問題1:如果通配符擴展導致循環依賴,我怎麼能解決?

問題2:如何跟蹤通配符擴展?以這種方式回顯文件的名稱和追蹤是否正確?運行make -d很有用,但我沒有看到如何避免它。我的假設是這些行引起的循環依賴關係:

$(BIN_DIR)/main.o:$(SRC_DIR)/main.cpp $(OBJECTS) $(H_FILES) 
    $(CC) -I$(H_DIR) -o [email protected] -c $(SRC_DIR)/main.cpp $(CC_FLAGS) 

感謝您的幫助和見解。

回答

0
$(BIN_DIR)/main.o:$(SRC_DIR)/main.cpp $(OBJECTS) $(H_FILES) 

在這條線,你說建main.o,我需要的main.cpp的* .h和*的.o

但*的.o有main.o所以你寫main.o的依賴main.o.只要刪除$(OBJECTS)你不需要對象來構建一個對象。

$(BIN_DIR)/main.o:$(SRC_DIR)/main.cpp $(H_FILES) 

不要使用通配符,最好是明確你的源文件。不要將CC用於C++編譯器,標準使用CXX。

爲例的Makefile:

NAME = foo 

CXX  ?= g++ 

RM  = rm 

DEBUG ?= no 

LEVEL ?= 3 

LIB  = -l m 

INCLUDE  = -I include 

CXXFLAGS += -Wall -Wextra -O$(LEVEL) 
CXXFLAGS += -ansi -pedantic -std=c++11 
CXXFLAGS += $(INCLUDE) 

ifeq ($(CXX), clang++) 
CXXFLAGS += -Weverything 
endif 

ifneq ($(DEBUG), no) 
CXXFLAGS += -g 
endif 

LDFLAGS  = $(LIB) 

ifeq ($(DEBUG), no) 
LDFLAGS  += -s 
endif 

SRC  = main.cpp 
SRC  += foo.cpp 

DPD  = $(SRC:.cpp=.dpd) 

OBJ  = $(SRC:.cpp=.o) 

all  : $(NAME) 

$(NAME) : $(OBJ) 
      $(CXX) $(OBJ) -o $(NAME) $(LDFLAGS) 

clean : 
      $(RM) -f $(OBJ) 
      $(RM) -f $(DPD) 

fclean : clean 
      $(RM) -f $(NAME) 

re  : fclean 
      $(MAKE) -C . 

%.dpd : %.cpp 
      $(CXX) -MM $(<) -o $(@) $(CXXFLAGS) -MT $(<:.cpp=.o) 

%.o  : %.cpp 
      $(CXX) -c $(<) -o $(@) $(CXXFLAGS) 

.PHONY  : all clean fclean re %.dpd %.o 

.SUFFIXES : .o.cpp .dpd.cpp 

include $(DPD) 
+0

問題解決了。非常感謝!那麼,如果可能的話,明確聲明來源是否更好?如果有大量來源通常會做什麼?可以調用另一個make文件來創建其他來源? – Program0

+0

要包含其他文件,您可以使用'include sources.mk'。你可以用它來重新組合一個項目的所有來源[例子](https://github.com/Stargateur/spider/blob/6e31676a092f7c0477be80cd4043dbfe84ed28b2/server.mk)。顯式源文件更好,因爲您可以在文件夾中添加臨時cpp文件,或者希望保留源文件但不將其用於項目。通配符不能選擇源文件。就像在cpp文件中一樣,你不包含每個頭文件。在你的Makefile中,你不需要添加所有的源文件:p – Stargateur