Makefile核心教程(十一) --- 一文吃透 Makefile 隐含规则

2 阅读4分钟

本文系统性拆解 Makefile 隐含规则所有知识点,从概念、分类、内置规则、默认变量、执行流程、禁用方法,一次性讲透,看完就能直接用到实际项目开发中。

Makefile核心教程总览,可查看文章Makefile核心教程总览(最通俗易懂完整版)。基础篇(11 篇)已全部免费发布;后续进阶篇(12 篇)为付费内容,可通过公众号「付费阅读」单篇购买,或加入知识星球一次性解锁全部 + 专属答疑。

鉴于源码篇幅稍长,故所有篇章的完整示例源码均打包上传在知识星球,源码均原创,可下载直接编译运行,注释讲解。结合完整源码阅读文章,理解更透彻。

一、基础概念

1. 什么是隐含规则

隐含规则是 Make 程序内置预设好的一套编译推导规则,不需要开发者手动书写命令和依赖关系,Make 会根据文件后缀、文件名格式,自动识别文件类型并执行对应的编译、汇编、链接动作。

2. 隐含规则的核心作用

  • 省去手写重复编译命令,精简 Makefile 代码量。
  • 自动推导文件依赖关系,无需逐个写依赖。
  • 统一编译规范,适配 C、C++、汇编等多类源码。
  • 小型工程甚至可以零配置,不用写任何规则就能编译。

3. 隐含规则生效前提

  • 工程文件命名遵循标准后缀规范(.c/.cpp/.s/.o 等)。
  • 没有自定义显式规则、模式规则覆盖同名推导逻辑。
  • 不主动禁用后缀规则和内置隐含规则。

4. 隐含规则 vs 显式规则区别

显式规则:开发者手动写目标、依赖、执行命令,优先级最高。 隐含规则:Make 内置自动推导,无显式规则时才会触发。

示例 demo1:

# 1. 显式规则(手写所有命令)
main: main.o
	$(CC) main.o -o main
main.o: main.c
	$(CC) $(CFLAGS) -c main.c -o main.o

# 2. 隐含规则(极简写法,自动编译)
main: main.o

二、隐含规则两大核心分类

1. 传统后缀隐含规则(了解即可)

这是老式 Make 规则写法,依靠文件后缀映射实现编译推导。

核心关键字:.SUFFIXES 后缀列表。

默认内置后缀:.c .cpp .cc .h .o .s .asm等。

原理:通过后缀1后缀2的格式,定义从一种文件编译成另一种文件的规则。例如.c.o 表示 .c 生成 .o

特点:写法老旧、灵活性差、无通配能力,现代工程已完全被模式规则(%.o:%.c)替代。

内置规则:

# 老式后缀规则(了解即可,实际开发中不推荐)
.SUFFIXES: .c .o
.c.o:
	gcc -c $< -o $@

2. 新式模式隐含规则(重点必学)

采用%通配符匹配,是现在主流的隐含规则形式,兼容性强、可读性高。

基础语法:%.o : %.c

%作用:匹配任意文件名前缀,实现批量文件统一规则。

内置规则:

# 系统自带的模式规则,你不用写,直接能用
%.o : %.c
	$(CC) $(CFLAGS) -c $< -o $@

关于模式规则的详细内容,可查看该核心教程文章 Makefile核心教程(七) --- 一文吃透 Makefile 模式规则

三、系统内置高频隐含规则

1、C 语言编译规则:.c → .o 自动把 C 语言源码文件编译生成目标文件,无需手写 gcc 编译命令。

内置模式规则:

%.o : %.c

自动执行:

$(CC) $(CFLAGS) -c $< -o $@

无需手写命令。详见示例 demo2。

2、C++ 编译规则:.cpp/.cc/.cxx → .o 识别多种 C++ 后缀文件,自动调用 C++ 编译器生成.o 目标文件。

内置模式规则:

%.o : %.cpp
%.o : %.cc
%.o : %.cxx

自动调用:

$(CXX) $(CXXFLAGS) -c $< -o $@

详见示例demo3。

3、汇编编译规则:.s/.asm → .o 自动汇编处理汇编源码,生成目标文件,适配底层驱动、汇编开发场景。

内置规则:

%.o : %.s

自动执行汇编命令。详见demo4。

4、目标文件链接规则:.o → 可执行文件

单个.o 目标文件自动链接,生成无后缀的可执行程序,不用手动写链接命令。 多 个.o目标文件不会自动链接,生成无后缀的可执行程序,不触发隐含链接规则,需要手动写链接命令。

内置规则:

% : %.o

自动把 .o 链接成可执行文件,无需写链接命令。详见示例 demo5。

5、单源码直接生成可执行文件:.c / .cpp 只需 main.c,Makefile 啥都不用写,空着也行。

直接执行:

make main

原理:Make 内置隐含规则:% : %.c。自动一步完成:编译 + 链接,直接生成可执行文件 main。

详见示例demo6。

四、隐含规则内置默认变量

隐含规则能自动生效,全靠一套默认 内置自动变量 + 内置宏变量 工作。内置自动变量详看 Makefile核心教程(三) --- 一文讲透Makefile 变量 一文。常用内置宏变量如下:

  1. 编译器相关变量 CC:默认 C 语言编译器,一般默认为 gcc。 CXX:默认 C++ 编译器,一般默认为 g++。 AS:默认汇编编译器。

  2. 编译参数相关变量 CFLAGS:C 语言编译选项(宏定义、优化等级、警告参数)。 CXXFLAGS:C++ 专属编译选项。 ASFLAGS:汇编编译选项。

  3. 链接相关变量 LDFLAGS:链接库路径参数。 LDLIBS:需要链接的库文件(如 -lpthread -lm)。

  4. 自定义覆盖方式 可在 Makefile 中直接重新赋值内置变量,就能修改隐含规则的默认编译行为,不用改写规则本身。

五、隐含规则执行流程与匹配优先级

  1. Make 规则查找顺序 优先匹配开发者手写的显式规则,其次匹配自定义模式规则,最后才触发系统内置隐含规则。

  2. 多规则冲突优先级 显式规则 > 自定义模式规则 > 系统隐含规则

六、工程级别示例源码

demo7:隐含规则示例(c/c++混合编译)

demo7
├── add.c
├── main.c
├── Makefile
└── utils.cpp

详见示例 demo7。

七、写在最后

公众号发送消息 星球,获取加入知识星球方式。