【Linux】项目自动化构建工具—make/makefile

news2024/11/19 6:29:00

文章目录

  • 1. 什么是make/makefile?
  • 2. make/makefile的使用
    • 2.1 实例代码
    • 2.2 依赖关系和依赖方法
    • 2.3 项目清理
    • 2.4 make是如何确定是否编译的
  • 3. Linux第一个小程序—进度条
    • 3.1 \r 和 \n
    • 3.2 进度条小程序


1. 什么是make/makefile?

make是一个命令工具,是一个解释makefile中指令的命令工具,那么究竟什么是makefile呢?

其实,在一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作作。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

其实,总的来说,make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。


2. make/makefile的使用

2.1 实例代码

这里我们可以先创建一个test.c文件来写一个简单的C语言程序,然后用vim来创建一个Makefile文件(当然了,文件名是makefile也是可以的),Makefile中的内容和test.c中的内容如下:

在这里插入图片描述

接下来我们使用make这个命令来进行编译:

在这里插入图片描述
在这里我们发现使用make指令后,自动帮我们执行了gcc test.c -o mytest这条指令。并且生成了可执行程序mytest,执行mytest这个可执行程序后,内容已经显示到了屏幕上。

下面我们看一下Makefile文件中原理。


2.2 依赖关系和依赖方法

在Makefile文件中有两行内容,第一行内容中的mytesttest.c依赖关系,因为mytest这个文件的生成必然要依赖于test.c的编译。

但是test.c是如何生成mytest的呢?是通过gcc编译器的编译而形成的。而编译所需要的命令就是gcc test.c -o mytest,所以这条命令就是所谓的依赖方法

在这里插入图片描述

下面我们通过上一篇博客讲到的程序翻译的四个阶段来深刻理解一下所谓的依赖关系和依赖方法:

在这里插入图片描述

当我们使用make指令来执行Makefile这个文件时,依赖关系和依赖方法会自上而下展开,mytest依赖于test.o,但是原来的文件中并不存在test.o,所以会继续向下寻找依赖关系,test.o又是依赖于test.s的,但是test.s还是找不到,所以会依次向下寻找依赖关系,直到最后一次test.i依赖于test.c,而test.c却是存在的,所以Makefile会自下而上去执行依赖关系所对应的依赖方法,下面我们用make指令来演示一下这个过程:

在这里插入图片描述


2.3 项目清理

工程是需要被清理的,例如我们在写代码的时候把已经写好的代码编译后生成了可执行程序,但这个可执行程序的执行结果却和我们预想的不一样,那我们就需要将这个可执行程序清理掉,重新编写源代码并生成新的可执行程序,基于这个原因,makefile给我们提供了项目清理工具。

我们可以定义一个clean,这里的clean没有被第一个目标mytest直接或间接依赖,所以clean不会被自动执行:

在这里插入图片描述

我们需要可以在make命令后面跟clean目标作为参数来执行其后所定义的命令。

在这里插入图片描述

.PHONY 伪目标

基于上面的clean,我们可以使用.PHONY来修饰,.PHONY修饰的对象就是伪目标,伪目标的特性是:总是被执行的。

这里我们需要注意的是:.PHONY修饰的一定能被反复执行,而能反复执行的不一定被.PHONY修饰。

在这里插入图片描述

当我们不加.PHONY时,clean依然可以被反复执行。但是我们一般都要给clean加上.PHONY,因为我们不知道目标文件是否已经被删除,所以保证每次都清理一遍。


2.4 make是如何确定是否编译的

我们发现如果我们用make编译过一遍我们需要执行的源程序后,第二遍编译的时候就不能再编译了。

在这里插入图片描述

这里我们发现当我们编译过一遍后,他告诉我们的可执行程序mytest已经是最新的了,所以从第二次开始就不能再编译了。那么make是如何知道我们的可执行程序已经是最新的呢?

其实这是因为存在两条时间线,一条是我们源程序的时间线,另一条是我们的可执行程序形成的时间线。而make呢就是通过这两条时间线上我们源程序和可执行程序最新形成的时间对比来确定是否要进行编译的。

在这里插入图片描述

如果可执行程序最新形成的时间在最新的源程序的时间之后,那么make认为当前的可执行程序是最新的,为了提高效率并不需要执行编译。相反,如果可执行程序最新形成的时间在最新的源程序的时间之前,那么make则认为需要重新进行编译形成新的可执行程序。

当然我们也可以通过touch指令来执行我们的源程序,如果touch的文件不存在那就会新建一个文件,如果要是存在的话,就会将文件的时间更新到最新。

在这里插入图片描述


3. Linux第一个小程序—进度条

3.1 \r 和 \n

‘\n’是我们在学习C语言的过程中经常遇到的转义字符,它的意思是 回车+换行,但其实’\n‘原本的意思仅有换行的意思,只不过是在C语言中将它做了优化,让他既具有回车的功能又具有换行的功能。下面我们看一下\r\n原本的意思。

\r:回车,将光标移动到当前行的行首

\n:换行,直接将光标移动到下一行

这里我们可以先提前看一下\r这种转义字符的效果:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 
  4 int main()
  5 {
  6   printf("hello world\r");
  7   fflush(stdout);//刷新一下缓冲区                                                                                                                                                      
  8   sleep(3);
  9   return 0;
 10 }

在这里插入图片描述


3.2 进度条小程序

首先我们需要先创建三个文件:process.h、process.c、test.c

process.h

  1 #pragma once 
  2 
  3 #include<stdio.h>
  4 
  5 #include<unistd.h>
  6 
  7 #include<string.h>
  8 
  9 #define NUM 101                                                                                                                                        
 10 extern void proccesson();

process.c

    1 #include"process.h"
    2 #define STYLE '='
    3 #define ARR '>'
    4 
    5 void processon()
    6 {
    7   char bar[NUM];
    8   memset(bar,'\0',sizeof(bar));
    9   const char*lable = "|/-\\";
   10   int n = 0;
   11   while(n<=100)
   12   {
   13     printf("[%-100s][%-3d%%][%c]\r",bar,n,lable[n%4]);
   14     fflush(stdout);
   15     bar[n++] =STYLE;
   16     if(n!=100) bar[n]=ARR;
   17 
   18 
   19     usleep(100000);
   20   }
   21   printf("\n");                                                                                                                       
   22 }

test.c

    1 #include"process.h"
    2 
    3 int main()
    4 {
    5    processon();                                                                                                                       
    6   return 0;
    7 }

在这里插入图片描述


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

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

相关文章

【Spring6源码・IOC】Bean的初始化 - 终结篇

前面两篇&#xff0c;我们着重讲解了一下《BeanDefinition的加载》和《bean的实例化》。 这一篇我们来讲解一下bean的初始化。 我们这里的案例依旧是以SpringBoot3.0、JDK17为前提&#xff0c;案例代码如下&#xff1a; Component public class A {Autowiredprivate B b;}Com…

Windows+iis+php+mysql搭建wordpress

准备工作 WindowsServer一台 IIS&#xff0c;在Server上开启 PHP:PHP: Downloads Mysql:MySQL :: MySQL Downloads wordpress下载 | WordPress.org China 简体中文 PHP程序在IIS上以fastcgi方式运行&#xff0c;在安装mysql和php之前确保vc库已安装。 IIS确保开启CGI模块…

JAVA开发(AOP之ProceedingJoinPoint)

我们在开发过程中经常使用到自定义注解来实现在一些类或者方法执行过程中切面&#xff0c;统一实现某些业务操作。例如自定义注解import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang…

YOLOv7:面向实时检测的目标检测器 | 附结构图

YOLOv7 在 5 FPS 到 160 FPS 范围内的速度和准确度都超过了所有已知的目标检测器&#xff0c;并且在 GPU V100 上 30 FPS 或更高的所有已知实时目标检测器中具有最高的准确度 56.8% AP。 YOLOv7-E6 目标检测器&#xff08;56 FPS V100&#xff0c;55.9% AP&#xff09;比基于Tr…

小孩护眼灯什么牌子的好?分享四款最好的台灯品牌

最近发现&#xff0c;在接送我家神兽上下学时&#xff0c;小朋友们会揉眼睛&#xff0c;眼睛始终没睁开的感觉&#xff0c;还有不少小学就戴上了眼镜&#xff0c;我深知戴眼镜&#xff0c;真的很麻烦&#xff0c;所以更加看重孩子的护眼工作。市面上越来越多护眼灯&#xff0c;…

Java高手速成 | 实现人物拼图游戏

拼图游戏指将一幅图片分割成若干拼块&#xff0c;并随机打乱顺序&#xff0c;当将所有拼块都放回原位置时就完成了拼图(游戏结束)。 01、游戏介绍 在游戏中&#xff0c;拼块以随机顺序排列&#xff0c;网格上有一个位置是空的。完成拼图的方法是利用这个空位置移动拼块&#xf…

服务搭建常见问题

怎么将myeclipse项目部署到tomcat服务器 https://www.laike.net/article-162-238315-0.html eclipse提示错误&#xff1a;save could not be completed Dynamic Web Module 4.0 requires Java 1.8 or newer. https://blog.csdn.net/xixihaha_coder/article/details/118345378 …

微星 MPG B460I GAMING EDGE WIFI +i5-10400电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板微星 MPG B460I GAMING EDGE WIFI (MS-7C86)&#xff08;LPC Controller B460芯片组&#xff09;处理器英特尔 Core i5-10400 2.90GHz 六核已驱动内存16 GB ( 芝奇 DDR4 2666MHz 8GB x 2 )已驱动硬盘朗科科技 NVMe SSD 480GB (480 GB / 固态硬盘)已驱动显…

React学习笔记:实用又好用的Hooks函数

React框架以前是采用Class类编程&#xff0c;在类编程中使用生命周期比较方便&#xff0c;但是随着迭代更新&#xff0c;官方开始推荐使用函数式编程&#xff0c;但是函数式编程就没有状态这一个概念&#xff0c;于是乎官方就定义了一系列钩子函数来弥补在这一缺陷&#xff0c;…

Rabbitmq(七) -- rabbitmq的工作模式

1. 简单模式&#xff1a;无需交换机 消息产生消息&#xff0c;将消息放入队列消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失&#xff0c;这里可以设置…

VTK-数据集vtkUnstructuredGrid

前言&#xff1a;本博文主要介绍vtkUnstructuredGrid的特点、结构组成&#xff0c;vtkUnstructuredGrid的创建方法&#xff0c;及其vtkUnstructuredGrid相关的接口及示例。 特点 非结构化网格数据&#xff0c;是最常见的数据集类型&#xff0c;它的拓扑结构和几何结构都是非结…

Pycharm调试功能介绍

文章目录pycharm中的debug模式debug的断点调试pycharm中的debug模式 在pycharm中&#xff0c;一共有4中方法开启debug调试&#xff0c;如下&#xff1a; 点击导航栏的run >> debug 双击打开py文件 >> 右上角点击小虫子图标。 写好if name ‘main’: >> 点…

React 类组件你不知道的细节+案例

React基础-组件-类组件 1.组件概述 目标&#xff1a;了解React组件的作用和创建组件的方式 什么是组件组件的设计思想 1.what is 组件啊&#xff1f; 在前端开发中组件就是用户界面当中一块独立的区域,在组件内部会包含这块区域中的视图代码,样式代码以及逻辑代码 React是采用…

Cadence PCB仿真使用Allegro PCB SI配置差分对的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,配置方法3,总结1,概述 本文简单介绍使用Allegro PCB SI配置差分对的方法。 2,配置方法 第1步:打开待仿真的PCB文件,并确认软件为Allegro PCB SI 如果,打开软件不是Allegro PCB SI则可这样切换 执行Fil…

天下苦“个人公众号认证”久矣,吾闻今可

大家好&#xff0c;我是小悟 一看到个人公众号可以认证&#xff0c;便以迅雷不及掩耳之势准备资料&#xff0c;一顿操作猛如虎后&#xff0c;我的号终于认证啦。 看到别人的个人公众号有认证的&#xff0c;这两天我就在想要怎么才能认证&#xff0c;于是就去搜索相关的内容&am…

电子采购系统的优势是什么 常用的电子采购系统介绍

采购是企业发展中的重要环节之一。在企业采购流程中&#xff0c;并不是简单的完成买和卖就行了&#xff0c;这其中还会涉及到各个方面。例如&#xff0c;在企业采购活动中&#xff0c;常常会遇到供应商数据维护难&#xff0c;采购成本把控难&#xff0c;供应商筛选难等问题。而…

面对集中式缓存实现上的挑战,Redis交出的是何种答卷?聊聊Redis在分布式方面的能力设计

大家好&#xff0c;又见面了。 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容&#xff0c;将会通过系列专题&#xff0c;讲清楚缓存的方方面面。如果感兴趣&#xff0c;欢迎关注以获取后续更新。 在本专栏前面的文章中&#xff0c;我们介绍了各种本地缓存框…

数据结构与算法1—线性表

1. 线性表的定义 线性表L是n&#xff08;n≥0&#xff09;个具有相同属性的数据元素a1&#xff0c;a2&#xff0c;a3&#xff0c;…&#xff0c;an组成的有限序列&#xff0c;其中序列中元素的个数n称为线性表的长度。当n0时称为空表&#xff0c;即不含有任何元素。常常将非空…

express接口

文章目录什么是接口创建 API 路由模块编写 GET 接口编写 POST 接口完整代码CORS 跨域资源共享使用 CORS 中间件解决跨域问题实现 JSONP 接口什么是接口 API (Application Programming Interface&#xff0c;应用程序编程接口 ) 是一些预先定义的函数&#xff0c;目的是提供应用…

TCP/IP 网络模型有哪几层

备注&#xff1a;本文参考小林coding相关内容&#xff0c;侵权请联系作者删除 1.应用层 最上层的&#xff0c;也是我们能直接接触到的就是应用层&#xff08;Application Layer&#xff09;&#xff0c;我们电脑或手机使用的应用软件都是在应用层实现。那么&#xff0c;当两个…