[Linux入门]---Linux项目自动化构建工具-make/Makefile

目录

  • 1.背景
  • 2.make指令
    • 输入make默认为Makefile文件第一条指令执行
    • Makefile文件对gcc指令特殊处理及原理
    • 特殊符号
  • 3.总结

1.背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:DelphimakeVisual C++nmakeLinuxGNUmake。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2.make指令

我们使用vim编辑器创建了test.c文本文件编译了如下代码:

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

输入指令:

gcc -o mytest test.c//编译允许代码

Xshell演示结果如下:
在这里插入图片描述

这个编译运行可执行程序过程还算简单,那如果需要代码代码预处理、编译、汇编、链接生成可执行程序等等过程的时候,那么就需要输入如下指令:

gcc -E test.c -o test.i #预处理
gcc -S test.i -o test.s #编译
gcc -c test.s -o test.o #汇编
gcc test.o -o test #生成可执行程序
./test #找到对应路径下可执行程序运行

使用完之后,或者发生错误,需要删除文件

rm -rf test.i test.s test.o test

Xshell演示结果如下:
在这里插入图片描述

上面的指令输入一次还算简单,假设你的代码需要多次修改,就需要重复输入预处理、编译、汇编、链接、删除指令,会很麻烦!这时候我们就需要使用到Makefile文件/makefile文件(首字母m大小写都可以)。

使用vim编辑器创建Makefile文件,向里面编入如下指令

test:test.ogcc test.o -o test 
test.o:test.sgcc -c test.s -o test.o
test.s:test.igcc -S test.i -o test.s
test.i:test.cgcc -E test.c -o test.i
clean:rm -rf test test.o tes.s test.i

Xshell演示结果如下:
在这里插入图片描述
在这里插入图片描述

  • test:test.o为依赖关系,即test文件生成需要依赖于test.c文件该指令写在行首;gcc test.o -o test 为依赖方法,通过gcc指令处理test.o文件得到test文件,该指令前有一个tab键的空格;所以必须要有test.o文件,而test.o文件的生成依赖于test.s文件,test.s文件依赖于test.i文件,test.i文件依赖于test.c文件,依赖关系后面伴随着依赖(实现)方法,由此可以看出test文件需要依靠层层依赖关系以及依赖方法才能得到;(像递归一样)
  • ②而clean指令后面为空格,无依赖关系表明clean不依赖于任何文件、指令,同时有自己的依赖(实现)方法。

输入make默认为Makefile文件第一条指令执行

指令实现顺序如下:
在这里插入图片描述
只输入make指令:
在这里插入图片描述
指令实现顺序如下:
在这里插入图片描述
只输入make指令:
在这里插入图片描述

①只输入make指令,只会执行Makefile文件实现的第一条指令(从上到下),一般我们程序执行指令放在作为Makefile文件的第一条指令;其他指令通过make+Makefile指令/文件名实现!
②Makefile文件的各文件依赖关系指令可以在任意位置(不一定是从上到下),系统会在Makefile文件中找到得到目标文件需要实现的依赖方法,所以对应的依赖关系缺失会导致指令运行不起来!总而言之就是make会自动推导Makefile中的依赖关系(栈式结构)

Makefile文件对gcc指令特殊处理及原理

为什么进行编译拦截?
在这里插入图片描述

我们使用make指令对test文件进行多次编译运行,发现只有第一次make指令被执行了,再次输入make指令却不被执行!这是为什么呢?就像机器提示那样:test文件没有更新,所以不需要进行多次编译!为什么机器会对我们的多次编译的指令进行拦截呢?多次编译消耗时间,会使Linux机器的工作效率大大降低,我们现在之所以没有感受出来,是因为写的代码太少了,当程序代码量很大的时候,编译一次编译需要消耗几十分钟、几个小时甚至更久,我相信对同样的代码编译多次的行为,作为程序员的你是第一个不答应的!😾😾😾

怎么做到对相同源文件只做一次编译呢?
一般情况下是由源文件生成可执行文件(即先有源文件,才有可执行文件),所以源文件最近修改时间比可执行文件早(老)。如果我们更改了源文件,此时源文件的修改时间比旧的可执行文件晚,所以此时我们使用make指令就可以将修改后的源代码重新编译生成新的可执行文件。该过程是怎么样的呢?接下来让我们认识一条指令!
stat指令

语法:stat 选项 文件名
功能: 显示文件\文件系统的详细信息,包括文件的访问时间,文件内容修改时间,文件属性的修改时间。
在这里插入图片描述
Access:文件的访问时间,查看、修改文件内容都可以算访问,Access显示的时间更新;Modify:文件内容修改时间,只有对文件内容进行增删等修改文件内容操作,Modify时间更新;Change:文件属性的修改时间,文件大小、文件拥有者、文件所属组等文件属性修改,Change显示时间会被更新。②文件内容修改一次,Modify显示的时间会被更新;文件属性内容修改一次,Change显示的时间会被更新;因为平时我们访问文件的次数比较频繁,所以访问文件达到一定次数Access显示的时间才会被更新。③修改源文件内容而引起的时间变化,源文件是否被编译比较源文件和可执行文件的是Modify显示的时间。
在这里插入图片描述
在这里插入图片描述

使用touch指令更新时间

指令1: touch -a 文件名(使用该指令更新文件的Access显示的时间、Change显示的时间)
指令2: touch -m 文件名(使用该指令更新文件的Modify显示时间)
先使用touch -m 文件名更新源文件的Modify显示时间,然后使用make指令重新编译源文件!
在这里插入图片描述

特殊符号

在这里插入图片描述
使用特殊符号:
在这里插入图片描述
使用之后:
在这里插入图片描述

$@表示冒号左边的文件名,$^表示冒号右边的文件名,在Makefile文件可以使用@放在语句前进行注释!

使用.PHONY将目标文件成为伪目标
在这里插入图片描述
在这里插入图片描述

使用.PHONY可以将test指令(文件)变成伪目标,使该指令(文件)总是被执行!一般情况,我们将clean指令(文件)设置为伪目标!
在这里插入图片描述

3.总结

1make会在当前目录下找名字叫“Makefile”“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
3. 如果test文件不存在,或是test所依赖的后面的test.o文件的文件修改时间要比test这个文件新,就会执行后面所定义的命令来生成test这个文件。
4. 如果test所依赖的test.o文件不存在,那么make会在当前文件中找目标为test.o文件的依赖性,如果找到则再根据那一个规则生成test.o文件。(这有点像一个堆栈的过程)
5. test.o的依赖方法存在,make会生成test.o文件,然后再用 test.o 文件声明make的终极任务,也就是执行test文件了。
6. make的依赖性:make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make不执行。
8. make只管文件的依赖性,即,如果在make找到依赖关系之后,冒号后面的文件还是不在,make不执行
9.工程是需要被清理的,像clean这种指令没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
10.一般我们将clean的目标文件设置为伪目标,用 .PHONY 修饰伪目标的特性是,总是被执行的。
11.make指令会判定文件的新旧,判定是否需要重新进行执行依赖关系,进行编译!

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

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

相关文章

CNN(九):Inception v3算法实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制 1 理论基础 Inception v3论文 Inception v3由谷歌研究员Christian Szegedy等人在2015年的论文《Rethinking the Inception Architecture f…

Jmeter集成到jenkins

Jmeter集成到Jenkins Jmeter集成到Jenkins. 1 软件下载... 4 一:环境配置... 4 1.JDK安装&#xff1a;... 4 配置JDK环境变量... 5 2.Jmeter安装&#xff1a;... 5 配置jmeter环境变量... 6 3.安装Ant 7 配置Ant环境变量... 7 4.Git安装&#xff1a;... 8 配置git环境…

Untiy UDP局域网 异步发送图片

同步画面有问题&#xff0c;传图片吧 using System.Text; using System.Net.Sockets; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using System.Net; using System; using System.Threading.Tasks; using Sy…

java内嵌浏览器CEF-JAVA、jcef、java chrome

java内嵌浏览器CEF-JAVA、jcef、java chrome jcef是老牌cef的chrome内嵌方案&#xff0c;可以进行java-chrome-h5-桌面开发&#xff0c;下面为最新版本&#xff08;2023年9月22日10:33:07&#xff09; JCEF&#xff08;Java Chromium Embedded Framework&#xff09;是一个基于…

Cesium 空间量算——生成点位坐标

文章目录 需求分析1. 点击坐标点实现2. 输入坐标实现 需求 用 Cesium 生成点位坐标&#xff0c;并明显标识 分析 以下是我的两种实现方式 第一种是坐标点击实现 第二种是输入坐标实现 1. 点击坐标点实现 //点位坐标getLocation() {this.hoverIndex 0;let that this;this.view…

板子接线图

1.ST-LINK V2接线 2.对抗板子刷蓝牙固件 接USB转TTL&#xff0c;用镊子短接两个孔 2.对抗板子用串口测试蓝牙AT命令 短接白色箭头&#xff0c;接TX&#xff0c;RX&#xff0c;电源

MongoDB【部署 04】Windows系统实现MongoDB多磁盘存储

Windows系统实现多磁盘存储 1.为什么2.多磁盘存储2.1 数据库配置2.2 文件夹磁盘映射2.3 创建新的数据集 3.总结 1.为什么 这里仅针对只有一台Windows系统服务器的情景&#xff1a; 当服务器存储不足时&#xff0c;或者要接入更多的数据&#xff0c;就会挂载新磁盘&#xff0c…

边缘计算AI智能安防监控视频平台车辆违停算法详解与应用

随着城市车辆保有量呈现高速增长趋势&#xff0c;交通拥堵、违章行为也日益泛滥。因为车辆未停放在指定区域导致的车位浪费、占用/堵塞交通要道、车辆剐蹭等问题层出不穷。通过人工进行违法停车的监控&#xff0c;不仅让监控人员工作负荷越来越大&#xff0c;而且存在发现不及时…

Lua学习笔记:词法分析

前言 本篇在讲什么 Lua的词法分析 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题…

SpringAOP补充-通知获取类型

JoinPoint 是 ProceedingJoinPoint 的父类。 getArgs()是JoinPoint获取原方法返回值的函数。 preceed()是ProceedingJoinPoint获取原方法返回值的函数。

【Java】Servlet API

Servlet API HttpServlet核心方法Servlet生命周期 HttpServletRequest核心方法 HttpServletResponse核心方法 HttpServlet 我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法. 核心方法 方法名称调用时机init在 HttpServlet 实…

近三年各领域数字孪生相关政策汇编(可下载)

自2021年国家“十四五”规划纲要提出“探索建设数字孪生城市”以来&#xff0c;国家发展和改革委员会、工业和信息化部、住房和城乡建设部、水利部、农业农村部等部门纷纷出台政策&#xff0c;大力推动数字孪生在千行百业的落地发展。这些政策不仅为数字孪生的应用提供了广阔的…

39 | selenium基础架构,UI测试架构

什么是测试基础架构&#xff1f; 测试基础架构指的是&#xff0c;执行测试的过程中用到的所有基础硬件设施以及相关的软件设施。因此&#xff0c;我们也把测试基础架构称之为广义的测试执行环境。通常来讲&#xff0c;测试基础架构主要包括以下内容&#xff1a; 执行测试的机器…

机器学习第十一课--K-Means聚类

一.聚类的概念 K-Means算法是最经典的聚类算法&#xff0c;几乎所有的聚类分析场景&#xff0c;你都可以使用K-Means&#xff0c;而且在营销场景上&#xff0c;它就是"King"&#xff0c;所以不管从事数据分析师甚至是AI工程师&#xff0c;不知道K-Means是”不可原谅…

MATLAB | R2023b更新了哪些好玩的东西?

R2023b来啦&#xff01;&#xff01;废话不多说看看新版本有啥有趣的玩意和好玩的特性叭&#xff01;&#xff01;依旧把绘图放最前面叭&#xff0c;有图的内容看的人多。。 1 调色板 MATLAB终于不只有一套配色了&#xff0c;诸君且看&#xff1a; y [3 5 7 9 11; 2 5 6 8 1…

uniapp确认提示框;uniapp判断输入框值是否符合正常手机号,身份证号

确认提示框 UniApp 中&#xff0c;你可以使用 uni.showModal 方法来创建确认提示框。以下是一个示例&#xff1a; <template><view class"container"><button click"showAuthModal">显示确认提示框</button></view> </…

【问题记录】解决“命令行终端”和“Git Bash”操作本地Git仓库时出现 中文乱码 的问题!

环境 Windows 11 家庭中文版git version 2.41.0.windows.1 问题情况 在使用 “命令行终端” 和 “Git Bash” 在本地Git仓库敲击命令时&#xff0c;对中文名称文件显示一连串的数字&#xff0c;如下所示&#xff1a;这种情况通常是由于字符编码设置不正确所引起的 解决办法 设置…

什么是分布式锁?他解决了什么样的问题?

相信对于朋友们来说&#xff0c;锁这个东西已经非常熟悉了&#xff0c;在说分布式锁之前&#xff0c;我们来聊聊单体应用时候的本地锁&#xff0c;这个锁很多小伙伴都会用 ✔本地锁 我们在开发单体应用的时候&#xff0c;为了保证多个线程并发访问公共资源的时候&#xff0c;…

网络编程day05(IO多路复用)

今日任务&#xff1a; TCP多路复用的客户端、服务端&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <unistd.h> …

uniapp 内容展开组件

uni-collapse折叠面板并不符合需求&#xff0c;需要自己写一个。 效果展示&#xff1a; 代码&#xff1a; &#xff08;vue3版本&#xff09; <template><view class"collapse-view"><view class"collapse-content"><swiper:autopl…