Makefile精读 · M03-03 | 自动变量:`$@` `$<` `$^` `$?` `$*` 与目录变体

发布时间:2026/9/10 20:54:18

Makefile精读 · M03-03 | 自动变量:`$@` `$<` `$^` `$?` `$*` 与目录变体 模块M03 变量体系篇号M03-03 / 41预计阅读4045 分钟主线GNU Make加厚篇★文章目录本篇目标30 秒速览正文1. 自动变量是什么2. 核心五件套2.1 $ — 当前目标2.2 $ — 第一个依赖prerequisite2.3 $^ — 所有依赖去重2.4 $ — 所有依赖保留重复2.5 $? — 「过期相关」的依赖2.6 $* — 茎stem3. 一张表背下来4. 目录与文件名变体5. 和模式规则一起读加厚6. 常见坑6.1 在配方外使用6.2 $ 不是「唯一源文件」而是「第一个依赖」6.3 $^ 包含不想链进的文件6.4 混淆 $? 与 $^6.5 $* 迷信7. 实战对照手写名 vs 自动变量8. 次常用$|、$%扫盲9. 对照表可贴显示器读 Makefile 检查清单练习判断题对 / 错改错题动手题下一篇预告本篇目标吃透规则配方里最常见、却从不需要你赋值的符号自动变量。掌握$$$^$?$*的精确含义以及$(D)/$(F)等目录变体。学完本篇模式规则与链接行终于能读能写不再靠「抄别人 Makefile」蒙混。30 秒速览自动变量只在配方中有意义由 Make 在执行该规则时填入。$当前目标$第一个依赖$^所有依赖去重$?比目标新的依赖$*模式规则的茎。链接常用$(CC) -o $ $^编译常用$(CC) -c $ -o $。目录变体$(D)/$(F)目标的目录/文件名$^亦有$(^D)等少见但要认得。$*在非模式规则里常为空或不靠谱——茎相关逻辑优先信任模式/静态模式。写死文件名能跑但换目标就炸自动变量让一条规则服务一类文件。正文1. 自动变量是什么它们不是你在文件开头:出来的配置而是 Make 在执行某条规则的配方时临时提供的app: main.o util.o gcc -o $ $^执行更新app时自动变量值$app$^main.o util.o$main.o第一个没有自动变量时你得写gcc -o app main.o util.o一换目标名或依赖列表配方就要改——模式规则更是几乎离不开自动变量。作用域记忆自动变量为「当前正在执行的这条规则」服务写在配方外通常无意义值为空或不符合预期。2. 核心五件套2.1$— 当前目标hello: hello.c gcc -o $ hello.cmake hello→-o hello。模式规则里更关键一条配方生成「正在构建的那个文件」。2.2$— 第一个依赖prerequisite%.o: %.c gcc -c $ -o $目标$$main.omain.cmain.o编译规则几乎总是$→ 源文件$→ 目标文件。若依赖写成%.c common.h$仍是第一个即对应的.c不会变成common.h顺序很重要。2.3$^— 所有依赖去重app: main.o util.o main.o gcc -o $ $^$^是main.o util.o重复的main.o去掉。链接行圣经$(CC) -o $ $^2.4$— 所有依赖保留重复与$^类似但不去重。少数工具链对链接顺序/重复库敏感时可能用到。一般优先$^。2.5$?— 「过期相关」的依赖比目标更新的那些依赖目标不存在时通常是全部依赖。适合「只处理变化的输入」lib.a: a.o b.o c.o ar r $ $?含义直觉只把比lib.a新的.o更新进库。日常编译/链接更常用$^读旧库维护规则时会见到$?。2.6$*— 茎stem在模式规则%.o: %.c更新path/foo.o时$*为path/foo。%.o: %.c echo stem$* gcc -c $ -o $显式规则无模式里$*常常为空——不要在普通hello: hello.c上依赖$*。需要茎时用模式/静态模式。3. 一张表背下来对规则build/app: main.o util.o假设正在更新build/app且util.o比build/app新、main.o不新变量典型值口诀$build/app目标全家桶路径$main.o第一个依赖$^main.o util.o所有依赖去重$同$^本例无重复所有依赖保留重复$?util.o比目标新的依赖$*非模式时勿用模式茎编译模式%.o: %.c $(CC) $(CFLAGS) -c $ -o $链接显式app: $(OBJS) $(CC) $(LDFLAGS) -o $ $^ $(LDLIBS)4. 目录与文件名变体目标或依赖带路径时常用「拆目录 / 拆文件名」变量含义若$build/tmp/app$(D)目标的目录部分build/tmp$(F)目标的文件名部分app$(D)/$(F)第一个依赖的目录/文件名同理$(*D)/$(*F)茎的目录/文件名模式规则时经典用途确保输出目录存在build/%.o: src/%.c mkdir -p $(D) $(CC) -c $ -o $也可mkdir -p build但$(D)在多层子目录build/foo/bar.o时更通用。说明若目标无目录app$(D)为.当前目录。还有$(^D)、$(^F)等对「所有依赖」的拆分少见认得即可。老代码可能用$(dir $)/$(notdir $)函数M04达到类似效果。5. 和模式规则一起读加厚bin/%: src/%.c mkdir -p $(D) $(CC) $(CFLAGS) -o $ $make bin/hello时变量值$bin/hello$src/hello.c$*hello$(D)bin静态模式同样适用$(OBJS): build/%.o: src/%.c mkdir -p $(D) $(CC) -c $ -o $阅读口诀先定当前目标 → 填$→ 看规则依赖列表如何展开 → 填$/$^→ 若有%再填$*。6. 常见坑6.1 在配方外使用TARGET : $ # 通常得不到「某个规则的目标」解析阶段没有「当前规则目标」的完整上下文别这么存。6.2$不是「唯一源文件」而是「第一个依赖」%.o: common.h %.c gcc -c $ -o $$是common.h编译会错。应把源文件依赖写在最前%.o: %.c common.h gcc -c $ -o $6.3$^包含不想链进的文件若把头文件或生成脚本误列进依赖$^会把它们丢给链接器。链接依赖应只列.o/库头文件用附加依赖规则挂上M02-02 / M06。6.4 混淆$?与$^$?只含过期依赖完整链接一般需要$^否则可能漏掉未重编的.o它们仍应参与链接。ar r $ $?是库更新的特殊习惯不要照搬到gcc -o $ $?。6.5$*迷信非模式规则里打印$*为空不代表 Make 坏了。需要「去后缀名」时用$(basename $)或模式茎。7. 实战对照手写名 vs 自动变量# 僵硬 app: main.o util.o gcc -o app main.o util.o # 灵活 app: main.o util.o gcc -o $ $^ # 再进一步 OBJS : main.o util.o app: $(OBJS) gcc -o $ $^改OBJS时配方不用动——这就是自动变量的工程价值。8. 次常用$|、$%扫盲变量含义$|order-only 依赖M06-03不参与「是否过期」的时间戳比较$%当目标是archive(member)形式时的成员名现代少手写本篇以五件套 目录变体为主见到$|知道去 M06 即可。9. 对照表可贴显示器$ 目标 $ 首依赖 $^ 全依赖去重 $ 全依赖保留重复 $? 比目标新的依赖 $* 模式茎 $(D) $(F) 目标的目录 / 文件名编译-c $ -o $链接-o $ $^建目录mkdir -p $(D)读 Makefile 检查清单配方里的$$$^能否还原成具体文件名$对应的是否真是「源文件」依赖顺序对不对链接行用的是$^还是误用$?带输出目录时是否用$(D)/mkdir -p$*是否出现在非模式规则中可疑练习判断题对 / 错$表示所有依赖。模式规则%.o: %.c中更新foo.o时$为foo.o$为foo.c。链接命令写成gcc -o $ $?与gcc -o $ $^在任何情况下等价。$(D)在目标为build/a.o时是build。参考答案错。$是第一个依赖全部依赖是$^。对。错。$?只含过期依赖完整链接通常要用$^。对。改错题%.o: headers.h %.c gcc -c $ -o $ app: main.o util.o gcc -o $ $?指出两处问题并改正。参考答案$会变成headers.h应把%.c放在依赖首位。链接应使用$^而不是$?。%.o: %.c headers.h gcc -c $ -o $ app: main.o util.o gcc -o $ $^动手题在模式规则配方第一行加echo $ $ $^ $*, 构建两个.o观察输出。写build/foo.o规则打印$(D)$(F)。打开任意真实项目 Makefile找到一处-o $与一处-c $还原其具体文件。下一篇预告M03-04《目标/模式特定变量、export与环境变量边界》—target: VAR : value、模式特定变量以及 Make 变量如何进到配方里的 shell 环境。学完 M03-04M03 模块收官变量体系闭环。
延伸阅读

更多相关文章

2026/9/10 5:47:00

AI模型调用成本优化:OpenRouter智能路由策略与工程实践

最近在折腾几个 AI 项目时,我发现一个挺有意思的现象:不少团队在模型调用成本上卡住了。不是技术实现不了,而是每次调用都在烧钱,尤其是面对高频、长文本或复杂推理任务时,账单增长速度比代码跑得还快。这时候&#xf…

2026/9/10 20:49:19

无线产品FCC认证全流程解析与优化策略

1. 无线产品FCC认证的核心要求解析FCC(Federal Communications Commission)认证是美国对无线通信设备的强制性准入制度。根据最新统计,2022年有超过37%的中国企业在首次送检时因技术文档不全被退回。认证主要涵盖三个关键部分:射频…

2026/9/10 20:49:19

光伏微电网双下垂控制原理与Simulink建模实践

1. 光伏交直流混合微电网系统概述光伏交直流混合微电网是当前分布式能源领域的重要研究方向,它通过整合交流母线和直流母线,能够高效接纳光伏发电、储能装置以及各类交直流负载。这种架构相比传统交流微电网具有显著优势:直流母线可直接连接光…

2026/9/10 20:49:19

CANN/ge ACL GEMM API迁移示例

ACL GEMM API Migration Sample 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTo…

2026/9/10 20:49:19

微信小程序阅读管理系统实战:从登录态到阅读器全解析

去年帮一个学弟把“基于微信小程序实现微信阅读网站管理系统”这个题目从零做到了答辩通过,前后花了三周。这期间踩了不少坑,也把微信小程序从登录到渲染的整套流程摸了一遍。这个题目看起来简单,其实“阅读网站管理系统”这几个字背后的工作…

2026/9/10 20:49:19

CANN/ge图引擎概念原理

概念原理 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的…

2026/9/10 16:39:38

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/10 12:32:02

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/10 15:19:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/10 15:49:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码