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

make如何解析Makefile中百分比匹配模式规则与显式规则

Makefile显式规则与模式规则的解析逻辑

核心规则前提

首先澄清两个常见认知误区:

  • 模式规则(%开头的规则)不等于预先生成所有匹配目标的显式规则:模式规则是Make的「后备候选规则」,仅当目标没有显式定义的构建命令时,才会被检索匹配
  • 同目标的多规则处理逻辑分两类:
    • 仅声明依赖、没有构建命令的显式规则:只会给目标追加依赖,不会覆盖已有构建命令
    • 带构建命令的显式规则:后定义的规则会覆盖前序同目标的构建命令
    • 模式规则的优先级永远低于显式规则:只要目标有显式定义的构建命令,就不会匹配任何模式规则

测试用例解析

针对你给出的测试Makefile:

foo : bar

bar :
    #bar

% : %.c
    #%

两种场景的执行逻辑如下:

场景1:目录下仅存在bar.c/无任何.c文件

Make默认取第一个目标foo作为最终构建目标:

  1. foo的规则仅声明依赖bar,没有定义构建命令
  2. 依赖bar存在带构建命令的显式规则,Make直接执行该规则的命令输出#bar
  3. 因bar已有显式构建命令,Make不会检索匹配通配模式规则,因此不会触发#%的输出

场景2:目录下仅存在foo、foo.c、Makefile

  1. 最终目标foo仅声明依赖bar,无显式构建命令
  2. 先构建依赖bar,执行显式规则输出#bar
  3. 回到foo的构建逻辑:因无显式构建命令,Make检索匹配到% : %.c模式规则,且依赖foo.c存在,因此执行模式规则的命令输出#%

头文件自动依赖原理解析

你提到的自动依赖写法的核心逻辑恰好匹配上述规则:

a.out: main.o
    g++ main.o

%.o: %.cpp
    g++ $< -c

main.o: main.cpp foo.h # *.d文件生成的仅依赖规则
  1. main.o的构建命令由%.o: %.cpp模式规则提供
  2. 后续main.o: main.cpp foo.h是仅声明依赖、无构建命令的显式规则,只会给main.o追加foo.h作为依赖,不会覆盖已有构建命令
  3. 最终等效于合并后的规则,实现修改头文件也会触发对应源文件重编译的效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:45:04