Linux项目自动化构建工具-make/Makefile
目录
- Linux项目自动化构建工具-make/Makefile
- 引言
- 1、make && makefile
- 2、make执行步骤
- 2.1 依赖关系
- 2.2 依赖方法
- 3、项目清理
- 4、伪目标 .PHONY
- 5、文件的三个时间
- 6、make的工作原理
- 7、Linux下的第一个小程序
- 认识缓冲区
- 进度条
- ①函数声明
- ②函数实现
- ③main文件
- ④makefile文件
引言
自动化构建工具
make
/Makefile
是一个备受关注的话题。在现代软件开发中,构建和部署过程越来越复杂,需要更加高效和自动化的工具来帮助开发人员管理项目。Make
/Makefile
就是这样一种工具,它可以通过定义规则和依赖关系来自动化地构建项目。本文将介绍make
/Makefile
的基本概念和工作原理,并探讨其在现代软件开发中的作用。
1、make && makefile
makefile带来的好处就是——自动化编译,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
下面我们通过如下示例来进一步体会它们的作用:
①编写makefile文件
touch makefile
vim makefile
使用vim编辑器编辑makefile
文件:
#makefile文件中的内容
hello.exe:hello.c
gcc hello.c -o hello.exe
.PHONY:clean
clean:
rm -f hello.exe
此时我们只需一个make
命令即可完成自动编译:
make
make
命令的作用,即是执行makefile
中的命令,此处执行的命令是:
gcc hello.c -o hello.exe
当我们输入:
make clean
此处就执行了:
rm -f hello.exe
2、make执行步骤
当我们在Linux中输入并执行make
命令时,make
会干些什么呢?
step 1:
make
会在当前目录下寻找Makefile
文件,找到了就会用这个文件作为后续操作的依据;如果没找到Makefile
,就会寻找名为makefile
的文件;两个都没找到就报错;step 2:找到
Makefile
或者makefile
之后,默认文件中第一行作为第一个目标;make
命令会分析第一个目标的依赖关系,并且执行该目标的依赖方法**;
2.1 依赖关系
hello.exe:hello.c #依赖关系
makefile
文件中hello.exe
就是目标(期望生成的内容);我们编译文件hello.c
,期望生成它对应的可执行文件hello.exe
,而你要编译生成这个目标文件,需要依赖hello.c
这个文件,这就是依赖关系。
2.2 依赖方法
有了依赖关系,我们就知道了生成目标可执行文件hello.exe
需要依赖hello.c
这个文件,那么我们该怎么利用hello.c
文件生成hello.exe
文件呢?我们是不是还缺少一个方法,而这个使用目标的依赖关系文件生成期望的目标文件的方法就是依赖方法。
gcc hello.c -o hello.exe #依赖方法
需要注意的是,依赖文件列表可以为空
3、项目清理
# makefile文件中的清理部分
.PHONY:clean
clean:
rm -f code
上述makefile
文件中,该部分即为项目清理部分;在上述介绍中,我们知道需要显式输入make clean
才能实现清除编译好的文件hello.exe
以便重新编译:
其中.PHONY
的使用,是将它设置为伪目标,伪目标的特性是:总是被执行的❓
4、伪目标 .PHONY
👉 怎样理解总是被执行的?我们试着多次输入make
指令,发现结果如下:
结果:当第一次使用make命令时,目标被执行生成了一个可执行文件,而当我们再使用make命令时发现make虽然不会报错但是会告诉我们生成的文件的已经是最新的了,目标并没有被执行
那么多次输入make clean
指令呢?结果如下:
可以一直执行rm -f hello.exe
这条指令!(即使已经重复执行了)
我们将生成可执行文件过程更改为伪目标(使用vim编辑器):
# 修改makefile文件
.PHONY:hello.exe
hello.exe:hello.c
gcc hello.c -o hello.exe
再测试一下:
👉 One more thing:
make
是怎么知道生成的目标文件是最新的呢❓ ——文件的三个时间
5、文件的三个时间
我们使用
stat
指令查看文件时间属性
stat hello.exe
其中:
Access
:文件最近一次被读取的时间;
Modify
:文件内容最近一次被修改的时间;
Change
:文件的属性最近一次被修改的时间。
因此,被依赖的文件hello.c
的Modify
时间一定比由依赖方法生成的文件hello.exe
的Modify
时间更新!那么此时make
指令即会由新的hello.c
文件生成最新的hello.exe
;
6、make的工作原理
在上文中我们提到过:“需要显式输入
make clean
才能实现清除编译好的文件hello.exe
”,那么我们需要思考的是,若我们只输入make
命令,其执行步骤是什么呢?
make
具有依赖性,make
会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make
就会直接退出,并报错, 而对于所定义的命令的错误,或是编译不成功,make
根本不理。如果在找了依赖关系之后,冒号后面的文件还是不在,那么就停止工作
hello.exe:hello.o
gcc hello.o -o hello.exe
hello.o:hello.s
gcc -c hello.s -o hello.o
hello.s:hello.i
gcc -S hello.i -o hello.s
hello.i:hello.c
gcc -E hello.c -o hell.i
.PHONY:clean
clean:
rm -f hello.exe hello.i hello.s hello.o
其寻找依赖关系过程如下:
7、Linux下的第一个小程序
认识缓冲区
概念引入:\r
和\n
的区别
\r
回车概念:回到当前行的开头。
\n
换行概念:换到下一行。
我们一般用'\n'
代表回车换行
代码示例:
//一下代码在Linux环境中运行
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("hello world!\n"); //行缓冲
sleep(2); //让程序休眠指定秒
return 0;
}
在运行该程序的可执行文件后,"hello world"直接打印于屏幕中,这其实很好理解,因为代码一定是顺序执行的,也就是一定是printf()
先执行打印,然后程序再休眠2秒
然而需要注意的是,我们删除'\n'
换行符后,代码会出现先休眠2秒,再打印输出❓
printf一定先跑完,只不过该数据并没有立即显示出来!对应数据就存储在缓冲区中
我们可以使用fflush
刷新缓冲区:
fflush(stdout);
stdout
的含义是**标准输出流 **,其作用是输出到显示器中:
此时加上fflush
可以看到先打印再休眠,其原理就是刷新缓冲区至显示屏
进度条
设计小程序,我们还是遵循我们的程序设计结构:函数声明文件、函数实现文件、main文件
①函数声明
该文件包含头文件包含、函数声明、宏定义
//process.h
#pragma once
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define NUM 101
#define STYLE '#'
void Process();
②函数实现
进度条的实现,需要按格式输出进度条框架、显示进度条百分比、显示进度条加载时的旋转动画;而“进度增长”的过程本质是一个动态变化的字符串,而由于其具有动态变化的特点,因此我们需要在每次输出后刷新缓冲区(更新屏幕上的内容)
#include "process.h"
const char* str[] = {"/","-","\\","|"};
void Process()
{
int count = 0;
char bar[NUM];
memset(bar, '\0', NUM);
while (count <= 100)
{
printf("[%-100s][%3d%%][%s]\r", bar, count, str[count % 4]);
// 刷新缓冲区
fflush(stdout);
// 更新字符串
bar[count] = STYLE;
count++;
// 休眠
usleep(100000);
}
printf("\n");
}
③main文件
#include "process.h"
int main()
{
Process();
return 0;
}
④makefile文件
ProcessOn.exe:main.c process.c
gcc main.c process.c -o ProcessOn.exe
.PHONY:clean
clean:
rm -f ProcessOn.exe
以上过程在Linux环境下执行如下:
vim process.h
vim process.c
vim main.c
vim makefile
make
./ProcessOn.exe
程序执行如下:
成功实现了进度条!