写完这篇文章之后,我注意到了一些事情,然后回过头去了。我换了一行:
$(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
答案 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)