我不确定我在这里做错了什么。我试图让 make 弄清楚我的项目有哪些依赖项,不仅是源文件,还有非系统包含的头文件。我在这个网站上有很多与这个主题相关的资源。
如:Makefile header dependencies和 Makefile, header dependencies
但是,当我这样做时
touch MyHeader.h
作为测试是否有效,我的 make 过程无法重建包含此 header 的源文件。所以,这就是我的 makefile 中的内容(相关)
CPP=g++
CPPFLAGS=-Iadditional/includes -MMD
CXXFLAGS=-std=c++0x -c
# not every source file in this directory needs to be included in this build
# this is because of shared code with Windows
SOURCESFILTER = File1.cpp File2.cpp
OBJ_DIR=obj
SOURCES = $(filter-out $(SOURCEFILTER),$(wildcard *.cpp))
OBJECTS = $(addprefix $(OBJ_DIR)/,$(SOURCES:.cpp=.o))
DEPENDENCIES = $(OBJECTS:.o=.d)
.PHONY: archive
archive : $(OBJECTS)
ar mylib.a obj/*.o
-include $(DEPENDENCIES)
$(OBJ_DIR)/%.o: $(SOURCES) $(DEPENDENCIES)
$(CPP) $(CPPFLAGS) $(CXXFLAGS) $< -o $@
我已经验证上述过程确实生成了预期的 *.d 文件。我认为我正确地包含了它们。然而,正如前面提到的,作为一个测试,我做了: 触摸 MyHeader.h
与源文件位于同一目录中,然后重新运行 make,包含此 header 的源文件都不会被重新制作。我错过了什么?
安迪
最佳答案
首先,您不能在后缀规则中包含先决条件。即使可以,您也肯定不会想要包含 $(SOURCES)
或 $(DEPENDENCIES)
,因为这会导致 每当任何源文件或依赖文件发生更改时,都会重建每个对象。
其次,您不能在与 make 期望的目录不同的目录中创建目标文件。 Make 会将要查找目标的位置放入变量 $@
中,并且您必须将输出准确地写入该位置。如果您看到修改目标的规则(例如上面使用 obj/$@ 的规则),则该规则将不起作用。
很可能 GCC 将文件写入 obj/foo.d
,但您的 include
试图包含 foo.d
但那不存在...但由于您使用了 -include
make 不会提示。
我建议您首先将对象文件写入本地目录并使其与依赖项一起使用。一旦成功,请阅读如何将目标写入不同的目录和/或再次询问。
预计到达时间:
尝试这样的事情:
CXX := g++
CPPFLAGS := -Iadditional/includes -MMD
CXXFLAGS := -std=c++0x
# not every source file in this directory needs to be included in this build
# this is because of shared code with Windows
SOURCESFILTER := File1.cpp File2.cpp
OBJ_DIR := obj
SOURCES := $(filter-out $(SOURCEFILTER),$(wildcard *.cpp))
OBJECTS := $(addprefix $(OBJ_DIR)/,$(SOURCES:.cpp=.o))
DEPENDENCIES := $(OBJECTS:.o=.d)
.PHONY: archive
archive: mylib.a
mylib.a: $(OBJECTS)
$(AR) $@ $^
-include $(DEPENDENCIES)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
关于makefile - 为什么 make 不检测 header 依赖项的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16221805/