当前位置: 首页 > news >正文

Linux项目自动化构建工具—make与makefile

目录

make/Makefile

为什么需要用到make/Makefile呢?

具体谈谈make与Makefile

Makefile

make

例子

项目清理 

 make的工作原理



make/Makefile

我们先来简单认识一下什么是make与Makefile,它们是用于自动化构建软件项目的工具,主要用于编译源代码文件,管理项目依赖关系,并确保只重新编译那些自上次构建以来有所更改的文件


为什么需要用到make/Makefile呢?

在window平台下编写C或者C++代码的时候,我们一般使用的都是配置完成的集成的开发环境,在我们完成代码编写的时候,我们只需要点击运行,平台便会自动的帮我们生成可执行文件,至于中间具体的过程,平台向用户进行了省略。

如在vs下我们生成可执行文件a.out时,需要经过四个步骤

  1. 由源文件test.c经过预编译(-E)得到test.i
  2. test.i经过编译(-S)得到test.s
  3. test.s经过汇编(-C)得到test.o
  4. 最后经过链接得到可执行文件a.out

 而在Linux下则不同,每一个源文件都需要用户手动地进行指令编译生成可执行文件。

在Linux中,我们也需要这种一站式服务,于是make和Makefile就出现了。

具体谈谈make与Makefile

Makefile

Makefile是一个文件。它是一个工程文件的编译规则,它记录了原始码如何编译的详细信息、描述了整个工程的编译链接等规则。

Makefile存在的意义就是为了构建依赖关系和依赖原理。

Makefile带来的好处是“自动化编译”,一旦写好的话,只需要一个make命令,整个工程的完全自动编译,极大的提高了软件开发的效率。

target(目标文件):文件1 文件2(依赖文件列表)		//依赖关系<Tab>gcc -o 欲建立的执行文件 目标文件1 目标文件2		///依赖方法command......

target为目标文件,即最终做需要的可执行文件。

  • 依赖文件列表即生成目标文件所需要的文件或目标。

  • <Tab>即这一行必须以TAB键开头,注意不能空格敲四下来代替。

  • <Tab>后面的即make需要执行的命令(这里可以是任意的shell命令)。

  • 如果在依赖文件列表中,有一个及以上的文件或目标比target文件新的话,command命令就会被执行。即make并不会管命令是怎么工作的,它只管执行所定义的命令,make会比较target和依赖文件列表中文件的修改日期,若后者比前者文件日期要新或者target不存在,则make会执行后续定义的命令(在后面的make原理会讲到)。

make

make是一个命令工具,是一个解释Makefile中指令的命令工具。

总结:make是一个命令,Makefile是一个文件,他们两个搭配使用,完成项目的自动化创建。

例子

这里我们简单举个例子,利用多文件的方式来使用make/Makefile进行编译。

  1. 我们先在Practice目录下touch三个文件分别保存函数的声明(.h文件),函数的实现(.c文件),主函数

     

#pragma once  
#include<stdio.h>
extern int count(int a,int b); 
#include"mytest.h"
int count(int a,int b)
{return a+b;                                                                                                                                           }
#include"mytest.h"                                                                                                                                       
int main(){int a=40;int b=50;int ret=count(a,b);printf("%d\n",ret);return 0;}

2、下面进行Makefile的编写

为了方便书写,Linux中还有特殊符号,如$@ 表示目标文件、$<表示第一个依赖文件、$^表示所有的依赖文件,所以上面的Makefile我们还可以写为

 

 如图,我们想生成一个可执行文件processOn,它依赖于main.c和mytest.c,第二行是它的依赖方法。此时我们使用make命令,则目录下会自动生成一个可执行文件processOn.

接着我们运行processOn

那么问题来了,Makefile的第三至5行是什么呢?

项目清理 

  • 工程是需要被清理的。
  • 像clean这种没有被第一个目标文件直接或者间接关联,那么它后面的命令就不会被执行,所以我们可以显式要make执行,即make clean,以此来一次性清除所有生成的目标文件,以便于重新编译。
  • .PHONY是一个关键字,被该关键字修饰的对象是一个伪目标,该目标总是被执行,不是拿时间来作为新旧文件的对比。所以一般将clean设置成伪目标。

 make的工作原理

  • make会在当前目录下找名字叫“Makefile”或“makefile”的文件,所以在创建makefile文件时首字母大小写都可以。
  • 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到processOn这个文件, 并把这个文件作为最终的目标文件。
  • 如果processOn文件不存在,或是processOn所依赖的后面的mytest.c/main.c文件的文件修改时间要比processOn这个文件新,那么,他就会执行后面所定义的命令来生成processOn这个文件。

那么make怎么判断文件的新旧呢?以什么依据作为判断条件呢?

我们可以使用Linux下的stat命令来查看源文件和可执行文件的所有属性

如图,上面一共有三个时间分别是 Acess(最后一次访问该文件的时间)、Modify(最后一次更改该文件属性或状态的时间)、Change(最后一次修改该文件内容的时间),make将Change的时间作为比较新旧的标准。

若processOn的时间比依赖文件列表main.c或mytest.c的时间晚,则不会执行make后面的命令。

而如果像前面的clean一样加了关键字.PHONY后成为伪目标,则make会执行后边的命令,即使目标文件的时间比依赖文件的时间晚。

  • 如果processOn所依赖的mytest.c/main.c文件不存在,那么make会在当前文件中找目标为mytest.c/main.c文件的依赖性,如果找到则再根据那一个规则生成mytest.c/main.c文件。(这有点像一个堆栈的过程)
  • 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

例如,下面的Makefile文件,目标文件test的形成依赖于test.o文件,但是test.o文件不存在,所以寻找test.o文件的依赖关系,找到test.s文件,而test.s文件也不存在,再找test.s的依赖关系,就这么一层层找下去,直到找到最后一个文件的依赖关系,生成test.i文件,再一层层往上生成,所以看起来有点像一个堆栈的过程。

  • 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错, 而对于所定义的命令的错误,或是编译不成功,make根本不理。
  • make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起, 我就不工作啦。


http://www.mrgr.cn/news/74980.html

相关文章:

  • 哈希表(极速学习版)
  • 什么是 C++ 中的智能指针?有哪些类型的智能指针?
  • dockerdsktop修改安装路径/k8s部署wordpress和ubuntu
  • 神经网络10-Temporal Fusion Transformer (TFT)
  • element ui 走马灯一页展示多个数据实现
  • 【动手学深度学习Pytorch】4. 神经网络基础
  • spring @Qualifier 注解解决依赖注入时类型相同但名称不同的 bean问题
  • window上 opencpn主要文件位置
  • JavaScript——DOM编程、JS的对象和JSON
  • VTK知识学习(8)-坐标系统
  • 18 为什么这些SQL语句逻辑相同,性能却差异巨大?
  • Spring Data Redis常见操作总结
  • Redis使用
  • 初识Redis
  • 护照阅读器在银行应用:提升客户身份认证效率,强化金融安全防护
  • javascript-Web APLs (五)
  • 区块链智能合约开发:全面解析与实践指南
  • C#基元类型表
  • 大数据治理:从概念到实践的旅程
  • SELINUX和防火墙
  • 【MMIN】缺失模态想象网络用于不确定缺失模态的情绪识别
  • 数据库参数备份
  • 父子孙嵌套组件的生命周期
  • IntelliJ IDEA设置打开文件tab窗口多行展示
  • HTTP基础
  • 网站架构知识之nginx负载均衡(day027)