1

I created a makefile based on the GNU Make the tutorial: https://www.gnu.org/savannah-checkouts/gnu/make/manual/html_node/index.html#SEC_Contents.

The make file works fine on initial make, but if a file is changed and make is ran there is a circular dependency dropped message and it does not build the changed file. The dropped dependency is bin/main.o <-bin/main.o. This makes sense as main.o should not depend on main.o. I searched several sites, including stackoverflow and found some useful answers, but I have not been able to resolve my issue. These two links were the most relevant to my issue: Makefile export .o file to a different path than .cpp and Makefile circular dependency error

Based on the above information I edited my makefile and at least now I can debug easier. The dependency issue probably has to do with the subsequent target and prerequisite after wildcard expansion, but I am just not seeing it.

Here is my 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)

Question1: If the wildcard expansion is causing the circular dependency, how could I fix?

Question2: How does one trace wildcard expansion? Would it be correct to echo the names of the files and trace that way? Running make -d was useful, but I am not seeing how to avoid it. My assumption is these lines are causing the circular dependencies:

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

Thank you for your help and insight.

Community
  • 1
  • 1
Program0
  • 37
  • 1
  • 7

1 Answers1

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

On this line you say to build main.o , I need main.cpp *.h and *.o

But *.o has main.o so you write main.o depend of main.o. Just remove $(OBJECTS) you don't need object to build a object.

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

Don't use wildcard, it's better to explicit your sources files. Don't use CC for c++ compiler, the standard use CXX.

exemple of 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)
Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • That fixed it. Thank you so much! So, is it better to explicitly declare sources if possible? What would normally be done if there are a large amount of sources? Could another make file be called to make the other sources? – Program0 Nov 19 '16 at 22:39
  • To include other file you can use `include sources.mk`. And you can use it to regroup all sources of a project [exemple](https://github.com/Stargateur/spider/blob/6e31676a092f7c0477be80cd4043dbfe84ed28b2/server.mk). It's better to explicit sources files because you could add temporary cpp file in your folder or you want keep a source file but not use it to the project. With the wildcard you can't select sources files. Like in a cpp file you don't include every header. In your Makefile you don't add all source file :p – Stargateur Nov 19 '16 at 22:55