简体   繁体   中英

Make and Re-Compiling Headers with Sub-Directories

There are a few different questions already related to what I'm trying to do, such as this , this , and this . However, I've looked at what is there and what they link to and I'm still not able to get it to work.

I have the following make file (I had some help with this here ). It builds .os in a build directory from .cpps in a source directory. I want to adjust this so that if the headers are updated, then it properly re-compiles those so I don't have to make clean the whole thing (most particularly the ones from the INC_DIR1 folder).

CC = g++
CFLAGS = -g -Wall

INC_DIR1 = include
INC_DIR2 = C:/CPPFiles/CPP_Extra_Libraries/armadillo-4.200.0/include
INC_DIR = $(INC_DIR1) $(INC_DIR2)
INCLUDES = $(foreach d, $(INC_DIR), -I$d)

BUILD_DIR = build
SRC_DIR = test

SRC = $(wildcard */*.cpp)

VPATH = $(SRC_DIR)

OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC:.cpp=.o)))

MAIN = armadillo_extra_functions_test

.PHONY: depend clean

all: $(BUILD_DIR) $(MAIN)
    @echo  compilation complete

$(BUILD_DIR):
    mkdir -p $@

$(BUILD_DIR)/%.o: %.cpp
    $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

$(MAIN): $(OBJS) 
    $(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS)

clean:
    $(RM) *.o *~ $(MAIN) $(BUILD_DIR)/*.o

depend: $(SRC)
    makedepend $(INCLUDES) $^

The latest thing I tried was to remove the depend and makedepend statements and then replace the $(BUILD_DIR/%.o: %.cpp statement with

DEPS = $(patsubst %.o, %.d, $(OBJS))

-include $(DEPS)

$(BUILD_DIR)/%.o: %.cpp
    $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@
    $(CC) -c $(CFLAGS) -MMD  $< > $(DEPS)

Without the last line of these adjustments, the make file runs, though it will not update headers. However, when I add in the last line I get an error about the $(BUILD_DIR)/%.d files not being there.

Basically you need to construct the makefile so that the .cpp files depend on the headers. In this way, changes to the headers will trigger recompilation of the .cpp files. To make this easier, ideally the header dependencies of each .cpp file would be automatically determined.

I recommend using either the GNU autotools approach (great for software you will publish in source form), jam (very simple configuration), or (my current favorite) CMake . All of these essentially automatically generate the makefile from another file (or set of files). They automatically handle the dependency detection and management, too. I would only hand-roll a makefile for self-education or for something with only a handful of source files, or perhaps something weird and complex.

You were almost right with the -MMD flag, but there is no need to complicate things:

INC_DIR1    :=  include
INC_DIR2    :=  C:/CPPFiles/CPP_Extra_Libraries/armadillo-4.200.0/include
INC_DIRS    :=  $(INC_DIR1) $(INC_DIR2)

BUILD_DIR   :=  build
SRC_DIR     :=  test

SRCS        :=  $(wildcard $(SRC_DIR)/*.cpp)
OBJS        :=  $(SRCS:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)
DEPS        :=  $(OBJS:.o=.d)

LDLIBS      :=  # -l flags
LDFLAGS     :=  # -L flags

CPPFLAGS    :=  -MMD -MP $(foreach DIR, $(INC_DIRS), -I $(DIR))
CXXFLAGS    :=  -W -Wall

MAIN        :=  armadillo_extra_functions_test

.PHONY: all clean

all:    $(MAIN)
    @echo "compilation complete"

$(MAIN):    $(OBJS)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

clean:
    $(RM) -r $(MAIN) $(BUILD_DIR)

-include $(DEPS)

$(BUILD_DIR):
    mkdir $@

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp | $(BUILD_DIR)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

Some quick notes :

  • You're using C++. Drop the $(CC) and $(CFLAGS) C variables for their C++ versions: $(CXX) and $(CXXFLAGS) variables.

  • $(CPPFLAGS) is meant for preprocessor flags, such as -MMD , -MP or -I .

  • You need to include the rules GCC created in the dependency files.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM