【Linux】Linux项目自动化构建工具make makefile
文章目录
- 1. 背景
- 2.实例
- 3.原理
- 4.项目清理
- 5. 文件属性中的三个时间
- 6. Linux下第一个小程序——进度条
- 6.1 前置知识1:缓冲区
- 6.2前置知识2:回车换行
- 6.3进度条的实现
- 7 Linux下git的”三板斧“
1. 背景
- 一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建
2.实例
下面,我们使用一个例子来示范怎么使用make和makefile
这里分别是我们的C语言源文件和makefile的内容,然后我们使用make指令
可以看到,使用make指令之后,就执行了makefile的第一行,也就第一个依赖方法。当执行make clean时,执行了clean的内容。这样就完成了我们所需要的功能
下面,我们来详细分析一下上面范例中的各个代码的作用
3.原理
首先明确一点,make/makefile的存在是为了构建项目,构建项目需要依赖关系和依赖方法。举个例子,学生时代的我们都会问父母要钱,要钱的时候,我们会说“老爸,我没钱了,给我打钱”,这里前面半句话就是表明了依赖关系:我是你儿子,你是我爸爸,后面半句话就是表明了依赖方法:给我打钱。
所以,在makefile中需要写的就是依赖关系和依赖方法,然后使用make去通过依赖关系执行依赖方法,从而产生我们需要的文件或者指令。
make是如何工作的?
- make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test_make”这个文件,并把这个文件作为最终的目标文件。
- 如果test_make文件不存在,或是test_make所依赖的后面的test_make.c文件的文件修改时间要比hello这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成hello这个文件。
- 如果test_make所依赖的test_make.c文件不存在,那么make会在当前文件中找目标为test_make.c文件的依赖性,如果找到则再根据那一个规则生成test_make.c文件。(这有点像一个堆栈的过程)
- 当然,你的.c文件和.h文件是存在的啦,于是make会生成 test_make.c 文件,然后再用 test_make.c 文件声明make的终极任务,也就是执行文件test_make了。
- 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
- make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦
知道了这些东西,那么我们如何着手去使用make构建项目呢?
makefile的编写
创建一个名为makefile或者Makefile的文件(只能是这两种可能,否则make识别不出来),在makefile中写入内容
建立依赖关系,谁依赖:于谁,例如上述的实例就是test_make依赖于test_make.c,所以在makefile的首行写
test_make:test_make.c,意思是test_make是由我们自己写的test_make.c编译得来的新起一行,必须以tab键开头(不能是四个空格),写编译的指令,例如上述的
gcc -o test_make test_make.c
makefile的使用
当我们写好makefile之后,直接使用
make 目标文件名/指令名,就可以达到使用make和makefile构建项目的目的,但是,我们上述的实例中直接使用了make指令,没有加上刚刚说的目标文件,也能够正常执行,达到效果,为什么呢?这是因为在makefile中被一个目标文件直接或者间接关联,那么他后面所定义的命令能够被自动执行。
4.项目清理
工程是需要被清理的
在上述的makefile中,我们同时设置了clean这个目标指令的,他的目的就是为了清除我们编译好的工程文件。

但是我们回到上述实例中,可以发现,多了一行内容,是我们不理解的东西,那么它是什么呢?
.PHONY:表示被该关键字修饰的对象是一个伪目标,这里我们引入了一个新的概念,叫做伪目标
什么是伪目标?
还是使用之前的那个test_make,我们发现,当该路径下没有目标文件的时候,我们能够正常的执行make指令,但是当我们想再次执行make指令的时候,发现出现了提示,没有办法正常执行make指令。反而,我们在执行make clean的时候,没有这种情况,能够连续执行任意次的make clean。这就是伪目标的作用。伪目标表示该目标是永远被执行的!!!
对于上述的情况,我们只需要再修改一下源文件test_make.c,就会发现make又可以正常执行一次了。这是因为,make会识别我们上一次编译之后,源文件是否已经被修改,如果没有被修改,就不需要再次执行编译操作,(这一点是很重要的,一个中大型的项目,编译所花的时间短则几十分钟,长则几个小时甚至十几个小时)。
那么make是怎么知道源文件有没有被修改的呢?
答案是比较时间,比较源文件和目标文件的内容修改时间
我们知道,是先有源文件,在有目标文件的,所以,我们只需要比较源文件和目标文件的内容修改时间,如果源文件的内容修改时间早于目标文件的修改时间,那就说明源文件在生成目标文件之后,没有被更改,所以就没有再次编译的必要,否则就需要再次编译。
5. 文件属性中的三个时间
上面我们讲到了文件的修改时间,在这里我们详细介绍一下文件的“三个时间”。
使用stat指令,我们可以看到文件的详细信息,其中就包括了文件的创建时间,修改时间与最后一次访问时间

对于modify和change的时间是容易理解的,但是access的时间改变规则有些不一样
因为对一个文件的访问,是很频繁的,如果每一次的访问,都要修改access时间的话,会导致系统的负荷太大,所以新的Linux内核就对access时间的修改规则做了修正,变成了根据一段时间内访问频率再去更新。
6. Linux下第一个小程序——进度条
6.1 前置知识1:缓冲区

对于这个测试,执行之后的结果是在屏幕上正常的打印hello world,然后停留一秒钟之后再提示输入下一个指令,但是我们将printf中的‘\n’去掉,然后再编译,执行得到的可执行,会发现屏幕中没有立刻显示hello world,而是再一秒钟后再显示的,这是因为每一行的内容会先放在缓冲区中,当执行回车换行也就是‘\n’之后,才会显示,否则就需要等当前进程结束之后再显示,所以为了让上述程序在没有‘\n’也能正常执行,我们需要使用fflush刷新缓冲区,即:

然后我们发现该程序可以正常执行输出然后再停顿了。
6.2前置知识2:回车换行
在刚刚,我们提到了回车换行的概念,但是,回车和换行是两个概念,回车表示的是回到当前行的开头位置,用\r表示,换行表示光标换到下一行的同一位置,但是到这里就会有疑问,我们键盘上的enter键,一般不就是叫做回车键嘛?我们注意一下早期的键盘上,回车键是什么样子的

用了一个向下和向左的箭头表示着这个键的作用是让光标去到下一行的开头。
那么如果不换行,只回车的话,会出现什么情况呢?
答案是会将屏幕上当前行的内容覆盖掉。
那么,利用这种特性,我们能够写出一个简易的倒计时程序

运行的结果是这样的:

这就是我们利用缓冲区和回车换行的特性写出来的简易倒计时。
6.3进度条的实现
有了上述的两个前置知识,我们就可以利用已知的知识写出进度条啦
接下来我们尝试一下多文件编程,首先定义一下头文件和主要的实现源文件,还有主函数文件,分别命名为process.h,process.c,main.c,然后对于一整个项目,我们要写一下makefile文件所以一共要创建四个文件
$ touch makefile process.c process.h main.c


各个部分代码如上,然后使用make编译,产生可执行文件ProcessOn,运行效果如下

7 Linux下git的”三板斧“
由于Linux是没有图形化界面的,所以我们在Windows下使用的“小乌龟”在这里就不能用了,所以我们要学一下git的命令行使用方式
1. git clone
首先,我们需要将已有的仓库拷贝到本地,所以就有了git clone指令,该指令后面跟我们需要拷贝的仓库的链接
2. git add
我们在本地写的代码需要添加到本地仓库,所以需要使用git add指令添加,git add指令后跟文件名,这里我们经常使用的是
git add .表示将所有新增文件全部添加3. git commit
对标Windows下使用小乌龟的过程,我们同样需要commit,我们在commit的同时,还需要附带本次上传的说明,
git commit -m "说明文字"4. git push
上传到本地仓库之后,我们还需要上传到线上的仓库,对标”小乌龟“,我们需要push,所以使用git push指令
注:默认每次上传的时候都要输入用户名和密码,这里可以配置成不需要输入,但是还是建议每次都手动输入点我配置免密码提交
5. git log
我们的每次上传都会被记录下来,成为日志,使用git log就可以查看提交日志
本节完。。。
相关文章:
【Linux】Linux项目自动化构建工具make makefile
文章目录1. 背景2.实例3.原理4.项目清理5. 文件属性中的三个时间6. Linux下第一个小程序——进度条6.1 前置知识1:缓冲区6.2前置知识2:回车换行6.3进度条的实现7 Linux下git的”三板斧“1. 背景 一个工程中的源文件不计其数,其按类型、功能、…...
华为OD机试题 - IPv4 地址转换成整数(JavaScript)| 含思路
华为OD机试题 最近更新的博客使用说明本篇题解: IPv4 地址转换成整数题目输入输出示例一输入输出说明示例一输入输出说明Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | …...
spring整合通用mapper
1.使用通用mapper可以更快速的进行数据库的增删查改操作,加入springboot的管理,常规的SQL都可以复用 2.整合 a)引入依赖 <dependencies><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId>…...
一天什么时间发抖音浏览量高?5个抖音最佳发布时间段
抖音作为现在一款现象级的软件,已经不知不觉地影响着我们生活的方方面面。那抖音想要被更多人看到,就需要掐准哪些时间活跃数最多,今天就来和大家分享一下一天什么时间发抖音浏览量高,又该如何抓住最佳投放契机呢?一、一天什么时…...
华为OD机试题 - 关联子串(JavaScript)| 含思路
华为OD机试题 最近更新的博客使用说明本篇题解:关联子串题目输入输出示例一输入输出说明示例二输入输出说明Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典...
【代码随想录训练营】【Day33休息】【Day34】第八章|贪心算法|1005.K次取反后最大化的数组和|134. 加油站|135. 分发糖果
K 次取反后最大化的数组和 题目详细:LeetCode.1005 这道题比较简单,这里直接给出贪心策略: 局部最优解: 按照 负数 > 0 > 正数 的优先级次序,依次对nums中的较小数值进行取反因为负负得正,负值越小…...
<c++> const 常量限定符
文章目录什么是 const 常量限定符const 的初始化const 的默认作用域const 的引用例外情况const 与指针const指针的声明指向 const 的指针const指针指向 const 的 const指针什么是 const 常量限定符 Q:什么是 const 常量限定符? A:const名叫常…...
pytorch实现transformer模型
Transformer是一种强大的神经网络架构,可用于处理序列数据,例如自然语言处理任务。在PyTorch中,可以使用torch.nn.Transformer类轻松实现Transformer模型。 以下是一个简单的Transformer模型实现的示例代码,它将一个输入序列转换为…...
【懒加载数据 Objective-C语言】
一、咱们就开始进行懒加载 1.懒加载发现,每一个字典,是不是就是四个键值对组成的: 1)answer:String,中国合伙人, 2)icon:String,movie_zghhr, 3)title:String,创业励志电影, 4)options:Array,21 items 前三个都是String类型,最后是不是Array类型, 所…...
人脸网格/人脸3D重建 face_mesh(毕业设计+代码)
概述 Face Mesh是一个解决方案,可在移动设备上实时估计468个3D面部地标。它利用机器学习(ML)推断3D面部表面,只需要单个摄像头输入,无需专用深度传感器。利用轻量级模型架构以及整个管道中的GPU加速,该解决…...
JMeter 控制并发数
文章目录一、误区二、正确设置 JMeter 的并发数总结没用过 JMeter 的同学,可以先过一遍他的简单使用例子 https://blog.csdn.net/weixin_42132143/article/details/118875293?spm1001.2014.3001.5501 一、误区 在使用 JMeter 做压测时,大家都知道要这么…...
git常用命令汇总
Git 是一种分布式版本控制系统,它具有以下优点: 分布式:每个开发者都可以拥有自己的本地代码仓库,不需要连接到中央服务器,这样可以避免单点故障和网络延迟等问题。 非线性开发:Git 可以支持多个分支并行开…...
【2023】华为OD机试真题Java-题目0226-寻找相似单词
寻找相似单词 题目描述 给定一个可存储若干单词的字典,找出指定单词的所有相似单词,并且按照单词名称从小到大排序输出。单词仅包括字母,但可能大小写并存(大写不一定只出现在首字母)。 相似单词说明:给定一个单词X,如果通过任意交换单词中字母的位置得到不同的单词Y,…...
【项目管理】晋升为领导后,如何开展工作?
兵随将转,作为管理者,你可以不知道下属的短处,却不能不知道下属的长处。晋升为领导后,如何开展工作呢? 金九银十,此期间换工作的人不在少数。有几位朋友最近都换了公司,职位得到晋升,…...
JAVA开发(Spring Gateway 的原理和使用)
在springCloud的架构中,业务服务都是以微服务来划分的,每个服务可能都有自己的地址和端口。如果前端或者说是客户端直接去调用不同的微服务的话,就要配置不同的地址。其实这是一个解耦和去中心化出现的弊端。所以springCloud体系中࿰…...
踩坑:解决npm版本升级报错,无法安装node-sass的问题
npm版本由于经常更新,迁移前端项目时经常发现报错安装不上。 比如,项目经常使用的sass模块,可能迁移的时候就发现安装不了。 因为node-sass 编译器是通过 C 实现的。在 Node.js 中,采用 gyp 构建工具进行构建 C 代码,…...
xFormers安装使用
xFormers是一个模块化和可编程的Transformer建模库,可以加速图像的生成。 这种优化仅适用于nvidia gpus,它加快了图像生成,并降低了vram的使用量,而成本产生了非确定性的结果。 下载地址: https://github.com/faceb…...
React—— hooks(一)
🧁个人主页:个人主页 ✌支持我 :点赞👍收藏🌼关注🧡 文章目录⛳React Hooks💸useState(保存组件状态)🥈useEffect(处理副作用)🔋useCallback(记忆函数&#…...
Ubuntu20.04下noetic版本ros安装时rosdep update失败解决方法【一行命令】
一、问题: 安装完ros后,需要执行sudo rosdep init,但是在没有全局科学上网的前提下,执行sudo rosdep init势必会报错: ERROR: cannot download default sources list from: https://raw.githubusercontent.com/ros/r…...
Vue2.0开发之——购物车案例-Footer组件封装-计算商品的总价格(51)
一 概述 App.vue中计算勾选商品的总价格定义子组件Footer中的商品总价格将App.vue中商品的总价格传递给Footer显示 二 App.vue中计算勾选商品的总价格 2.1 商品总价格的计算逻辑 所有勾选商品的价格*数量 2.2 App.vue中通过计算属性计算总价格 通过计算属性计算总价格 co…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...



