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

简介: Linux项目自动化构建工具-make/Makefile的使用和进度条小程序的实现。

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中的内容如下:

image.png

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

image.png

在这里我们发现使用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,所以这条命令就是所谓的依赖方法

image.png

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

image.png

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

image.png


2.3 项目清理

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

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

image.png

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

image.png

.PHONY 伪目标

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

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

image.png

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


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

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

image.png

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

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

image.png

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

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

image.png


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 }

1.gif


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 }

2.gif


相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
9天前
|
测试技术
自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
本文介绍了如何使用Pytest和Allure生成自动化测试报告。通过安装allure-pytest和配置环境,可以生成包含用例描述、步骤、等级等详细信息的美观报告。文章还提供了代码示例和运行指南,以及重构项目时的注意事项。
43 1
自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
|
9天前
|
测试技术 Python
自动化测试项目学习笔记(四):Pytest介绍和使用
本文是关于自动化测试框架Pytest的介绍和使用。Pytest是一个功能丰富的Python测试工具,支持参数化、多种测试类型,并拥有众多第三方插件。文章讲解了Pytest的编写规则、命令行参数、执行测试、参数化处理以及如何使用fixture实现测试用例间的调用。此外,还提供了pytest.ini配置文件示例。
14 2
|
9天前
|
测试技术 Python
自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法
本文主要介绍了自动化测试中setup、teardown、断言方法的使用,以及unittest框架中setUp、tearDown、setUpClass和tearDownClass的区别和应用。
23 0
自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法
|
13天前
|
Linux C++
Linux c/c++之makefile的基础使用
Linux下C/C++项目中makefile的基本使用,包括基础、进阶和高级用法,以及如何创建和使用makefile来自动化编译过程。
11 0
Linux c/c++之makefile的基础使用
|
2月前
|
Web App开发 编解码 Linux
使用Selenium自动化测试解决报告生成失败问题及Linux部署指南
这篇文章介绍了使用Selenium自动化测试解决报告生成失败问题的方法,包括Linux环境下的部署指南和代码实现。
40 1
使用Selenium自动化测试解决报告生成失败问题及Linux部署指南
|
2月前
|
jenkins 测试技术 持续交付
解锁.NET项目高效秘籍:从理论迷雾到实践巅峰,持续集成与自动化测试如何悄然改变游戏规则?
【8月更文挑战第28天】在软件开发领域,持续集成(CI)与自动化测试已成为提升效率和质量的关键工具。尤其在.NET项目中,二者的结合能显著提高开发速度并保证软件稳定性。本文将从理论到实践,详细介绍CI与自动化测试的重要性,并以ASP.NET Core Web API项目为例,演示如何使用Jenkins和NUnit实现自动化构建与测试。每次代码提交后,Jenkins自动触发构建流程,通过编译和运行NUnit测试确保代码质量。这种方式不仅节省了时间,还能快速发现并解决问题,推动.NET项目开发迈向更高水平。
44 8
|
2月前
|
存储 监控 Linux
|
2月前
|
存储 运维 监控
|
2月前
|
持续交付 C# 敏捷开发
“敏捷之道:揭秘WPF项目中的快速迭代与持续交付——从需求管理到自动化测试,打造高效开发流程的全方位指南”
【8月更文挑战第31天】敏捷开发是一种注重快速迭代和持续交付的软件开发方法,通过短周期开发提高产品质量并快速响应变化。本文通过问题解答形式,探讨在Windows Presentation Foundation(WPF)项目中应用敏捷开发的最佳实践,涵盖需求管理、版本控制、自动化测试及持续集成等方面,并通过具体示例代码展示其实施过程,帮助团队提升代码质量和开发效率。
63 0
|
2月前
|
Java Spring UED
Spring框架的异常处理秘籍:打造不败之身的应用!
【8月更文挑战第31天】在软件开发中,异常处理对应用的稳定性和健壮性至关重要。Spring框架提供了一套完善的异常处理机制,包括使用`@ExceptionHandler`注解和配置`@ControllerAdvice`。本文将详细介绍这两种方式,并通过示例代码展示其具体应用。`@ExceptionHandler`可用于控制器类中的方法,处理特定异常;而`@ControllerAdvice`则允许定义全局异常处理器,捕获多个控制器中的异常。
44 0