玩转Makefile | 四步教你从零开始写Makefile

简介: 玩转Makefile | 四步教你从零开始写Makefile


1. 前言


通过之前章节的学习,我们对Makefile有个基础的认识,现在开始自己动手写Makefile。


目前网络上有不少可以自动生成Makefile的工具,但很多项目其实没必要那么复杂,完全可以自己动手写出来。


而且对于初学者来说,自己动手写一遍Makefile可以顶看十遍高手写的Makefile,也可以加深对Makefile的理解,将来公司的Makefile有需要修改的时候自己就可以动手搞定,不需要依靠他人,何乐而不为?


2. 源代码介绍


在本教程中用于示例的代码很简单,仅仅是在main函数中调用了fun1及fun2函数,而fun1及fun2独立写在fun1.c及fun2.c里。代码如下:


//main.c  
int main()  
{  
    printf("hello world\n");  
    fun1();  
    fun2();  
}  
//fun1.c  
void fun1()  
{  
    printf("this is fun1\n");  
}  
//fun2.c  
void fun2()  
{  
    printf("this is fun2\n");  
}


3. 第一版Makefile


对于我们的示例代码,不通过Makefile编译其实也很简单:


gcc main.c fun1.c fun2.c -o app  


我们知道,Makefile其实就是按规则一条条的执行。所以,我们完全可以把上面那条命令写成Makefile的一个规则。我们的目标是app,按此写法依赖是main.c fun1.c fun2.c,则最终的Makefile如下:


app: main.c fun1.c fun2.c  
    gcc main.c fun1.c fun2.c -o app


但这个版本的Makefile有两个很重要的不足:


  1. 对于简单代码还好,而对于大型项目,具有成千上万代码来说,仅用一行规则是完全不够的,即使够的话也需要写很长的一条规则;


  1. 任何文件只要稍微做了修改就需要整个项目完整的重要编译。


基于此,我们在第一版的基础上优化出第二版。


4. 第二版Makefile


在第二版Makefile中,为了避免改动任何代码就需要重新编译整个项目的问题,我们将主规则的各个依赖替换成各自的中间文件,即main.c --> main.o,fun1.c --> fun1.o,fun2.c --> fun2.o,再对每个中间文件的生成各自写条规则比如对于main.o,规则为:


main.o: main.c  

   gcc -c main.c -o main.o  


这样做的好处是,当有一个文件发生改动时,只需重新编译此文件即可,而无需重新编译整个项目。完整Makefile如下:


app: main.o fun1.o fun2.o  
    gcc main.o fun1.o fun2.o -o app  
main.o: main.c  
    gcc -c main.c -o main.o  
fun1.o: fun1.c  
    gcc -c fun1.c -o fun1.o  
fun2.o: fun2.c  
    gcc -c fun2.c -o fun2.o


第二版Makefile同样具有一些缺陷:


  1. 里面存在一些重复的内容,可以考虑用变量代替;


  1. 后面三条规则非常类似,可以考虑用一条模式规则代替。


基于此,我们在第二版的基础上优化出第三版。


5. 第三版Makefile


在第三版Makefile中,我们使用变量及模式规则使Makefile更加简洁。使用的三个变量如下:


obj = main.o fun1.o fun2.o  

target = app  

CC = gcc  

使用的模式规则为:


%.o: %.c  

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


这条模式规则表示:所有的.o文件都由对应的.c文件生成。在规则里,我们又看到了两个自动变量:$<和$@。其实自动变量有很多,常用的有三个:


       $<:第一个依赖文件;

       $@:目标;

       $^:所有不重复的依赖文件,以空格分开


obj = main.o fun1.o fun2.o  
target = app  
CC = gcc  
$(target): $(obj)  
    $(CC) $(obj) -o $(target)  
%.o: %.c  
    $(CC) -c $< -o $@


第三版Makefile依然存在一些缺陷:


  1. obj对应的文件需要一个个输入,工作量大;
  2. 文件数目比较少时还好,文件数目一旦很多的话,obj将很长;
  3. 而且每增加/删除一个文件,都需要修改Makefile。


基于此,我们在第二版的基础上优化出第四版。


6. 第四版Makefile


在第四版Makefile中,我们隆重推出了两个函数:wildcardpatsubst


wildcard:

扩展通配符,搜索指定文件。在此我们使用src = $(wildcard ./*.c),代表在当前目录下搜索所有的.c文件,并赋值给src。函数执行结束后,src的值为:main.c fun1.c fun2.c。


patsubst:

替换通配符,按指定规则做替换。在此我们使用obj = $(patsubst %.c, %.o, $(src)),代表将src里的每个文件都由.c替换成.o。函数执行结束后,obj的值为main.o fun1.o fun2.o,其实跟第三版Makefile的obj值一模一样,只不过在这里它更智能一些,也更灵活。


除了使用patsubst函数外,我们也可以使用模式规则达到同样的效果,比如:obj = $(src:%.c=%.o),也是代表将src里的每个文件都由.c替换成.o。


几乎每个Makefile里都会有一个伪目标clean,这样我们通过执行make clean命令就是将中间文件如.o文件及目标文件全部删除,留下干净的空间。一般是如下写法:


.PHONY: clean  

clean:  

       rm -rf $(obj) $(target)  

.PHONY代表声明clean是一个伪目标,这样每次执行make clean时,下面的规则都会被执行。


src = $(wildcard ./*.c)  
obj = $(patsubst %.c, %.o, $(src))  
#obj = $(src:%.c=%.o)  
target = app  
CC = gcc  
$(target): $(obj)  
    $(CC) $(obj) -o $(target)  
%.o: %.c  
    $(CC) -c $< -o $@  
.PHONY: clean  
clean:  
    rm -rf $(obj) $(target)


7. 总结


Makefile其实也并不难,但关键的是一定要自己动手写,这样才会更加加深理解,否则也容易造成眼高手低。如果实在不知道从何下手,可以尝试按上面的教程,一步步写下来,也只需要写四个版本而已,写完了相信就有了初步的理解。


附:本教程对应的源码可通过在公众号内回复mk1获取。


在源代码里,总共有四个Makefile文件,可以通过make -f Makefile1来执行不同的Makefile。


目录
相关文章
|
11月前
|
JSON 机器人 API
微信机器人自动回复插件,vx自动回复机器人脚本助手,python框架分享
这个微信机器人系统包含三个主要模块:主程序基于itchat实现微信消息监听和自动回复功能
|
JSON API 数据安全/隐私保护
虾皮(shopee)商品详情接口(虾皮 API 系列)
Shopee 商品详情接口(item_get)用于获取商品的标题、价格、描述、库存和图片等详细信息。开发者需使用 Shopee 提供的 API 密钥进行认证,通过 GET 请求访问指定 URL。请求参数包括 partner_id、shopid、itemid、timestamp 和 sign。签名生成需按字母顺序排序参数,拼接后与 API 密钥进行 HMAC-SHA256 加密。响应为 JSON 格式,包含商品详细信息及错误提示。注意妥善保管 API 密钥,并遵守请求频率限制。
1447 2
|
19天前
|
人工智能 自然语言处理 文字识别
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
Qwen3.7-Max是阿里云百炼面向智能体时代推出的新一代旗舰模型,对标GPT-5.5、Claude Opus 4.7等闭源旗舰。该模型支持百万级token上下文窗口,具备顶级推理能力、多模态搜索与视觉理解增强、流式输出低延迟响应等核心优势,覆盖编程、办公、长周期自主执行等复杂场景。同时支持OpenAI接口兼容,便于系统快速迁移。用户可通过Token Plan团队或节省计划等订阅方式灵活调用,适合企业级高要求场景使用。
6917 30
阿里云百炼Qwen3.7-Max简介:能力、优势、支持订阅计划参考
|
4天前
|
数据采集 人工智能 前端开发
让 Coding Agent 从黑盒到透明:阿里云 Agent 观测审计数据采集实践
AI Agent 规模化落地带来执行黑盒、行为难追溯、成本难度量三大难题。阿里云基于 OTel 标准,面向 Coding Agent、个人通用助理和框架型 Agent,推出 LoongSuite Pilot、插件及探针等无侵入采集方案,让 Agent 实现可看见、可分析、可审计、可治理。
613 138
|
4天前
|
人工智能 弹性计算 运维
阿里云发布堡垒机智能运维Agent,运维交互进入自然语言新时代
支持自然语言运维,提升效率与安全双保障。
1145 0
|
10天前
|
人工智能 安全 定位技术
CodeGraph深度解析 让Claude Code工具调用直降七成的核心原理与实操教程
如今以Claude Code为代表的AI编程智能体已经成为开发者日常编码、项目重构、漏洞修复的必备工具。但在长期使用过程中,几乎所有开发者都会遇到同一个明显痛点:AI虽然具备强大的代码生成与分析能力,却常常陷入盲目探索的循环中。
1185 1
|
13天前
|
存储 定位技术 数据库
CodeGraph 如何让 Claude Code减少 7 成工具调用?
CodeGraph 为 Coding Agent 提供本地代码知识图谱,把函数、类、调用链和框架路由提前整理成“项目地图”,减少盲目搜索和文件读取。它不是新 Agent,而是上下文基础设施,让 Agent 更快找到正确代码路径,平均减少 7 成工具调用。
1285 3
|
11天前
|
人工智能 弹性计算 安全
阿里云618活动时间、活动入口、优惠活动详细解读
2026年阿里云618创新加速季已全面开启,作为年度力度最大的云产品促销活动,本次大促覆盖轻量应用服务器、ECS云服务器、GPU云服务器、数据库、AI算力、安全服务、CDN等全品类产品,推出5亿元算力补贴、新用户限时秒杀、普惠满减、企业专享、免费试用、云大使返佣等多重福利,个人开发者、中小企业、AI团队均可享受专属低价。本文将系统梳理2026年阿里云618活动的完整时间节点、官方参与入口、各类优惠细则、使用规则、热门产品推荐及实操代码,帮助用户精准参与、高效省钱,以最低成本完成上云部署。
995 5