避免重复GNU Make规则

时间:2011-08-22 15:43:40

标签: makefile rules targets

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

所以而不是:

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

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

创建没有重复的内容,如:

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

或者这种强制冗余只是GNU Make设计的一个不幸因素吗?

2 个答案:

答案 0 :(得分:3)

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

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

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

$(foreach src,cpp cc,$(eval %.d: %.$(src) ; $$(CPP) -MM $$(CPPFLAGS) $$<))

答案 1 :(得分: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或类似文件)
  • 使用GNU make的$(eval)$(call)函数生成并评估它们

与C / Unix开发工具链中的大多数其他内容一样,这些技术本质上是一种预处理形式,使得它们易于理解且价格难以使用(大量的双重或三重逃逸,很难保持跟踪什么是扩展的时候;调试可能是一种皇家的痛苦,至少在我的经验中。)

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