避免重复GNU Make规则

5

我正在编写一个Makefile,执行一些依赖项生成,但是因为现有代码库包含混合的.cpp.cc文件,所以我不得不复制规则。这似乎有点不美观。是否有办法指定目标的先决条件可以是.cpp.cc文件?

因此,不需要像这样重复:

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

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

创建不带重复的内容,例如:

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

这种强制冗余是GNU Make设计中不幸的元素吗?

如果您使用GNU Autotools,可能可以使用m4宏。 - Kevin
2个回答

3

第一种选择,使用变量一次定义规则主体,并根据需要重复使用:

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

第二种选择,使用$(eval)来动态生成规则:
$(foreach src,cpp cc,$(eval %.d: %.$(src) ; $$(CPP) -MM $$(CPPFLAGS) $$<))

1

这应该可以工作:

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

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

另一个想法:

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

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

另一个想法是让GNU make生成这两个模式规则。基本上有两种方法可以做到这一点:
  • 将它们写入makefile(%-cc.mk或类似的文件),然后使用GNU make的include语句在实际的makefile中包含它们。
  • 使用GNU make的$(eval)$(call)函数来生成和评估它们。

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

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


这两个选项似乎都不能导致更简洁的makefile。我可能会坚持使用原始形式。谢谢你的建议。 - Alastair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接