【Linux】Linux下的Makefile基本操作

news2024/12/23 13:08:34

1.Makefile与 make介绍

在Linux中, Makefile 是⼀个⽂件, 令会在当前⽬录下找 make 是⼀个指令,当使⽤ Makefile ⽂件从⽽执⾏内部的内容

2.创建第一个 Makefile并使用make

⾸先,在当前⽬录下创建⼀个makefile文件

接下来在同级⽬录下创建⼀个 code.c ⽂件

使⽤vim编辑器输⼊下⾯的内容:

 #include <stdio.h>
 int main()
 {
 printf("hello linux\n");
 return 0;
 }

保存c ode.c ⽂件后退出当前vim,使⽤vim打开 Makefile 文件 输⼊下⾯的内容:

code:code.c
 gcc -o code code.c
 .PHONY:clean
 clean:
 rm -rf code

需要注意, gcc -o code code.c和 rm -rf code前⽅是⼀个Tab键的⼤ ⼩,⽽不是4个或者8个空格

保存M akefile ⽂件后退出当前vim,在当前⽬录下输⼊ make 指令即可在当前⽬录下 创建code.c 对应的可执⾏⽂件(具有可执⾏权限并且⽂件本身可执⾏) code ,例 如下图:

通过常规⽅式运⾏该可执⾏⽂件 ./code 即可看到打印输出的内容:

接着使⽤ make clean 指令清理刚才⽣成的可执⾏⽂件 code :

3.Makefile文件基本格式介绍

以前⾯例⼦中的 Makefile 为例:

 code:code.c
 gcc -o code code.c
 .PHONY:clean
 clean:
 rm -rf code

第⼀⾏中的 code:code.c 代表依赖关系, code 表示⽬标⽂件, 赖⽂件列表中的⽂件,第⼆⾏的 code.c 表示依 gcc -o code code.c代表依赖⽅法(指令)

第三⾏中的 .PHONY 表示⽣成⼀个伪⽬标, clean 表示伪⽬标的名字(可以类⽐ 变量名)

第四⾏及第五⾏与第⼀⾏及第⼆⾏含义⼀致,表示依赖关系和依赖⽅法,⽽因为 clean 没有需要依赖的⽂件,所以 clean: 后没有任何依赖⽂件列表⽂件

依赖关系:表示两个⽂件之间构成的⼀定关系,⽐如⽗⼦关系

依赖⽅法:通过依赖⽅法可以执⾏的对应的指令

依赖⽂件列表: code.c 所处的位置即为依赖⽂件列表,为了⽣成⽬标⽂件 code 而需要的⽂件称为依赖⽂件,依赖⽂件列表可以含有不⽌⼀个⽂件

注意:理论上来说,依赖⽂件列表中的  code.c 在当前情况下可以不写,但是如 果不写,在第⼀次执⾏ make 指令后,不论之后 code.c 是否修改,再执⾏ make 指令都⽆法执⾏对应的依赖⽅法,因为 code ⽂件已经存在,所以为了保 证可以修改,需要加上 code.c

从上⾯的运⾏结果可以看出,每⼀次执⾏make时都会在控制台回显出对应的依赖⽅ 法,如果将编译指令改为 echo "测试",则效果如下:

可以看到先回显了对应的依赖⽅法,再执⾏依赖⽅法,如果不希望出现这种情况,可 以在执⾏的指令前加上@使指令不再回显,所以上⾯的 Makefile 可以修改为:

 code:code.c
  2   @echo "Start Compiling..."
  3   @gcc -o code code.c
  4   @echo "End Comliling"
  5 .PHONY:clean
  6 clean:
  7     @echo "Cleaning code..."
  8     @rm -rf code
  9     @echo  "End Cleaning..."
 10                                                                                   
~

⼀个依赖集中可以有多个依赖⽅法

此时正常运⾏结果如下:

如果代码出现错误,则 gcc 会中断编译,所以此时运⾏结果如下:

使⽤. PHONY 可以⽣成⼀个指定名字的伪⽬标,伪⽬标的作⽤是:清除依赖⽅法执⾏ 时进⾏的⽂件时间对⽐,下⾯是具体介绍: ⾸先,在Linux中可以使⽤ stat+⽂件名查看⽂件当前的属性,对于 code.c 有:

执⾏结果中,主要关注三个部分: Access 、 Modify 和 Change ,这三个部分分别 表示⽂件最近⼀次的访问时间、⽂件内容被修改的时间和⽂件属性被修改的时间

Access 时间:⼀般不是特别精确,因为如果⼀个⽂件访问⼀次就需要更新⼀次 访问时间,那么对于多个⽂件来说,这种操作的消耗对于CPU来说是很⼤的

Modify 时间: Modify 时间只表示⽂件内容被修改的时间,如果⽂件属性时间 修改,则不影响 Modify 时间,但是需要注意, 着Ch Modify 时间⼀旦改变⼀般伴随 ange 时间改变,因为修改⽂件内容有时会影响到⽂件的相关属性(例如⽂ 件⼤⼩等)

Change 时间:Change 时间只表示⽂件属性被修改的时间,修改⽂件属性时间不会影响Modify时间

接着,观察对于没有添加伪⽬标的 Makefile 第⼀部分依赖集,如果code文件已经存在,再一次进行make的效果:

code:code.c
 @echo "Start Compiling..."
 @gcc -o code code.c
 @echo "End Compiling..."

那么指令是如何知道⽂件是否被修改呢?就是通过前⾯提到的 Modify 时间和 Change 时间,过程如下图所示:

因为code.c 创建的时间早于 code.c 编译的时间,所以开始时不存在 所以第⼀次执⾏ code ⽂件, make 指令时正常执⾏。

当code.c ⽂件未修改时,第⼆次执⾏ make 指令会发现 code.c 的 Change 时间依旧在 make 之前,因为第⼀次已经满⾜了 Modify 时间和 code.c 的两个时间在 code ⽂件的两个时间之前,所以 gcc 就不会再进⾏⼀次编译。

当修改 code.c ⽂件后, code.c 的 的两个时间在 Modify 时间和 Change 时间改变,导致 code ⽂件的两个时间之后,此时 code.c gcc 就可以正常执⾏,从⽽ make 指 令不受影响

⽽如果再 Makefile 中为这⼀部分添加⼀个伪⽬标,则可以清除指令中⽂件时间的对 ⽐过程:

.PHONY:code
     code:code.c
 @echo "Start Compiling..."
 @gcc -o code code.c
 @echo "End Compiling..."

此时⽆论执⾏多少次 make 指令,都不会出现 : make 指令中 gcc 因为⽂件时间对⽐⽽导致执⾏结果不同

make 指令虽然结果完全相同,但是不代表依赖⽅法没有执⾏,即⽂件确实每⼀ 次都重新编译

执⾏完编译部分的 make 指令,想要执⾏删除 code ⽂件对应的 make 后加上 clean ,这个 make 指令需要在 clean 代表伪⽬标名,之所以前⾯直接使⽤ make 就可以 执⾏编译指令,是因为 make 指令在读取 Makefile ⽂件时是从上⾄下顺序查找,⽽ 直接使⽤ make ,就会执⾏第⼀个依赖集对应的依赖⽅法,执⾏完毕后就不会再继续 往下读;⽽对于删除 code ⽂件的指令来说,其所在位置时Makefile 中的第⼆个依赖集,所以需要告诉 make 指令找哪⼀部分

所以,此处可以看出.PHONY 的第⼆个作⽤就是声明⼀个伪⽬标,通过该伪⽬标帮助make 指令快速定位需要执⾏的依赖集

如果细⼼可以发现,对于 clean 依赖集来说,不论是否有 .PHONY 都可以⽆限制执⾏ rm -rf依赖⽅法,所以可以推断出 rm -rf指令本身不会考虑⽂件的时间属性,但 是为什么此处还需要加 .PHONY ?⼀⽅⾯是为了声明伪⽬标,另⼀⽅⾯是为了当前依 赖集中的其他指令会有时间对⽐

4.Makefile通用写法

在前⾯的Makefile中,每⼀个依赖⽅法都需要在前⾯的依赖关系部分的⽂件重新写⼀ 遍,为了简化过程,可以使⽤下⾯的写法:

 TARGET=code
 SRC=code.o
 $(TARGET):$(SRC)
 $(CC) -o $@ $<
 %.o:%.c
 $(CC) -c $< -o $@
 .PHONY:clean
 clean:
 @rm -rf $(TARGET) $(SRC)

上⾯的代码中,⾸先创建了两个变量分别代表⽣成的⽬标⽂件 code 以及第⼀个依赖 集中的依赖⽂件列表中的⽂件,在依赖⽅法中使⽤了两个⾃动变量(⼀般建议⼤ 写),分别是$@和$<

在M akefile 中, $@ 表示⽣成的⽬标⽂件,$<表示从依赖⽂件列表中取出⼀个⽂ 件,对应的还有$^表示依赖⽂件列表中的所有⽂件

⽽对于gcc来说,在 Makefile 中可以使⽤内置变量 如果涉及到多个⽂件编译,则在 SRC 和 CC (表示C编译器的名字)代替 %.c 处使⽤空格分隔每⼀个⽂件

⾄此,⼀个基本的 Makefile ⽂件编写语法就这么多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2216661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态规划一>珠宝的最高价值

1.题目&#xff1a; 2.解析&#xff1a; 代码&#xff1a; /**1.创建dp表2.初始化3.填表4.返回*/public int jewelleryValue(int[][] frame) {int m frame.length, n frame[0].length;int[][] dp new int[m1][n1];//虚拟节点的值直接为0满足条件&#xff0c;已经初始化好…

字典树 计数问题(含 2022 icpc杭州 K)

//最近学了字典树&#xff0c;补一下 1.概念和实现 首先&#xff0c;字典树是一棵树&#xff08;废话&#xff09;&#xff0c;边表示字母&#xff0c;从根到叶子节点所有边的顺序组合表示字目排列顺序。 看一下图明白很多&#xff1a; 例如&#xff1a;abc这个字母排序&am…

MybatisWebApp

如何构建一个有关Mybatis的Web&#xff1f; 在这里给出我自己的一些配置。我的TomCat版本&#xff1a;10.1.28 &#xff0c;IDEA版本&#xff1a;2024.1.4 Pom.XML文件 <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/200…

Linux platform子系统和设备树

1 Linux platform子系统 在Linux 2.6内核中&#xff0c;提出了总线、设备、驱动的架构&#xff0c;目的是让我们写出来的驱动通用性更强。 arm核内部总线结构&#xff1a; 1.1 核心思想 将设备的信息从驱动中分离出来&#xff0c;我们需要在操作系统中&#xff0c;添加设备…

【H2O2|全栈】JS入门知识(二)

目录 JS 前言 准备工作 运算符 算数运算符 比较运算符 自增、自减运算符 逻辑运算符 运算符的优先级 分支语句 if-else语句 switch语句 三元表达式 结束语 JS 前言 本系列博客主要分享JavaScript的基础语法知识&#xff0c;本期为第二期&#xff0c;包含一些简…

平时使用Xshell能连接虚拟机,现在突然连接不上

问题&#xff1a;平时使用Xshell能连接虚拟机&#xff0c;现在突然连接不上&#xff0c;使用ip addr 命令查看ip地址 ens33 接口状态为 DOWN&#xff0c;没有分配IP地址&#xff0c;这通常意味着该网络接口未激活或存在配置问题。&#xff08;因为平时能连接&#xff0c;就说明…

mysql 09 独立表空间结构

表空间中的页实在是太多了&#xff0c;为了更好的管理这些页面&#xff0c;设计 InnoDB 的大叔们提出了 区 &#xff08;英文名&#xff1a; extent &#xff09;的概念。对于16KB的页来说&#xff0c;连续的64个页就是一个 区 &#xff0c;也就是说一个区默认占用1MB空间大小。…

农作物苹果叶片病虫害识别数据集

农作物苹果叶片病虫害识别数据集 一、引言 农作物病虫害是影响农业生产的重要因素之一&#xff0c;其中苹果作为广泛种植的水果品种&#xff0c;其叶片病虫害问题尤为突出。为了有效应对苹果叶片病虫害&#xff0c;提高苹果产量和品质&#xff0c;农业科研机构和学者不断开展…

2024软考网络工程师笔记 - 第4章.局域网和城域网

文章目录 局域网基础1️⃣局域网和城域网体系架构 IEEE&#xff08;负责链路层&#xff09;2️⃣局域网拓扑结构 &#x1f551;CSMA/CD1️⃣CSMA/CD2️⃣CSMA/CD三种监听算法3️⃣冲突检测原理 &#x1f552;二进制指数退避算法1️⃣ 二进制指数退避算法 &#x1f553;最小帧长…

你的抠图最快速度是多久?

前言 在图像处理的过程中&#xff0c;抠图速度和质量往往是大家非常关注的问题。那么&#xff0c;你的抠图最快速度是多久呢&#xff1f;今天我要给大家分享一个我用过的极为方便的抠图工具 —— 千鹿 AI。 只需要简单地上传图片&#xff0c;几秒钟后&#xff0c;就能得到一张…

【超详细】TCP协议

TCP(Transmission Control Protocol 传输控制协议) 传输层协议有连接可靠传输面向字节流 为什么TCP是传输控制协议呢&#xff1f; 我们以前所看到的write接口&#xff0c;都是把用户级缓冲区的数据拷贝到发送缓冲区中&#xff0c;然后数据就由TCP自主决定了&#xff0c;所以…

29.第二阶段x86游戏实战2-遍历周围-花指令与二叉树数据结构(有如何阅读vm代码混淆代码)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

到底是微服务,还是SOA?

引言&#xff1a;大概正式工作有5年了&#xff0c;换了三个大厂【也是真特么世道艰难&#xff0c;中国互联网人才饱和了】。基本上每个公司有的架构都不太相同&#xff0c;干过TOC和TOB的业务&#xff0c;但是大家用的架构都不太相同。有坚持ALL in one的SB&#xff0c;最后服务…

windows下安装、配置neo4j并服务化启动

第一步&#xff1a;下载Neo4j压缩包 官网下载地址&#xff1a;https://neo4j.com/download-center/ &#xff08;官网下载真的非常慢&#xff0c;而且会自己中断&#xff0c;建议从以下链接下载&#xff09; 百度网盘下载地址&#xff1a;链接&#xff1a;https://pan.baid…

李生——2024年特别推荐中国品牌艺术家

李生北京人&#xff0c;字玄鹤、云鹤&#xff0c;号墨湖斋&#xff0c;玄鹤楼&#xff0c;中国共产党党员。主要成就:中国著名书法家、国家高级书法师、中国当代正能量文艺工作者:时代标杆等荣誉称号&#xff0c;现为中国东方文化研究会科教文化艺术专业委员会副研究员。自幼喜…

基于Python的博客系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

JavaSE——泛型

目录 一、泛型的引入 二、泛型的好处 三、泛型介绍 四、泛型的语法 (一)泛型的声明 (二)泛型的实例化 五、泛型使用的注意事项和细节 六、泛型练习题1 七、自定义泛型 (一)自定义泛型类 (二)自定义泛型接口 (三)自定义泛型方法 八、泛型练习题2 九、泛型的继承和…

【Linux-进程间通信】vscode使用通信引入匿名管道引入

一、新系统&#xff0c;新软件 1.新系统 哈喽宝子们&#xff0c;从今以后我们不再使用风靡一时的CentOS系统了&#xff0c;因为CentOS已经不在维护了&#xff0c;各大公司几乎也都从CentOS转入其他操作系统了&#xff1b;我们现在由原来的CentOS系统切换到最新的Ubuntu系统&a…

向日葵下载教程以及三款远程控制工具推荐!!!

向日葵远程控制下载教程&#xff01;&#xff01; 亲爱的朋友们&#xff0c;如果你对远程控制软件有所需求&#xff0c;那么向日葵绝对是一个不错的选择。现在我将带你走一遍向日葵的下载流程。 1. 打开你的浏览器&#xff0c;输入“向日葵官方网站”&#xff0c;进入官方网站…

力扣之1398.购买了产品A和产品B却没有购买产品C顾客

题目&#xff1a; Sql 建表语句&#xff1a; Create table If Not Exists Customers (customer_id int, customer_name varchar(30)) Create table If Not Exists Orders (order_id int, customer_id int, product_name varchar(30)) Truncate table Customers insert in…