标头中的更改未导致使用makefile重新编译

时间:2016-09-16 17:39:19

标签: c++ makefile

修改

写完这篇文章之后,我注意到了一些事情,然后回过头去了。我换了一行:

$(CXX) -MT $(BUILD_DIR)/$(@:.d=.o) -MM $(CXXFLAGS) $^ > $@

以下内容:

$(CXX) -MM $(CXXFLAGS) $^ > $@

由于首先获取生成的依赖项文件似乎有点多余,因此将它们命名为.o文件,然后将它们转换回.d文件。

现在目标实际上已经生成,但是当更改头文件时它仍然不会重新生成。

原始

我将这个makefile作为课程的一部分创建,在运行make时,一切正常,为主机和目标构建。当头文件发生更改时会出现问题(例如:part1.h),此实现专门用于考虑这一点,并且它似乎有效。

现在几个星期,我终于意识到它没有按预期工作,因为在更改任何头文件后它不会重新编译。 (part1.h或part2.h)。

我查看了目标生成的依赖项文件:

$(BUILD_DIR)/%.d: %.cpp

part1.d的示例包含以下内容:

build/host/build/host/part1.o: part1.cpp part1.h

对我来说,双目录列表是一个错误,但我尝试更改该行:

$(CXX) -MT $(BUILD_DIR)/$(@:.d=.o) -MM $(CXXFLAGS) $^ > $@

对于以下内容,删除BUILD_DIR变量:

$(CXX) -MT $(@:.d=.o) -MM $(CXXFLAGS) $^ > $@

这样做解决了双目录列表问题,但是给了我一个链接器错误:

build / host / main.o:文件无法识别:无法识别文件格式

我试图找到一些解决方案,这将确保在对头文件进行更改时重新编译程序。

我试图弄清楚我错过了什么,我看了相关的文献,一切似乎都匹配。

SOURCES=main.cpp part1.cpp part2.cpp
OBJECTS=$(addprefix $(BUILD_DIR)/,$(SOURCES:.cpp=.o))
DEPS=$(addprefix $(BUILD_DIR)/,$(SOURCES:.cpp=.d))
EXE=prog
CXXFLAGS=-I.

#Make sure that default choice for make is the host
ifndef (${ARCH})
    ARCH=host
endif

#Making for host
ifeq (${ARCH},host)
CXX=g++
BUILD_DIR=build/host
BIN_DIR=bin/host
endif

# Making for target
ifeq (${ARCH},target)
CXX=arm-devkit-g++
BUILD_DIR=build/target
BIN_DIR=bin/target
endif

$(BIN_DIR)/$(EXE): $(DEPS) $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $(OBJECTS)

#Generate dependency files. Place them in build/host or build/target depending on choice
$(BUILD_DIR)/%.d: %.cpp
    $(CXX) -MT $(BUILD_DIR)/$(@:.d=.o) -MM $(CXXFLAGS) $^ > $@

#Generate object files. Place them in build/host or build/target, depending on choice.
$(BUILD_DIR)/%.o: %.cpp
    $(CXX) -o $@ -c $^

#Create the build dir,
${BUILD_DIR}:
    mkdir -p ${BUILD_DIR}

#Create the bin dir
${BIN_DIR}:
    mkdir -p ${BIN_DIR}


.PHONY:clean
clean:
    rm -f $(BUILD_DIR)/*.o $(BIN_DIR)/$(EXE) $(BUILD_DIR)/*.d

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

1 个答案:

答案 0 :(得分:1)

如果在编译过程中生成依赖项,不仅可以避免采取额外步骤,还可以依赖编译器生成正确的路径。这需要对makefile进行一些其他更改,但我发现只重写它更简单,make有许多功能可以简化其他一些操作。

arch ?= host

build_dir := build/$(arch)
bin_dir   := bin/$(arch)

ifeq ($(arch),target)
prefix := arm-devkit-
endif

sources := main.cpp part1.cpp part2.cpp
objects := $(sources:%.cpp=$(build_dir)/%.o)
deps    := $(objects:.o=.d)

target := $(bin_dir)/prog

CXX      := $(prefix)$(CXX)
CPPFLAGS := -MMD -MP

$(target): CC := $(CXX)
$(target): $(objects) | $(bin_dir)
    $(LINK.o) $^ $(LDLIBS) -o $@

$(build_dir)/%.o: %.cpp | $(build_dir)
    $(COMPILE.cpp) $(OUTPUT_OPTION) $<

$(build_dir) $(bin_dir): ; mkdir -p $@

.PHONY: clean
clean: ; $(RM) $(target) $(objects) $(deps)

-include $(deps)