避免重复 GNU Make 规则

发布于 2024-11-30 23:24:41 字数 443 浏览 5 评论 0原文

我一直在编写一个执行一些依赖项生成的 Makefile,我发现自己必须重复规则,因为(遗留)代码库包含 .cpp.cc 文件。好像有点难看。无论如何,是否可以指定目标的先决条件可以是 .cpp.cc 文件?

因此,而不是:

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

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

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

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

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

I've been writing a Makefile that performs some dependency generation and I've found myself having to duplicate rules because the (legacy) codebase contains a mixture of .cpp and .cc files. It seems a bit unsightly. Is there anyway to specify that the prerequisites of a target can be either .cpp or .cc files?

So rather than having:

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

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

Create something without the duplication like:

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

Or is this enforced redundancy just an unfortunate element of GNU Make's design?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

维持三分热 2024-12-07 23:24:41

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

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

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

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

First option, use a variable to define the rule body once, and reuse it as needed:

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

Second option, use $(eval) to dynamically generate the rules:

$(foreach src,cpp cc,$(eval %.d: %.$(src) ; $(CPP) -MM $(CPPFLAGS) $<))
近箐 2024-12-07 23:24:41

这应该可行:

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

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

另一个想法:

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

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

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

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

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

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

This should work:

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

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

Another idea:

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

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

Another idea is to make GNU make generate the two pattern rules.
There are essentally two ways of doing this:

  • write them to makefiles (%-cc.mk or similar) that you include within your actual makefile with GNU make's include statement
  • generate and evaluate them inline with GNU make's $(eval) and $(call) functions

Like most everything else in the C/Unix development toolchain, these techniques are essentially a form of preprocessing, making them easy to understand at the price of being really hard to use (lots of double or triple escaping, really hard to keep track of what is expanded when; debugging can be a royal pain, at least in my experience).

So reserve them for more complicated use cases (of which Stack Overflow lists a few).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文