【问题标题】:Make: circular dependency dropped c++Make: 循环依赖被丢弃 c++
【发布时间】:2016-11-19 21:02:28
【问题描述】:

我根据 GNU Make 教程创建了一个 makefile:https://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/index.html#SEC_Contents

make 文件在初始 make 时工作正常,但如果文件被更改并运行 make,则会出现循环依赖删除消息,并且它不会构建更改的文件。删除的依赖项是 bin/main.o Makefile export .o file to a different path than .cpp 和 Makefile circular dependency error

根据以上信息,我编辑了我的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 $@ -c $< $(CC_FLAGS)

$(BIN_DIR)/main.o:$(SRC_DIR)/main.cpp $(OBJECTS) $(H_FILES)
    $(CC) -I$(H_DIR) -o $@ -c $(SRC_DIR)/main.cpp $(CC_FLAGS)

rshell: $(OBJECTS)
    $(CC) -o $(BIN_DIR)/$@ $(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 $@ -c $(SRC_DIR)/main.cpp $(CC_FLAGS)

感谢您的帮助和洞察力。

【问题讨论】:

    标签: c++ makefile gnu-make circular-dependency wildcard-expansion


    【解决方案1】:
    $(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)
    

    不要使用通配符,最好明确你的源文件。 c++编译器不要使用CC,标准使用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)
    

    【讨论】:

    • 修复了它。非常感谢!那么,如果可能的话,明确声明来源会更好吗?如果有大量来源,通常会怎么做?是否可以调用另一个 make 文件来制作其他来源?
    • 要包含其他文件,您可以使用include sources.mk。您可以使用它重新组合项目exemple 的所有源。最好使用显式源文件,因为您可以在文件夹中添加临时 cpp 文件,或者您希望保留源文件但不将其用于项目。使用通配符,您不能选择源文件。就像在 cpp 文件中一样,您不会包含每个标题。在您的 Makefile 中,您不会添加所有源文件:p
    猜你喜欢
    • 2014-09-14
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 2013-02-04
    • 2019-04-03
    • 2011-04-30
    相关资源
    最近更新 更多