5

我一直在编写一个生成一些依赖项的 Makefile,我发现自己不得不复制规则,因为(旧版)代码库包含文件的.cpp混合.cc。好像有点不好看。无论如何要指定目标的先决条件可以是文件.cpp还是.cc文件?

因此,与其拥有:

%.d : %.cpp
    $(CPP) -MM $(CPPFLAGS) $<

%.d : %.cc
    $(CPP) -MM $(CPPFLAGS) $<

创建没有重复的东西,例如:

%.d : %.(cpp | cc)
    $(CPP) -MM $(CPPFLAGS) $<

还是这种强制冗余只是 GNU Make 设计的一个不幸元素?

4

2 回答 2

3

第一个选项,使用一个变量来定义规则体一次,并根据需要重用它:

DEPGEN=$(CPP) -MM $(CPPFLAGS) $<
%.d: %.cpp ; $(DEPGEN)
%.d: %.cc  ; $(DEPGEN)

第二个选项,用于$(eval)动态生成规则:

$(foreach src,cpp cc,$(eval %.d: %.$(src) ; $$(CPP) -MM $$(CPPFLAGS) $$<))
于 2011-08-24T00:52:35.480 回答
1

这应该有效:

%.d :: %.cpp
    $(CPP) -MM $(CPPFLAGS) $<

%.d :: %.cc
    $(CPP) -MM $(CPPFLAGS) $<

另一个想法:

%.d : %.c
    $(CPP) -MM $(CPPFLAGS) $<

%.c : %.cpp
    ln $< $@  # or cp -p

另一个想法是让 GNU make 生成两个模式规则。基本上有两种方法可以做到这一点:

  • 使用 GNU make语句将它们写入%-cc.mk您包含在实际 makefile 中的 makefile(或类似文件) include
  • $(eval)使用 GNU make和$(call)函数内联生成和评估它们

像 C/Unix 开发工具链中的大多数其他东西一样,这些技术本质上是一种预处理形式,使它们易于理解,但代价是非常难以使用(大量的双重或三重转义,很难跟踪什么何时扩展;至少在我的经验中,调试可能是一种皇家痛苦)。

因此,将它们保留用于更复杂的用例(其中 Stack Overflow 列出了一些)。

于 2011-08-22T18:15:29.117 回答