linux进阶05——Makefile(二)

2023-11-09

1. 源代码

//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");  
}  

2. 第一版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. 对于简单代码还好,而对于大型项目,具有成千上万代码来说,仅用一行规则是完全不够的,即使够的话也需要写很长的一条规则;

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

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

3. 第二版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. 里面存在一些重复的内容,可以考虑用变量代替;

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

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

4. 第三版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。

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

5. 第四版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) 

本文转自公众号【良许Linux】——【玩转Makefile | 四步教你从零开始写Makefile】

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux进阶05——Makefile(二) 的相关文章

随机推荐

  • 俄罗斯方块代码

    package Game1 import java awt Color import java awt Font import java awt Graphics import java awt event ActionEvent impo
  • C语言之实现矩阵(3行3列)的转置(即行列互换)

    例如 输入下面的矩阵 100 200 300 400 500 600 700 800 900 程序输出 100 400 700 200 500 800 300 600 900 代码如下所示 include
  • 数据结构视频教程 -《[猎豹网校]数据结构与算法_C语言》

    整个视频打包下载地址 史上最全的数据结构视频教程系列分享之 猎豹网校 数据结构与算法 C语言 转载请保留出处和链接 更多优秀资源请访问 我是码农 数据结构是信息与计算科学专业中一门重要的专业基础课程 当用计算机来解决实际问题时 就要涉及到数
  • vmware esxi 6.7 下载以及如何在虚拟机里实现显卡直通?

    为了让vmware支持显卡 找了好久esxi下载 版本太多了 都不知道要下哪个 找到别人贡献的百度链接 分析给大家 使用esxi也不行 esxi需要安装在裸机上 才能支持独显 不能直接安装在windows上 后来查资料使用 qemu kvm
  • 【Windows基线检查】

    文章目录 前言 一 目的 二 要求 总结 前言 企业在发布服务器到公网前都应该对服务器进行安全测试 包括漏洞扫描 基线检查 业务流程测试等等 本期介绍Windows基线检查的部分内容和一些操作系统策略设置方法 一 目的 旨在为即将发布到公网
  • 获取时间的方法

    Java获取当前年份 月份和日期是通过Calendar类的实例对象来获取的 首先创建一个Calendar类的实例对象 Calendar类属于java util包 Calendar calendar Calendar getInstance
  • linux内核开发基础(linux内核源码、树莓派源码编译、SD卡挂载)

    首先下载树莓派linux内核源码 下载网址 https github com raspberrypi linux 在树莓派使用指令 uname r查看当前树莓派的版本号 然后选择对应的linux内核版本号进行下载 将linux内核源码从共享
  • linux下写穿/直写(Write-Through)与写回(Write-Back)

    CPU使用高速缓存 DCache 时 它对内存的的写操作有两种模式 写穿 write throuht 写回 write back 写穿 write throuht 模式 该模式下 CPU对主存写数据时 不经过DCdcache直接写到内存 此
  • JavaScript中将字符串的首字母大写

    其实方法有很多 这里我们使用其中一种 利用字符串的内置api来更改 1 定义全小写一个字符串 2 利用字符串的方法将首字母取出转化为大写并与剩余字符串进行拼接 3 弹窗显示结果 个人习惯 当然也可以控制台输出等等 代码为下 let str
  • 简简单单吃个磁盘(硬盘?)

    前言 Version S Description Date By V1 C First Version 2020 10 24 AYZP C Create A Add M Modify D Delete 整理资料的时候 发现个磁盘的相关知识不
  • 怎样建立css,怎样建立新的css规则

    建立新css规则的方法 首先打开dreamweaver软件 然后在菜单中单击 文件 选择 新建 接着创建 XHTML1 0 transitional 最后打开 新建CSS规则 对话框 并指定要创建的CSS规则的选择器类型即可 本教程操作环境
  • android设置状态栏颜色(沉浸式状态栏)

    设置状态栏颜色的方法是andorid4 4以后支持的 最少要api19以上才可以使用哟 方法如下 第一种 public static void setStatusBarTranslucent ViewGroup vg Activity ac
  • mac os 安装 redis

    mac os 安装 redis 在redis官网下载 https redis io download 1 下载 在mac os系统 双指点击 finder 图标 选 Go to Folder 输入 usr local 另外开一个finder
  • 基于鲸鱼算法改进支持向量机SVM的多分类研究,woa-svm

    目录 背影 支持向量机SVM的详细原理 SVM的定义 SVM理论 鲸鱼算法的原理及步骤 SVM应用实例 鲸鱼算法改进SVM的多分类研究 代码 结果分析 展望 背影 传统的支持向量机只能进行二分类 本文调用libsvm工具箱 并用鲸鱼算法改进
  • 算法编程7:一个四位数 abcd,满足 abcd * 4 = dcba,求这个数

    描述 一个四位数 abcd 满足 abcd 4 dcba 求这个数 编程实现1 for i in list range 1000 2500 num2 i 4 a i 1000 b i 1000 100 c i 1000 100 10 d i
  • 序列化错误小结:SerializationFailedException

    公司项目 不提供具体代码 仅提供思路 问题描述 错误报告MultipartRequest无法实现序列化 问题解决1 发生SerializationFailedException时 第一时间根据错误报告定位错误类 发现MultipartReq
  • 分布式事务专题之9、分布式事务解决方案之最大努力通知型

    目录 1 支付宝充值案例 假如我们自己有一个电商系统 支持用户使用支付宝充值 流程如下 2 用户支付流程 是一个同步的过程 用户在浏览器发起充值请求 gt 电商服务 电商服务生成充值订单 状态为0 待支付 0 待支付 100 支付成功 20
  • 软件产品质量模型

    ISO IEC 9126是国际标准组织 ISO 制订的用于评估软件质量的国际标准1 ISO IEC 9126标准由6个特性和27个子特性组成 是评价软件质量的国际标准1 ISO IEC 9126已经被ISO IEC 25010取代 后者是国
  • STM32刷Micropython固件参考指南

    STM32刷Micropython固件指南 其实刷固件和普通的程序下载烧录无多大的差异 主要是其他因数的影响导致刷固件或刷完固件无法运行的情况和相关问题 刷固件教程 固件下载 目前所支持的stm32型号有这些 stm32f0 stm32f4
  • linux进阶05——Makefile(二)

    1 源代码 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