通过两步依赖计算了解Makefile

时间:2012-11-24 05:22:42

标签: makefile build-automation gnu gnu-make building

我想构建一些C ++代码。我已经有了一个可以自动计算依赖关系的魔术Makefile,但我想将目标文件保存在不同的目录中。所以结构看起来像:

  • 生成文件
  • 源/一个/
  • 源/ B /
  • 源/ C /
  • OBJ /

我能够运行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(或者我理解 - 但后来我不知道为什么大多数例子都不需要这个)。

1 个答案:

答案 0 :(得分:2)

假设源文件为foo.cppbar.cpp,标头为foo.hbar.h,以使foo.cpp包括foo.hbar.hbar.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.obar.o

记住重建依赖文件很痛苦。让Make做它会更好。何时必须重建foo.d?好吧,当foo.cpp被修改时,肯定是:

project: $(OBJECTS)
    ...

%.o: %.cpp
    ...

%.d: %.cpp
    ...

-include *.d

但是,foo.d(即foo.ofoo.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。