【Linux】自动化构建-Make/Makefile

【Linux】自动化构建-Make/Makefile
前言

        上文我们讲到了Linux中的编译器gcc/g++        【Linux】编译器gcc/g++及其库的详细介绍-ZEEKLOG博客

        本来我们将一个对于编译来说很重要的工具:make/makfile

1.背景

        在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile可以来定义那些文件先编译,那些文件后编译,那些文件需要重新编译。甚至是一些更为复制的功能

        makefile带来是好处就是"一键化编译",只需要一个make命令就可以实现。这极大的提高了开发的效率

会不会写makefile从侧面很大程度的反应了一个人是否具有完成大型工程项目的能力 

2.简单认识什么是make/makefile

make是一个命令工具,用于解释makefile中指令的工具

make是一个指令,makefile是一个文件,需要我们自己建立。两个搭配使用就可以实现我们的自动化编译

3.make/makefile的基本使用

3.1简单一键化编译

创建makefile,并使用vim写入内容(m大小写都可以)

hyc@hcss-ecs-4ce7:~$ touch makefile hyc@hcss-ecs-4ce7:~$ vim makefile 

makefile的基本结构为:依赖关系+依赖方法 

(注:写入依赖方法前,要先点击TAB键。一定要TAB键不要4个空格,这是写书格式!!) 

退出并保存,执行make指令,自动化执行编译

hyc@hcss-ecs-4ce7:~$ make gcc test.c -o test hyc@hcss-ecs-4ce7:~$ ./test hi,Yuzuriha hyc@hcss-ecs-4ce7:~$ ls makefile test test.c 

3.2简单一键化清理

再次打开makefile,写入清除命令

注:

        先忽略.PHONY:clear不看,clear的格式其实和上面的格式都是:依赖关系+依赖方法。只不过clear并没有依赖什么文件,就不写依赖文件

退出并保存,执行make clear,完成一键清除

hyc@hcss-ecs-4ce7:~$ ls makefile test test.c hyc@hcss-ecs-4ce7:~$ make clear rm test hyc@hcss-ecs-4ce7:~$ ls makefile test.c 
大家看到这里可能一头雾水,但是没关系我们来一个一个看

3.2.1为什么这个我们要使用make clear才能达到效果,而前面只需要执行make就可以了呢?

我们可以把这个两个指令交换一下位置,看看效果

我们可以看到此时我们执行make指令时,实现的效果就是清除效果 

hyc@hcss-ecs-4ce7:~$ ls makefile test test.c hyc@hcss-ecs-4ce7:~$ make rm test hyc@hcss-ecs-4ce7:~$ ls makefile test.c 
总结: 
        执行make指令时,会从上到下扫描makefile文件,并且默认执行第一个扫描到的方法。如果想要执行其他方法,可以make + 目标名,显示的调用

3.2.2  .PHONY是什么东西?

.PHONY + 目标名用于声明伪目标

伪目标不是实际存在的目标,而是用于执行特定的命令(如清理)

.PHONT的主要功能是保证对应的依赖关系和依赖方法总是被执行 

要理解什么叫总是被执行?我们可以先理解什么叫不总是被执行。我们可以看到当我们多次执行make指令时,第一次正常执行,而后面的都不再执行了。这就叫不总是被执行。

而换做clear,则可以正常执行多次

同样的,当我们使用 .PHNOY修饰test时,也可以反复的执行编译语句 

 总结:
        .PHONY是定义伪目标,其功能是让其对应的依赖关系和依赖方法总是被执行但一般情况下编译都是不要.PHNOY修饰的,因为代码没有经过修改是不需要反复编译的。反复编译会极大的浪费资源。
补充:make是如何判断源文件是否被修改? 

1.文件的acm时间

make正是通过两个文件的Modify时间来判断出源文件是否被修改的。

如果可执行文件的时间晚于源文件时间,这代表没有被修改。反之,这代表源文件被修改了想要重新编译。

ACM时间小知识:

        Access时间并不是我们想象的我们访问一次就更新一次时间,因为整个系统最频繁的操作就是访问文件,如果每访问一次文件就统计一次时间这会带来巨大的开销。因此,Access时间是会等用户访问到一定次数才会更新。

        Modify时间修改,Change时间往往也会一起修改。因为Modify是记录文件内容修改的时间,但是文件内容有修改其体积大小往往会修改,而体积是属于文件属性这一块的,所以Change时间也会修改。

4.make/makefile深入理解

4.1make的推导规则

现在makefile中为一下内容:

执行make指令我们可以看见,执行的指令顺序和我们写入makefile中的顺序是不一样的

因为makefile的推导规则是满足类似栈结构的:myproc由myproc.o文件推导,而myproc.o当先并不存在,要由myproc.s文件推导。那就先把推导myproc的指令入栈,先推导myproc.o文件。以此类推,直到前置条件完成后,通过出栈依次执行后面的指令

4.2makefile的升级之路

4.2.1makefile可以使用变量

makefile可以像我们的编程语言一样使用自定义变量,来指代文件、指令、选项等等。

$:表示这个变量所指代的内容,比如:$(BIN)就表示myproc这个文件

4.2.2makefile中的特殊变量

$@:表示目标文件,既$(BIN)

$^:表示依赖文件,既$(SRC)


特殊符号可以帮助我们简化makefile的书写

4.2.3makefile中一段依赖关系中可以存在多个依赖方法

一段依赖关系中可以存在多个依赖方法,比如这里我们想直观的看到我们做了什么操作,就可以利用echo来输出信息

效果如下: 

我们这里看到了我们自己写是echo指令回显了,我们如果想要指令不回显只看效果,可以使用@符号

这样指令就不会回显了

4.2.4makefile处理多文件编译

对于多文件的编译,我们上一篇文章讲到过,我们一般都是先将所有文件编译为.o文件,最后在将所有的.o文件连接

%是makefile下的通配符。%.c:%.o表示将当前路径下的所有.o/.c文件全部展开,比如有100个.c文件,这里就会展开一百个依赖关系,并执行一百个依赖方法。 

效果如下:

4.2.5makefile最终版本        

        上面我们说到,如果有多文件的编译makefile的处理方式。确实在依赖方法的书写上,这个便捷多了。但是我们没有考虑到这一切都是建立在使用变量上的,而我们的变量则需要将多个文件表示出来。

如果我们想要编译多个文件,就需要在变量里写多个文件 

 

 3个文件还能接受,可对于项目工程来说有上百个文件怎么办?我们不可能一个一个写上去

解决这一问题有两个方法

方法一:

  OBJ=$(SRC:.c=.o) :语法格式,将.c文件替换为同名.o文件
  SRC=$(shell ls *.c):使用命令行指令,一键获取.c文件

方法二:

 SRC=$(wildcard *.c) :wildcard为makefile的函数,其作用就是获取所有.c文件

至此这就是makefile的最终形态

Read more

【算法】【优选算法】优先级队列

【算法】【优选算法】优先级队列

目录 * 一、1046.最后一块石头的重量 * 二、703. 数据流中的第 K 大元素 * 三、692. 前 K 个⾼频单词 * 四、295. 数据流的中位数 一、1046.最后一块石头的重量 题目链接:1046.最后一块石头的重量 题目描述: 题目解析: * 题意就是让我们拿出提供的数组的最大两个值,大减小作差,将差值再放入数组,直到数组空了或者只有一个元素为止。 解题思路: * 题目要求我们在一个乱序的数组中找最大两个值,我们首先想到数组排序,但是由于我们还需要将差值放入数组,我们放一次就需要排序一次。 * 使用优先级队列,大根堆,开销会小一些,我们只需要每次拿堆顶元素即可。 解题代码: //时间复杂度 O(n)//空间复杂度 O(n)classSolution{publicintlastStoneWeight(int[] stones)

By Ne0inhk
解锁动态规划的奥秘:从零到精通的创新思维解析(3)

解锁动态规划的奥秘:从零到精通的创新思维解析(3)

解锁动态规划的奥秘:从零到精通的创新思维解析(3) 前言: 小编在前几日书写了关于动态规划习题的博客(PS:其实这些都是我的存稿,我已经好久没写博客了截止到现在,确实摆烂),今天各位继续跟着小编的步伐,走进动态规划的世界,接下来我们将会·讲述一个比较新的动态规划问题:路径问题。 正文: 1.不同路径 1.1.题目来源 本题和之前的题目一样,都是来自于力扣,下面小编给上链接:62. 不同路径 - 力扣(LeetCode) 1.2.题目解析 和之前的规矩一样,小编先给各位分析一下题目到底想要传达给我们什么信息,其实本题也是很好理解的,这个题目就像我们小学做过的益智游戏一样,此时给定我们一个机器人,此时我们从左上角开始走,想要我们求解走到右下角的方法有几种,此时我们选择往右走,也可以选择往下走,只要走到右下角即可。这就是一个典型的路径问题,通过动态规划我们就可以轻易解决此类问题,下面小编进入本题的思路讲解部分。 1.3.思路讲解 对于动态规划的题目,我们首先需要先设置好一个dp表用于存放数据,此时根据题目分析我们可以知道此时我们需要设置一个二维的dp表,

By Ne0inhk
【数据结构初阶】--从“最小值筛选”到代码落地,解锁选择排序的核心思想!

【数据结构初阶】--从“最小值筛选”到代码落地,解锁选择排序的核心思想!

🔥@晨非辰Tong: 个人主页 👀专栏:《C语言》、《数据结构与算法入门指南》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 文章目录 * --引言 * 一、排序宗门:选择排序 * 1.1 流派基本思想 * 二、 流派1:直接选择排序 * 1.1 基本思想 * 1.1.1 算法思路 * 1.1.2 特性总结 * 1.2 排序源码呈现 * 1.2.1 残缺排序功法 * 1.2.2 完成排序功法 * 1.3 ==注意要点== * 三、流派2:堆排序 * 3.

By Ne0inhk
三维的组合导航。 ins和卫星的组合导航算法,基于卡尔曼滤波和eskf滤波的都有。 MATLAB源码

三维的组合导航。 ins和卫星的组合导航算法,基于卡尔曼滤波和eskf滤波的都有。 MATLAB源码

三维的组合导航。 ins和卫星的组合导航算法,基于卡尔曼滤波和eskf滤波的都有。 MATLAB源码,有kf和eskf的对比,也有单独的误差,或者输入滤波之后的位移速度等导航参数。 这段程序主要是一个卡尔曼滤波器,用于估计运动物体的位置和速度。它涉及到数据的读取、处理和滤波过程。 首先,程序通过`importdata`函数读取名为`ceshi.txt`的数据文件,并将数据存储在变量`data`中。 接下来,程序从`data`中提取出所需的数据,并将其存储在不同的变量中,如`gvx`、`gvy`、`gvz`等。这些变量代表了运动物体的速度和位置信息。 然后,程序对数据进行处理,计算出一些相关的量,如位移量和时间和。这些处理包括对速度和加速度进行积分,计算位移和时间和。 接下来,程序初始化一些变量,并创建一些空矩阵用于存储测量值和协方差矩阵。 然后,程序进入一个循环,从第二个数据点开始,计算一系列的矩阵和向量,包括转移矩阵、过程噪声协方差、观测矩阵等。然后,程序使用离散卡尔曼滤波公式对状态进行更新和校正,

By Ne0inhk