You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GNU Make含双重后缀文件无法识别模式规则问题咨询

问题描述

我编写了一个仅包含如下模式规则的极简Makefile:

%: %.m4
    m4 $< > $@

使用GNU Make测试时:

  • 执行 touch foo.in.m4 ; make foo.in 可正常运行,生成命令为 m4 foo.in.m4 > foo.in;
  • 但对于带双重后缀的 foo.sh.m4,执行 touch foo.sh.m4; make foo.sh 时提示:*** No rule to make target 'foo.sh'。

类似问题还出现在.f、.c、.o、.tex、.dvi等后缀,但.xml、.doc、.mp3等多数后缀可正常工作。测试脚本如下:

for suff in pdf sh f c o xml doc docx tex dvi mp3 png odt txt in none yxn; do
      touch foo.$suff.m4
      make foo.$suff
done

使用 make -r 可正常运行,推测与默认后缀列表有关,但添加空规则 .SUFFIXES: 后,情况有所改善但仍存在.c和.tex后缀的问题,即存在 bar.c.in 和 bar.tex.in 时,make bar.c 和 make bar.tex 仍提示无规则。

我原以为后缀列表仅与后缀规则相关,与模式规则无关,想请教这一现象的原因。

问题原因解析

你的核心误解在于:GNU Make的.SUFFIXES后缀列表及内置隐含规则,并非仅作用于传统后缀规则,还会直接影响模式规则的匹配优先级与逻辑。具体原因分以下几点:

  1. 内置隐含规则的优先级抢占
    GNU Make默认加载了大量内置隐含规则,针对.c、.sh、.tex这类常见后缀,存在对应的生成规则(比如.c文件可从.i预处理文件生成,.tex可从相关辅助文件生成)。当你执行make foo.sh或make foo.c时,Make会优先尝试匹配这些内置隐含规则,而非你自定义的%: %.m4模式规则。若存在部分依赖文件(比如你提到的bar.c.in),Make会尝试用对应隐含规则生成目标,而非匹配你的.m4规则。

  2. 后缀列表对模式匹配的影响
    .SUFFIXES定义的后缀列表会改变Make对目标文件名的拆分逻辑。对于列表中的后缀,Make会将目标视为「基名+后缀」的组合,优先尝试匹配针对该后缀的规则(包括后缀规则和隐含模式规则),而不是直接将整个目标名匹配到你的%模式中。比如.sh在默认后缀列表里,Make会把foo.sh拆分为基名foo+后缀.sh,然后寻找能生成.sh后缀文件的规则,而非直接匹配%为foo.sh的自定义规则。

  3. make -r与.SUFFIXES:的差异

  • make -r会完全禁用所有内置隐含规则,此时Make只能依赖你定义的规则,因此所有后缀的目标都能正常匹配%: %.m4。
  • 添加空的.SUFFIXES:仅清空了默认后缀列表,但并未禁用所有内置隐含模式规则(比如%.c: %.i、%.tex: %.tex.in这类规则依然存在)。当存在bar.c.in时,Make会匹配这类隐含规则尝试生成bar.c,但因依赖或命令不完整最终报错,而非匹配你的.m4规则。
解决建议

如果想让自定义的%: %.m4规则优先生效,可以采取以下两种方式:

  • 直接使用make -r命令,彻底禁用所有内置隐含规则;
  • 在Makefile中添加.SUFFIXES:清空后缀列表,同时加上MAKEFLAGS += -r来禁用内置隐含规则,确保自定义规则成为唯一选择。

内容的提问来源于stack exchange,提问作者nwcyclist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 06:13:13