【Makefile 专家之路 | 基础篇】03. 规矩方圆:书写规则详解(通配符、文件搜索与伪目标)

文章目录

  • [一、 通配符:批量处理的艺术](#一、 通配符:批量处理的艺术)
  • [二、 文件搜索:VPATH 与 vpath](#二、 文件搜索:VPATH 与 vpath)
  • [三、 伪目标(.PHONY):绝对的"安卓必修课"](#三、 伪目标(.PHONY):绝对的“安卓必修课”)
  • [四、 多目标与多规则](#四、 多目标与多规则)
  • [五、 💡 安卓工程师的记忆卡片](#五、 💡 安卓工程师的记忆卡片)

一、 通配符:批量处理的艺术

在 Makefile 中,如果你想表示"所有的 .c 文件",你会用到通配符。

  1. *(星号) :与 Shell 里的用法一致。
    • 例子:rm -f *.o 表示删除所有以 .o 结尾的文件。
    • 陷阱: 如果你在变量定义中使用 objects = *.o,而此时目录下还没有生成任何 .o,那么 objects 的值就是字符串 *.o,而不是文件列表。
  2. % (百分号)这是 Makefile 的精髓 。它用于"匹配"。
    • 它不像 * 那样简单展开,而是在规则中定义"模式"。例如 %.o : %.c 表示"任何一个 .o 目标都依赖于同名的 .c 文件"。

二、 文件搜索:VPATH 与 vpath

在 Android 源码中,头文件和源文件通常分开放(比如 src/ 和 include/)。如果 Makefile 找不到文件,就会报错。

  1. VPATH 变量:这是一个全局搜索路径。
bash 复制代码
VPATH = src:../headers

make 如果在当前目录找不到依赖文件,就会去 src 和 .../headers 目录下挨个找。

  1. vpath 关键字(小写): 更精准的分类搜索。
bash 复制代码
vpath %.h ../headers
vpath %.c src

这告诉 make:所有的 .h 去 .../headers 找,所有的 .c 去 src 找。

三、 伪目标(.PHONY):绝对的"安卓必修课"

这是本章最重要的概念。
场景: 假设你的 Makefile 里有一个 clean 目标,但不巧,你的文件夹里真的有一个文件叫 clean

  • 结果: 当你输入 make clean 时,make 发现 clean 文件已经存在,且没有依赖,它会认为"目标已最新",从而拒绝执行删除命令!

解决方案 : 使用 .PHONY 显式声明。

bash 复制代码
.PHONY: clean
clean:
	rm -rf $(OBJS)
  • 意义: 告诉 make,clean 不是一个真正的"文件",而是一个"动作"。无论目录下有没有同名文件,请务必执行它。

四、 多目标与多规则

  1. 多目标: 一个命令生成多个文件。
  2. 静态模式: 让你能更灵活地指定哪些目标应用哪些规则(我们将在之后的自动化篇深入剖析)。

五、 💡 安卓工程师的记忆卡片

  1. Android 源码中的 .PHONY
    在 AOSP 源码中,你会看到大量的伪目标,比如 make bootimage、make systemimage。这些显然不是为了生成一个叫 bootimage 的单个文件,而是触发一整套复杂的打包脚本。
  2. 目录搜索的工程实践
    虽然 VPATH 很好用,但在极大型项目中(如 Android),过度依赖全局 VPATH 可能会导致链接到错误版本的库。现代 Android 开发更倾向于在 Android.mk 中直接使用 $(LOCAL_PATH) 绝对路径或明确的相对路径。
  3. 续行符 \
    当 vpath 路径太长或者 OBJS 列表太长时,记得在行末使用 \。
    1)\ 后面不能有任何字符(空格和制表符也不能有)
    2)解析时,\ 和换行符被删除,但下一行的前导空白字符(空格和制表符)被保留,一同拼接到第一行的末尾
    3)echo (OBJS) 或 (info $(OBJS)) 输出时,make 本身会将多个空白压缩为一个空格显示(但实际值中仍有多个空白)。

【本篇思考题】

  1. 在 Android 源码中,如果你在当前目录下执行 make clean,结果发现没有任何文件被删除,但目录下确实有 .o 文件。请问最可能的原因是什么?
  2. %.o : %.c 和 *.o : *.c 这两种写法,哪一个是正确的模式匹配规则?
相关推荐
mounter6252 小时前
现代 Linux 内存管理的演进与变革:从传统 LRU 到多代架构 MGLRU
linux·服务器·kernel
赵渝强老师2 小时前
【赵渝强老师】Kubernetes(K8s)中的金丝雀升级
linux·docker·云原生·容器·kubernetes
Qt程序员3 小时前
Linux RCU 原理与应用
linux·c++·内核·linux内核·rcu
The Sheep 20233 小时前
Vue复习
linux·服务器·数据库
兄台の请冷静3 小时前
Linux 安装es
linux·elasticsearch·jenkins
fengyehongWorld3 小时前
Linux rg命令
linux
pride.li4 小时前
海思视觉Hi3516CV610--开机自动设置ip
linux·网络·网络协议·tcp/ip
我叫张小白。4 小时前
CentOS 7 安装 Docker并配置镜像加速(完整指南)
linux·docker·centos
Titan20245 小时前
Linux动静态库
linux·服务器·c++
赵民勇5 小时前
Linux file命令详解
linux·运维