[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.xdnf.cn/news/139601.html

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

相关文章

Lua学习笔记:词法分析

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

207.Flink(二):架构及核心概念,flink从各种数据源读取数据,各种算子转化数据,将数据推送到各数据源

一、Flink架构及核心概念 1.系统架构 JobMaster是JobManager中最核心的组件,负责处理单独的作业(Job)。一个job对应一个jobManager 2.并行度 (1)并行度(Parallelism)概念 一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)。这样,包含并行子任…

【方案】浅析AI视频分析与视频监控技术的工厂车间智能化监管方案

一、方案背景 工厂生产车间一般是从原材料到成品的流水作业&#xff0c;有大量器械和物料。为保障车间财产安全并提高生产效率&#xff0c;需要进行全面的监管。在生产制造流水线的关键工序中&#xff0c;不仅有作业过程监管需求&#xff0c;同时&#xff0c;也存在生产发生异…

第七章 查找

一、树形查找-二叉排序树和红黑树 二叉排序树 // 二叉排序树节点 typedef struct BSTNode{ElemType key;struct BSTNode *lchild, *rchild; } BSTNode, *BSTree;五叉查找树 // 5叉排序树的节点定义 struct Node{ElemType keys[4]; // 5叉查找树一个节点最多4个关键字struct…

【二、安装centOS】

下载 地址&#xff1a;https://mirrors.aliyun.com/centos/ 地址 1、https://mirrors.aliyun.com/centos/7.9.2009/ 2、https://mirrors.aliyun.com/centos/7.9.2009/isos/ 3、https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/ 选哪一个 可以选择第一个&#xff0…

Openresty(二十二)ngx.balance和balance_by_lua终结篇

一 灰度发布铺垫 ① init_by_lua* init_by_lua init_by_lua_block 特点: 在openresty start、reload、restart时执行,属于master init 阶段机制&#xff1a; nginx master 主进程加载配置文件时&#xff0c;运行全局Lua VM级别上的参数指定的Lua代码场景&#xff1a; …

java版Spring Cloud+Mybatis+Oauth2+分布式+微服务+实现工程管理系统

鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部工程管…

(二)随机变量的数字特征:探索概率分布的关键指标

文章目录 &#x1f34b;1. 随机变量的数学期望&#x1f34b;1.1 离散型随机变量的数学期望&#x1f34b;1.2 连续型随机变量的数学期望 &#x1f34b;2. 随机变量函数的数学期望&#x1f34b;2.1 一维随机变量函数的数学期望&#x1f34b;2.2 二维随机变量函数的数学期望 &…

基于SpringBoot的网上超市系统的设计与实现

目录 前言 一、技术栈 二、系统功能介绍 管理员功能实现 用户功能实现 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计…

linux升级glibc-2.28

1.准备工作 1.1升级gcc到gcc8 # 安装devtoolset-8-gcc yum install centos-release-scl yum install devtoolset-8 scl enable devtoolset-8 -- bash# 启用工具 source /opt/rh/devtoolset-8/enable # 安装GCC-8 yum install -y devtoolset-8-gcc devtoolset-8-gcc-c devtoolse…

open62541开发:添加sqlite3 历史数据库

历史数据库在OPCUA 应用中十分重要&#xff0c;例如OPCUA 网关和OPCUA 汇聚服务器中都需要历史数据库功能。但是open62541 协议栈中仅包含了基于内存的历史数据库&#xff0c;在实际应用中是不够的。本博文讨论open62541 中添加sqlite3 为基础的历史数据库若干问题。 借鉴 Gi…

某手新版本sig3参数算法还原

Frida Native层主动调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81…

Lua学习笔记:探究package

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

ruoyi框架修改左侧菜单样式

菜单效果 ruoyi前端框架左侧的菜单很丑&#xff0c;我们需要修改一下样式&#xff0c;下面直接看效果。 修改代码 1、sidebar.scss .el-menu-item, .el-submenu__title {overflow: hidden !important;text-overflow: ellipsis !important;white-space: nowrap !important;//…

微软宣布推广数字助理 Copilot;GPT 应用开发和思考

&#x1f989; AI新闻 &#x1f680; 微软宣布推广基于生成式人工智能的数字助理 Copilot 摘要&#xff1a;微软宣布将基于生成式人工智能的数字助理 Copilot 推广到更多软件产品中。新的 AI 助理 Microsoft Copilot 将在 Windows 中无缝可用&#xff0c;包括 Windows 11 桌面…

【C++面向对象侯捷】12.虚函数与多态 | 13.委托相关设计【设计模式 经典做法,类与类之间关联起来,太妙了,不断的想,不断的写代码】

文章目录 12.虚函数与多态举例&#xff1a;委托 继承【观察者模式】13.委托相关设计Composite 组合模式Prototype 原型模式 12.虚函数与多态 纯虚函数 一定要 子类重新定义的 继承和复合 关系下的构造和析构 举例&#xff1a;委托 继承【观察者模式】 13.委托相关设计 问题…

BOM与DOM--记录

BOM基础&#xff08;BOM简介、常见事件、定时器、this指向&#xff09; BOM和DOM的区别和联系 JavaScript的DOM与BOM的区别与用法详解 DOM和BOM是什么&#xff1f;有什么作用&#xff1f; 图解BOM与DOM的区别与联系 BOM和DOM详解 JavaScript 中的 BOM&#xff08;浏览器对…

蓝桥杯 题库 简单 每日十题 day8

01 扫雷 题目描述 在一个n行列的方格图上有一些位置有地雷&#xff0c;另外一些位置为空。 请为每个空位置标一个整数&#xff0c;表示周围八个相邻的方格中有多少个地雷。 输入描述 输入的第一行包含两个整数n&#xff0c;m。 第2行到第n1行每行包含m个整数&#xff0c;相邻整…

数据结构——单链表

目录 一.前言 二.链表表示和实现&#xff08;单链表&#xff09; 1.1 顺序表的优缺点 1.2 链表的概念及结构 1.3 打印函数 1.4 空间函数 1.5 尾插函数&#xff08;最最最麻烦的&#xff09; 1.5.1 尾插最关键部分&#xff01; 1.6 头插函数 1.7 尾删函数…

深拷贝和浅拷贝

两者区别 深拷贝和浅拷贝是用来描述对象或者对象数组这种引用数据类型的复制场景的。 浅拷贝 浅拷贝&#xff0c;就是只复制某个对象的指针&#xff0c;而不复制对象本身。这种复制方式意味着两个引用指针指向被复制对象的同一块内存地址&#xff0c;如下图&#xff1a; 深拷贝…