【Linux】自动化构建工具-make/Makefile第一个小程序

news2025/8/10 5:42:11

大家好我是沐曦希💕

文章目录

  • 一.项目自动化构建工具-make/Makefile
    • 1.背景
    • 2. 举例
    • 3. 原理
    • 4. 总结
    • 5. 项目清理
    • 6. 习题
      • 习题一
      • 习题二
  • 二.第一个小程序-进度条
    • 1.行缓冲区
    • 2.倒计时
    • 3.进度条

一.项目自动化构建工具-make/Makefile

1.背景

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

2. 举例

  • 第一步编写一个.c/.cpp文件
vim mycode.cpp

在这里插入图片描述
编写完后退出该文件。

  • 第二步创建一个Makefile文件
vim Makefile

在这里插入图片描述
退出该文件

  • 输入make进行编译
    在这里插入图片描述
    可以看见编写完一个Makefile后,输入make指令后,就会编译你指定要比编译的文件(例:mycode.cpp),生成了对应可执行程序(mycode)。
    这样可以免去写编译指令,完成项目自动化构建。在需要大量编译时候可以节省很多时间,直接一个make命令就能完成了。

那么要删除可执行程序怎么办呢?
在这里插入图片描述
其中 .PHONY:clean 是伪目标,只输入make时候,不会执行.PHONY: 后面的指令,需要make加 .PHONY: 后面的指令才会执行该伪目标。

make clean

在这里插入图片描述
只输入make时候,不会编译也不会显示伪目标
在这里插入图片描述

那么Makefile是怎么实现这些的呢?

3. 原理

Makefile存在意义是为了构建项目的(要做一件事情),那么就需要依赖关系和依赖方法。例如:你问你爸要钱,那么你们之间的依赖关系是你们是父子,表明依赖方法是你爸要给你钱。

所以Makefile内部要写的是:依赖关系和依赖方法。

  • 依赖关系
    在这里插入图片描述
    Makefile的mycode依赖mycode.cpp。mycode是可执行程序,必须由源文件mycode.cpp编译获得。
    所以 mycode:mycode.cpp 是依赖关系。

依赖方法是: g++ mycode.cpp -o mycode
表明可执行程序是由源文件编译获得,提供依赖方法。

注意的是:在写完依赖方法回车到下一行,一个是按[Tab]键,不然会报错。
在这里插入图片描述
.PHONY被关键字修饰的对象是一个伪目标,该目标总是能被执行。
在这里插入图片描述
可见即便mycode不存在了,clean指令依然被执行,不会报错。

甚至.PHONY可以修饰mycode,使编译始终被执行。

 .PHONY:mycode

在这里插入图片描述
在这里插入图片描述
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

如果不用修饰.PHONY修饰mycode,能不能重复执行编译呢?
在这里插入图片描述
在这里插入图片描述
可见不能一直重复编译,报错:

`mycode' is up to date.

意思使mycode已经使最新的了。

  • 那么是什么工具阻止了重复的命令?又是怎么知道不需要再编译的呢?

是g++/gcc阻止该命令。g++/gcc通过比较源文件和可执行程序的Modify时间,如果源文件Modify时间比可执行程序时间新,就会编译,否则不会编译。

  • 查看文件三个时间
stat mycode.cpp
stat mycode

在这里插入图片描述

其中Modif:文件内容被修改的时间
Chang:文件内容属性最新一次被修改时间
Access:文件最后访问时间

那么我们进入到源文件mycode.cpp中后再退出会看到Access和Chang有时候会变化,有时候不会变化,Access一变化那么Chang就会变化,而Modif不会变化。
(注意:退出vim时候,底行模式时候,只能输入q,因为w是保存,相当于更改了文件的内容)
Access显示不是文件最后访问时间吗为什么时变时不变呢?而Chang会随着Access变化而变化呢?
在这里插入图片描述
因为文件操作的时候,文件的访问次数比文件的更改次数多,那么Access时间就会被频繁更改,更改频率太高了;而Access也算文件的属性,Chang记录的是文件内容属性最新一次被修改时间,那么Access被修改了,文件属性就会变化,Chang就会变化。而文件属性是有大小的,而更改Access时间就需要访问磁盘,那么频繁更改Access时间会频繁访问磁盘,效率降低,占用内存增大。
所以对Access时间进行了优化,Access只有在进行访问文件到达一定次数后才更改Access时间。

那么进行mycode.cpp更改后,Modify和Chang时间都会更改。
在这里插入图片描述

那么也可以解释为什么.PHONY修饰下的mycode可以一直执行了,因为它不会对比时间,而是直接执行。

  • Makefile的推导规则
    结合编译链接的知识点,更改mycode:mycode.cpp的写法:
    在这里插入图片描述
    在这里插入图片描述

所以Makefile的推导规则是往下查找,直到找到存在的文件,类似于VS下的调用堆栈,会一直调用直到底层函数,然后一个一个返回。

不过建议直接写成

mycode:mycode.cpp
	g++ mycode.cpp -o mycode

补充:make默认从上往下下扫描,第一个命令可以省略名字,make只生成一个可执行程序,默认为第一个。

4. 总结

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mycode”这个文件,并把这个文件作为最终的目标文件。
  3. 如果mycode文件不存在,或是mycode所依赖的后面的mycode.o文件的文件修改时间要比mycode这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成mycode这个文件。
  4. 如果mycode所依赖的mycode.o文件不存在,那么make会在当前文件中找目标为mycode.o文件的依赖性,如果找到则再根据那一个规则生成mycode.o文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 mycode.o 文件,然后再用 mycode.o 文件声明make的终极任务,也就是执行文件mycode了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

5. 项目清理

  • 工程是需要被清理的
  • 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。

6. 习题

习题一

1.下列关于makefile描述正确的有?
A.makefile文件保存了编译器和连接器的参数选项
B.主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释
C.默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件, 找到了解释这个文件
D.在Makefile不可以使用include关键字把别的Makefile包含进来

答案:ABC

  1. makefile文件中,保存了编译器和链接器的参数选项,并且描述了所有源文件之间的关系。make程序会读取makefile文件中的数据,然后根据规则调用编译器,汇编器,链接器产生最后的输出。根据makefile的功能理解,A选项是正确的
  2. Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释, B选项是正确的
  • 显式规则说明了,如何生成一个或多个目标文件。
  • make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写makefile,比如源文件与目标文件之间的时间关系判断之类
  • 在makefile中可以定义变量,当makefile被执行时,其中的变量都会被扩展到相应的引用位置上,通常使用 $(var) 表示引用变量
  • 文件指示。包含在一个makefile中引用另一个makefile,类似C语言中的include; 根据这一项可以推导D选项是错误的。
  • 注释,makefile中可以使用 # 在行首表示行注释
  • 默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,C选项也正确
  • 根据以上对makefile的理解,可以分析出正确的选项包含:A B C

习题二

2.下列关于make/Makefile描述正确的有?
A.make会生成Makefile中定义的所有目标对象
B.make会自动根据依赖对象检测目标对象是否需要重新生成
C.Makefile中伪对象的功能是目标对象存在则不需要生成
D.Makefile中声明伪对象使用 .PHONY

答案:BD

  • make的执行规则是,只生成所有目标对象中的第一个,当然make会根据语法规则,递归生成第一个目标对象的所有依赖对象后再回头生成第一个目标对象,生成后退出。因此A选项错误。
  • make在执行makefile规则中,根据语法规则,会分析目标对象与依赖对象的时间信息,判断是否在上一次生成后,源文件发生了修改,若发生了修改才需要重新生成。因此B选项正确
  • makefile中的伪对象表示对象名称并不代表真正的文件名,与实际存在的同名文件没有相互关系,因此伪对象不管同名目标文件是否存在都会执行对应的生成指令。伪对象的作用有两个,1. 使目标对象无论如何都要重新生成。2. 并不生成目标文件,而是为了执行一些指令。 根据对伪对象的理解,C选项错误
  • makefile中使用 .PHONY 来声明伪对象, .PHONY: clean。 D选项正确
  • 根据makefile的理解,可以分析出 B D选项正确

二.第一个小程序-进度条

在c语言中’\n’的功能相当于’\r’+‘\n’

  • ‘\r’:回车,即将光标移动到当前行的行首;
  • ‘\n’:换行,即将光标移动到下一行;

C语言中的 ‘\n’ 的作用是 回车 + 换行,而不仅仅是换行,这是沿用老式键盘。

1.行缓冲区

我们知道从键盘输入的字符以及向显示器输出的内容,并不会直接读入或输出,而是会先被存放到输入缓冲区与输出缓冲区中,待缓冲区刷新时数据才会才会被读入或输出;而行缓冲是缓冲区类型的一种,在行缓冲下,当 在输入和输出中遇到换行符时,才执行真正的I/O操作;即我们输入的字符会先存放在缓冲区,等按下回车键时才进行真正的I/O操作。

#include<stdio.h>    
#include<unistd.h>    
int main()    
{    
    printf("you can see me .......");
    sleep(5);
    return 0;                                        
}

在这里插入图片描述
结果是休眠5秒才printf,我们知道先执行的一定是printf,代码是顺序结构的,只不过是数据并没有立即显示出来! 因为先执行printf不一定数据先显示。
可以看到只有休眠5秒后从刷新新的数据,既然printf先执行完成了打印,那么对呀输出的数据在哪里呢?
数据都在缓冲区里面存储,这就是为什么会先睡眠后才把数据显示出来。要把数据立即显示出来,我们直接刷新缓冲区,fflush(stdout) ;或者在在数据后面加上’\n’

#include<stdio.h>    
#include<unistd.h>    
int main()    
{    
    printf("you can see me ......."); 
    fflush(stdout);           
    sleep(5); 
    return 0;
}

在这里插入图片描述

2.倒计时

#include<stdio.h>    
#include<unistd.h>    
int main()    
{    
    int cnt = 10;    
    while(cnt)    
    {    
        printf("剩余时间:%2d\r",cnt);
        cnt--;    
        fflush(stdout); 
        sleep(1);    
    }    
    return 0;    
}

在这里插入图片描述
下面,我们直接来写一个进度条:

3.进度条

创建的文件:
在这里插入图片描述
//Progress.h

#pragma once    
#include<stdio.h>    
#include<unistd.h>    
#include<string.h>    
#define NUM 101    
#define S_NUM 5
extern void ProccessOn();//函数声明

//Progress.c

#include"Progress.h"    
char stype[S_NUM] = {'-','.','#','>','+'};
void ProccessOn()    
{    
    char bar[NUM];    
    memset(bar,'\0',sizeof(bar));    
    const char* lable = "|\\-/";
    int cnt = 0;//循环101次 
    while(cnt <= 100)
    {    
        printf("[%-100s][%-3d%%][%c]\r",bar,cnt,lable[cnt%4]);
        fflush(stdout);    
      	 bar[cnt++] = stype[N];    
        //sleep(1);    
        usleep(50000);
    }
    printf("\n");
}

//main.c

#include"Progress.h" 
int main() 
{
    ProccessOn();
    return 0; 
}

//Makefile

ProccessOn:main.c Progress.c 
    gcc -o ProccessOn main.c Progress.c -DN=3//利用命令行传值,选择进度条的形状
.PHONY:clean
clean:
    rm -f ProccessOn

在这里插入图片描述

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

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

相关文章

使用 elasticdump 跨版本迁移 ES 数据

1、elasticdump 用途介绍 elasticdump 是一个在 Github 开源的 Elasticsearch 的数据迁移工具&#xff0c;项目 Github 地址&#xff1a;[传送门](Github 地址&#xff1a;https://github.com/elasticsearch-dump/elasticsearch-dump) elasticdump 支持跨版本导出和导入数据&am…

【java进阶07:常用类】String类、包装类、日期类Date、数字类、随机数、枚举类型

String类 String类型的字符串存储原理 /*关于java JDK中内置的一个类&#xff1a;java.util.String1、String表示字符串类型&#xff0c;属于引用数据类型&#xff0c;不属于基本数据类型。2、在java中随便使用双引号括起来的都是String对象&#xff0c;例如&#xff1a;"…

零基础上手unity VR开发【配置PC端项目的实时调试】

&#x1f4cc;个人主页&#xff1a;个人主页 ​&#x1f9c0; 推荐专栏&#xff1a;Unity VR 开发成神之路 --【着重解决VR项目开发难&#xff0c;国内资料匮乏的问题。从零入门&#xff0c;一步一个脚印&#xff0c;带你搞定VR开发! &#x1f63b;&#x1f63b;】 &#x1f4d…

聊一聊如何截获 C# 程序产生的日志

一&#xff1a;背景 1.讲故事 前段时间分析了一个dump&#xff0c;一顿操作之后&#xff0c;我希望用外力来阻止程序内部对某一个com组件的调用&#xff0c;对&#xff0c;就是想借助外力实现&#xff0c;如果用 windbg 的话&#xff0c;可以说非常轻松&#xff0c;但现实情况…

当下互联网行业趋势,你顶得住吗?

持续三年的疫情导致经济形式大不如前&#xff0c;特别是互联网行业&#xff0c;不少员工面临着失业的压力&#xff0c;在如此恶劣的大环境下&#xff0c;计算机行业的我们应该如何生存&#xff1f;有一个很好的办法就是 —— 考证&#xff01;&#xff01;&#xff01;如今越来…

多线程与并发 - 常见的几种锁的实现方式

1、悲观锁 正如其名&#xff0c;它是指对数据修改时持保守态度&#xff0c;认为其他人也会修改数据。因此在操作数据时&#xff0c;会把数据锁住&#xff0c;直到操作完成。悲观锁大多数情况下依靠数据库的锁机制实现&#xff0c;以保证操作最大程度的独占性。如果加锁的时间过…

深度学习入门(6)误差反向传播基础---计算图与链式法则

在我的第三篇博文《深度学习入门&#xff08;3&#xff09;神经网络参数梯度的计算方式》中详细介绍了通过微分方式计算神经网络权重参数的梯度。但是数值微分的方式计算梯度效率较低。后续博文会介绍另外一种更加高效的梯度计算方式---误差的反向传播。 这篇文章介绍的是误差…

CorelDRAW2023最新版矢量设计软件

CorelDRAW2023最新版是我比较用的比较好的一款软件&#xff0c;因为其作为一款优秀的矢量设计软件&#xff0c;兼具功能和性能&#xff0c;它是由Corel公司出品的矢量设计工具&#xff0c;被广泛应用于排版印刷、矢量图形编辑、网页设计等行业。CDR软件的优势在于&#xff1a;易…

ROS2 机器人操作系统入门和安装以及如何使用 .NET 进行开发

本文是 ROS2 入门的第一课&#xff0c;简单介绍了 ROS 系统&#xff0c;并演示了 ROS2 系统在 Ubuntu 22.04 中的安装&#xff08;使用 gitee 和清华源&#xff09;以及其中错误的解决。最后对其优势进行总结&#xff0c;为什么选择 ROS。最后介绍简单 Demo 和如何使用 .NET 接…

ThingsBoard源码解析-规则引擎

描述 规则引擎是Thingsboard的核心部分&#xff0c;基于Actor编程模型&#xff0c;类似事件驱动&#xff1b; 每个actor都有自己的消息队列&#xff08;mailBox&#xff09;保存接收到的消息 actor可以创建actor actor可以将消息转发给其他actor 分析 Actor模型实现 系统…

戴尔科技集团通过多云数据保护和安全创新增强网络弹性

中国北京——2022年11月18日 Dell PowerProtect Data Manager软件更新和新一代备份一体机可帮助客户提高运维安全和网络弹性 戴尔多云数据保护解决方案利用内置的安全运维功能加速采用零信任原则 2022年全球数据保护指数(GDPI)调查结果公布 戴尔科技集团(NYSE:Dell)扩大其在数据…

OA系统,有效提升企业办公效率落实执行力

企业管理的成功将最终取决于企业的执行情况&#xff0c;只要有良好的经营管理&#xff0c;管理系统&#xff0c;一个好的领导者&#xff0c;充分调动员工的积极性&#xff0c;将能最大限度的管理执行力。 OA协同办公系统提供了工作流和协同工作互补结合。工作流程严格规定了工作…

PCB铺铜的优点与缺点

PCB设计铺铜是电路板设计的一个非常重要的环节。 什么是PCB铺铜&#xff0c;就是将PCB上无布线区域闲置的空间用固体铜填充。铺铜的意义在于减小地线阻抗&#xff0c;提高抗干扰能力;降低压降&#xff0c;提高电源效率&#xff0c;与地线相连&#xff0c;还可以减小环路面积。 …

基于蛙跳算法求解简单调度问题附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

python与Electron联合编程记录之九(Electron与Flask联合编程实现)

前面铺垫了这么多&#xff0c;这一节就要真正的实现Electron与python联合编程。这一节我通过加法器这个简单的例子来演示如何真正实现Electron和Flask联合编程。 1、安装Axios包 在终端工具选项卡中输入如下命令安装Axios包: npm i --save-dev axios2、项目结构 项目结构如下…

C语言源代码系列-管理系统之家庭财务小管家

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过…

COLMAP输出的文件类型(bin, txt)

默认情况下&#xff0c;COLMAP使用二进制文件格式(bin&#xff0c;机器可读&#xff0c;速度速)来存储稀疏模型。此外&#xff0c;COLMAP也可以将稀疏模型存储为文本文件(txt&#xff0c;人类可读&#xff0c;速度慢)。在这两种情况下&#xff0c;模型导出的信息被分为关于相机…

【吴恩达机器学习笔记】三、矩阵

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

Cygwin安装

Cygwin是一个在Windows平台上运行的类UNIX模拟环境&#xff0c;在其提供的命令行界面中完美地兼容了Windows和Linux的命令行指令&#xff0c;安装和使用教程很容易百度到&#xff0c;可从官网下载安装包&#xff1a;Cygwin官网。安装步骤如下所示&#xff0c;也可自行百度安装方…

web网页设计实例作业HTML+CSS+JavaScript蔬菜水果商城购物设计

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…