0

我在目录中有几个 cpp 和 hpp 文件./src。我将所有 cpp 文件编译到一个二进制文件中,比如./bin/run. 我只想在需要时重新编译,即它或它的标题之一已更改。

我可能可以创建 Makefile,当且仅当文件被更改时才会重新编译文件,但这很不舒服,因为我的大部分代码都在标题中。(它不会改变,因为产品本身就是标头,而 cpp 文件是测试)。

我想将临时.o文件存储在./build

我知道g++ -MM功能,但我不确定如何使用它。

我很高兴看到使用不必要make但任何其他可能的系统的解决方案,如果它们足够简单的话。

UPD 我会试着澄清一下,问题是什么:

可能会创建新的 cpp,可能会添加或删除包含,等等。我不想每次都编辑我的 makefile。

4

4 回答 4

2

为了解决我提到的问题(-include不是一个好的解决方案),我使用这样的东西:

build/%.o: %.cpp
    @$(CC) -MD -c -Wall -o $@ $<
    @cp build/$*.d build/$*.P
    @sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
         -e '/^$$/ d' -e 's/$$/ :/' < build/$*.P >> build/$*.d
    @rm build/$*.P

-include build/*.d

不需要 `%.d 规则。

编辑:

@JackKelly 有 [ *cough*, *choke* ] 向我展示了一种更好的方法来有效地获取相同的依赖文件:

build/%.o: %.cpp
    @$(CC) -MD -c -Wall -o $@ $<
    @$(CC) -MM -MP -Wall -o $*.d $<

-include build/*.d

是的,你可以对同一个目标有多个规则,只要其中一个有命令即可;先决条件积累。我们的想法是获取这样的文件:

file.o: file.cpp headerfile.h
headerfile.h:

第二行 ( headerfile.h:) 是headerfile.h没有先决条件或命令的规则。它什么也不做,但它是一个规则,所以如果headerfile.h缺少,Make 会很满意。

于 2012-10-12T22:56:33.157 回答
1

解决方案的概要如下:

  • 为每个源文件使用辅助依赖文件(即 create foo.depfor foo.cbar.depforbar.c等)
  • 用于gcc -MM创建依赖文件
  • 为了强制make自动执行此操作,请将andfoo.c用作先决条件;这需要一些小的魔法输出foo.depfoo.osedgcc -MM
  • 在主 makefile 中包含所有依赖文件;这是使这种方法成为可能的关键步骤。

最后一步写成如下:

-include $(dependency_files)

这是非常棘手但可能的;有关更多信息,请参阅GNU make 手册

于 2012-10-12T20:18:38.070 回答
1

你提到g++ -MM,它可以做你想做的事情:

include $(ALLOBJ:%.o=%.d)

%.d: %.cxx
    @echo making dependencies for $<
    @g++ -MM -MP $(CXXFLAGS) $< -o $@
    @sed -i 's,$*\.o,& $@ ,g' $@

.d基本上,这定义了从文件创建文件的规则.cxx.d反过来,该include语句需要这些.o文件,该语句要求ALLOBJ.

依赖规则的最后一行是“sed 魔法”,它使依赖文件自己重新生成。如果您认为正则表达式充其量只是 hack,而且通常是邪恶的,那么您可以使用-MTflag

于 2012-10-12T20:20:20.757 回答
0

您可以使用 Make 执行此操作,您只需在规则的敏感度列表中指定标题。例如

myfile.o: myfile.cpp
    gcc -c myfile.o myfile.cpp ${LDFLAGS}    # This is optional. make can infer this line.

变成

myfile.o: myfile.cpp myfile.h
    gcc -c myfile.o myfile.cpp ${LDFLAGS}    # Again, optional.

现在,无论何时myfile.h发生变化,myfile.cpp都会重建。更多的标头可以以类似的方式链接起来。

于 2012-10-12T20:05:01.130 回答