我想构建一些C ++代码。我已经有了一个可以自动计算依赖关系的魔术Makefile,但我想将目标文件保存在不同的目录中。所以结构看起来像:
我能够运行Makefile,使用obj /前缀将源转换为对象,但是当我想要向后移动依赖项计算时,事情变得混乱。
问题是几乎所有的Makefile示例都是一步完成的,从.cpp(%.d: %.cpp
)创建.d。我花了一些时间试图理解Makefile并用试验和错误修复它。最后我有一个工作脚本:
DIRS := a b c
SOURCES := $(foreach dir,$(DIRS),$(wildcard source/$(dir)/*.cpp))
OBJECTS := $(patsubst %.cpp,obj/%.o,$(SOURCES))
obj/%.d: %.cpp
@mkdir -p $(@D)
@$(CXX) -E $(CXXFLAGS) -MM -MP -MF $@ -MQ $(@:.d=.o) -MQ $@ $<
obj/%.o: %.cpp obj/%.d
@$(CXX) $(CXXFLAGS) -o $@ -c $<
project: $(OBJECTS)
...
-include $(OBJECTS:.o=.d)
但我仍然不确定为什么我需要为cpp-&gt; d和cpp&amp; d - &gt;分别设置步骤。 o(或者我理解 - 但后来我不知道为什么大多数例子都不需要这个)。
答案 0 :(得分:2)
假设源文件为foo.cpp
和bar.cpp
,标头为foo.h
和bar.h
,以使foo.cpp
包括foo.h
和bar.h
,bar.cpp
包含bar.h
。
你可以拥有一个根本不涉及依赖文件的简单makefile:
project: $(OBJECTS)
...
%.o: %.cpp
...
现在,如果您修改foo.cpp
,则Make会重建foo.o
(以及project
)。如果您修改bar.cpp
,则会重建bar.o
(以及project
)。如果修改标题,Make将不执行任何操作,因为Make不知道对象以任何方式依赖于标题。
您可以为依赖项文件添加规则:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d:
...
-include *.d
现在Make将构建并使用依赖文件 - 如果你记得要告诉它。如果您这样做,Make会知道当您修改foo.h
时,它必须重建foo.o
,当您修改bar.h
时,它必须重建foo.o
和bar.o
。
记住重建依赖文件很痛苦。让Make做它会更好。何时必须重建foo.d
?好吧,当foo.cpp
被修改时,肯定是:
project: $(OBJECTS)
...
%.o: %.cpp
...
%.d: %.cpp
...
-include *.d
但是,foo.d
(即foo.o
或foo.h
)的任何其他先决条件都已修改后,还必须重建bar.h
。我没有详细说明规则中的命令(我对%.d
规则中的命令没有多大意义),但是一个简单的规则将构建一个如下所示的foo.d
:
foo.o: foo.cpp foo.h bar.h
可以编写一个产生foo.d
的命令,如下所示:
foo.o: foo.cpp foo.h bar.h
foo.d: foo.cpp foo.h bar.h
有更复杂的方法,但今天就足够了。
至于为什么许多示例makefile共享某个次优特征,这是因为人们在没有严格检查或理解每个特征的情况下复制彼此的makefile。