【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

这篇具有很好参考价值的文章主要介绍了【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、什么是make/makefile

什么是makefile

在我们以后的工作环境中,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

Linux中提供了自动化构建工具–makefile来帮我们解决这个问题,makefifile带来的好处就是——“自动化编译”,makefile一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率

此外,会不会写makefifile,从一个侧面说明了一个人是否具备完成大型工程的能力

什么是make

make是一个命令工具,是一个解释makefifile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefifile都成为了一种在工程方面的编译方法

总结:make是一条命令,makefifile是一个文件,两个搭配使用,完成项目自动化构建

二、如何编写makefile

makefile的编写重要的是编写依赖关系和依赖方法,依赖关系是指一个文件依赖于另一个文件,即我们想到得到一个文件,在目录下我们必须先有的另外一个文件,依赖方法是指如何依赖文件来得到对应的目标文件

我们在编写makefile的时候需要注意一下几点:

1.makefile文件名必须是makefile/Makefile,不能是其他的文件名,否则make无法识别

2.依赖文件可以有多个,也可以没有

3.依赖方法必须以Tab键开头,不能是四个空格

我们以下面的例子来说明如何编写makefile文件

#include <stdio.h>
int main()
{
	printf("hello makefile\n");
    return 0;
}

makefile文件:

test.out:test.c  // 依赖关系
    gcc test.c -o test.out  // 依赖方法
.PHONY:clean //伪目标
clean:
	rm -f test.out

如上,在makefile文件中,test.out 依赖于test.c ,我们以冒号作为分隔符,依赖方法是gcc 编译执行,clear不依赖于任何文件,依赖方法为rm -f指令,其中,.PHONY修饰的clear表示其是一个伪目标,表示它总是被执行

三、make 的工作原理

1.make的使用

在Linux在,我们输入make命令之后,make会在当前目录下找名字叫“Makefifile”或“makefifile”的文件,如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test.c”这个文件,并把这个文件作为最终的目标文件,如果找不到,就会打印提示信息

在我们上面的例子中,makefile中一共有两个目标文件,test.out和clear,如下,我们输入make它会默认执行第一个目标文件,此外,我们也可以指定多个目标文件来让它执行多个目标文件

1.没有编写makefile文件:

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

2.使用一个指令:

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

3.同时使用多个指令

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

2.make的依赖性

我们将上面例子的makefile修改成如下内容:

test.out:test.o
    gcc test.o -o test.out
test.o:test.s
    gcc -c test.s -o test.o
test.s:test.i
    gcc -S test.i -o test.s
test.i:test.c
    gcc -E test.c -o test.i
.PHONT:clean
clean:
	rm -f test.i test.o test.s test.out            

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

我们在输入make指令之后,make会在当前目录找名字叫“Makefifile”或“makefifile”的文件,如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test.out”这个文件,并把这个文件作为最终的目标文件,如果test.out所依赖的test.o文件不存在,那么make会在当前文件中找目标为test.o文件的依赖性,如果

找到则再根据那一个规则生成test.o文件(l类似于栈–后进先出)

如果test.o依赖的文件也不存在,则继续执行该规则,知道找到存在依赖文件的目标文件,得到目标文件之后层次返回形成路径上的其他目标文件,或者最后被依赖的文件找不到,直接退出并报错

这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件

在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理

对于我们上面的例子,test.out依赖的文件test.o不存在,make会去寻找以test.o为目标文件的依赖关系,test.o依赖的test.s也不存在,make会去找以test.s为目标文件的依赖关系,然后test.s依赖test.i,test.i依赖test.c,test.c文件存在,此时,make就会根据test.i的依赖方法形成test.i,层层向上返回,依次形成test.s,test.o,test.out

3.项目清理

工程是需要被清理的,在makefile中,我们使用clean作为项目清理的目标文件,由于项目清理不需要依赖于其他文件,所以clean 也不需要依赖关系

像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的

4…PHONY伪目标

当我们对同一个源文件多次make的时候,我们就会发现第一次程序正常编译,但是第二次之后它就不会再进行编译了,而是提示“make :‘test.out’ is up to date.":

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

但是如果我们将源文件进行修改再进行make的时候,第一次正常进行编译,第二次之后情况还是和上述情况一样

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

实际上,Linux是为了防止我们对已经编译好的并且没有经过修改的文件进行重复编译,从而造成时间的浪费,有人可能会说,我编译一个程序最多几秒中,浪费这一点时间问题不大,但是我们在工作的时候,编译一个程序可能需要几十分钟甚至更久,这时对已经编译好的文件不再进行编译,就会减少很多的时间。对于上面我们的代码,如果test.c已经编译得到了test.out,并且我们对test.c文件没有进行修改,那么我们再次make的时候make就不再执行,即不进行重复编译。

那么make是如何判断源程序不需要重新编译呢?也就是如何判断源文件没有被修改呢?

make会通过比较源文件和目标文件的时间戳来判断是否需要重新编译。如果源文件的时间戳比目标文件的时间戳早,说明源文件没有被修改过,此时make就不需要重新编译。否则,make会重新编译源文件生成新的目标文件

具体来说,make会根据每个源文件生成一个对应的目标文件,然后比较它们的时间戳。如果目标文件不存在,或者其时间戳比源文件早,说明源文件已经被修改过,此时make就需要重新编译。否则,make就认为源文件没有被修改过,不需要重新编译

需要注意的是,如果源文件的修改只是微小的变化,例如修改了注释或空格等,此时make可能无法正确判断是否需要重新编译。为了避免这种情况,可以使用一些工具来生成文件的摘要或哈希值,并将其与目标文件的哈希值进行比较,这样可以更加准确地判断是否需要重新编译

在Linux中,文件一共有三种时间:

1.访问时间(Access):当我们查看文件内容后该时间改变,比如cat,vim,less等等

2.修改时间(Modify):当我们修改文件的内容后该时间改变

3.改变时间(Change):当我们修改文件的属性或者权限的时候该时间改变,比如vim/nano(文件大小改变),chmod/chown/chgrp(文件的权限改变)

但是实际上,我们访问文件的内容不一定会改变文件的访问时间,其原因如下:

1.在Linux下,访问文件内容的操作十分频繁,而修改文件的访问时间需要对文件进行IO操作,如果我们每次访问都修改文件的访问时间,会增大系统的负担

2.一个文件是否能被读取是由文件的权限决定的,而既然文件是可读的,那么说明文件的拥有者/所属组是并不在意我们对文件进行读取,所以也没有必要每次都修改文件的访问时间

3.有些文件系统可能会使用一些优化策略,例如延迟写入(delayed write)或写时复制(copy-on-write),这些策略可能会导致文件的访问时间不及时更新。此外,在某些情况下,文件的访问时间可能会被关闭或禁用

4.为了提高系统性能,Linux内核使用了一些优化策略来减少对文件访问时间戳的更新。例如,内核会将文件的访问时间戳的更新延迟到一定时间后再更新,或者只在文件被关闭时才更新访问时间戳。这样可以减少对文件系统的读写操作,提高系统性能

5.在某些情况下,文件系统可能会禁用访问时间戳的更新,例如使用noatime或nodiratime选项挂载文件系统时,访问时间戳不会被更新。这些选项可以提高文件系统的性能,但会牺牲文件访问时间戳的准确性

访问文件内容不一定会改变文件的访问时间戳,这取决于文件系统的优化策略和挂载选项。但是,在大多数情况下,访问文件内容会导致访问时间戳的更新。

综上所述,Linux下并不会每次访问文件的内容都会更新文件的访问时间,而是积累到一定的访问次数或者积累一段时间才更新

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

而make则是根据可执行程序的修改时间(Modify time)与源文件的修改时间进行对比来判断是否需要重新进行编译

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

make判断源文件是否需要重新编译只与源文件的修改时间有关,与源文件的内容改动无关,我们可以通过touch命令来进行验证,(touch file:如果file已经存在,则更新file的所有时间)

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

我们在了解make是如何判断是否需要重新执行依赖方法形成目标文件之后,.PHONY的原理和作用就显而易见了:被.PHONY修饰的目标文件不根据文件的修改时间来判断是否需要重新执行,从而达到总是被执行的效果

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

我们也同样可以使用.PHONY来修饰test.out,使得test.out每次都被重新编译

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

四、Linux第一个小程序 – 进度条

1.\r&&\n

对于\n相信大家一定会熟悉,因为在C语言中我们经常使用/n来进行换行,但是实际上我们C语言的‘\n’是’\r’+’\n’

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

‘\n’:换行,即将光标移动到下一行

所以我们C语言的’\n’的作用是回车+换行,而不仅仅是换行

2.行缓冲区概念

我们知道,我们从键盘输入的字符以及向显示器输出的内容,并不是直接的读入或者输出,而是会被存放到输入缓冲区和输出缓冲区中,待缓冲区刷新时数据才会被读入或输出

而行缓冲是缓冲区的一种,在行缓冲下,当输入和输出中遇到换行符时,才执行真正的I/O操作,即我们输入的字符会先存放到缓冲区,等按下回车键时才进行真正的I/O操作。我们可以使用两份不同的代码来验证上诉结论:

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

我们可以看到,test1.c的数据printf后并没有直接打印显示到终端上,而是等待程序结束后缓冲区刷新后才显示,而test2.c中的数据由于’\n’可以刷新行缓冲,所以直接打印到了终端

3.进度条

此时,我们就可以运用回车换行的特性以及我们所学了C语言知识来编写一个进度条小程序了

process.h

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

process

#include "process.h"
 // 进度条字符数组
    const char style[S_NUM]={'#','$','*','>','-'};
// 函数的定义 
void ProcessOn()
{
    int cnt=0;
    // 定义字符数组,用于存储进度条显示的字符
    char bar[NUM];
    memset(bar,'\0',sizeof(bar));
    // 旋转光标
    const char* lable = "|\\-/";
    // 循环101次
    while(cnt<=100)
    {
        printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%4];)
        // printf("\033[42;34m[%-100s][%d%%][%c]\033[0m\r",bar,cnt,lable[cnt%4]);
        // 缓冲区刷新
         fflush(stdout);
        // bar[cnt++] = STYLE;                                                                                                                                              
        bar[cnt++] = style[N];         
        usleep(50000);                                                             
    }                                                                                     
   printf("\n");                                     
 }

test.c

#include "process.h"
int main()
{
    ProcessOn();                                                                             return 0;
}

makefile

ProcessOn:process.c test.c
    gcc process.c test.c -o ProcessOn -DN=0                                          .PHONT:clean
clean:
    rm -f ProcessOn

在process.c中,我们每次打印数据之后使用’\r’让光标回到行首,然后刷新缓冲区,再增加bar数组里面的标识字符,这样就可以使我们下一次打印数据时可以直接覆盖之前的数据,并且会增加一个字符的内容,就有就可以实现进度条的效果

同时,为了使进度条更加的真实,我们还增加了一个显示进度的百分比和一个旋转光标,每次打印打印完成之后休眠0.05秒,使得进度条在5秒中之后打印完毕,这样就使得进度条就有了一个加载进度以及一个旋转的符号

usleep函数

usleep函数的一个休眠函数,传入参数的单位是纳秒,而sleep传入参数的单位是秒

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

最后我们了为了丰富进度条字符的样式,我们把进度条字符设置为一个字符数组,我们可以根据我们想要的样式来进行选择,选择时调整N的值即可

此外,我们还可以给输出字符加上颜色。控制颜色的基本格式为:

printf("\033[字背景颜色;字体颜色m字符串\033[0m");
// 比如下面的例子
printf("\033[47;31mhello world\033[5m");

这里有一篇相关的文章,大家有兴趣的可以看一看C语言控制台下printf设置文字颜色和背景色以及实现简单的文字选择菜单

注意:在printf函数中,%具有特殊的意义,所以我们需要输入%%对其进行转义,同样,在lable数组中,字符’\‘也是特殊字符,我们需要输入’\\’

最终我们实现的进度条演示如下:

【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现文章来源地址https://www.toymoban.com/news/detail-467985.html

到了这里,关于【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    🎉博客主页:小智_x0___0x_ 🎉欢迎关注:👍点赞🙌收藏✍️留言 🎉系列专栏:Linux入门到精通 🎉代码仓库:小智的代码仓库 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需

    2024年02月12日
    浏览(63)
  • 【Linux】项目自动化构建工具——make/Makefile及拓展

    1、背景知识 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作 makefile带来的好处就是——“自动化编译”,一旦

    2023年04月27日
    浏览(48)
  • 【Linux】Linux下的项目自动化构建工具——make和makefile

            大家好,好久不见!今天小狮子为大家带来的文章是一篇关于Linux下的项目自动化构建工具——make和makefile的博客,希望能帮助到大家。         当我们进行涉及多文件的工程开发时,我们需要对很多不同类型、不同功能,存在于不同目录下的源文件进行编译操作,

    2024年02月13日
    浏览(49)
  • Linux工具【2】(调试器gdb、项目自动化构建工具make/Makefile)

    在上一篇文章中介绍了Linux中的编辑器vim与编译器gcc与g++: 戳我看vim与gcc详解哦 在本篇文章中将继续来介绍Linux中的工具: 调试器gdb与项目自动化构建工具make/Makefile 在Windows环境中,我们使用vs时,常常会逐过程与逐语句地调试代码以更高效地寻找到错误的位置。在Linux中也

    2024年02月12日
    浏览(51)
  • Linux项目自动化构建工具-make/Makefile以及git三板斧

    是否会写make/makefile,从侧面反映了一个程序员是否具备完成大型工程的能力。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更

    2024年02月16日
    浏览(48)
  • 【Linux】Linux编译器-gcc/g++ && Linux项目自动化构建工具-make/Makefile

    目录 Linux编译器-gcc/g++使用 1.背景知识  Linux中头文件的目录在 Linux 库 条件编译的典型应用 2.gcc如何完成 动态库 vs 静态库 debug release Linux项目自动化构建工具-make/Makefile 背景 用法 特殊符号  预处理(去注释,头文件展开,条件编译,宏替换) 编译(生成汇编) 汇编(生成

    2024年02月20日
    浏览(49)
  • 【Linux】项目自动化构建工具-make和Makefile 的使用和进度条的实现

    什么是makefile 在我们以后的工作环境中,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作 Linux中提供了自动化

    2024年02月07日
    浏览(67)
  • 【Linux】:Linux项目自动化构建工具——make/Makefile || Linux第一个小程序——进度条(简单版本)

    在本章开始给大家分享一个图片 希望对你有帮助 在这里插入图片描述 在开始本章之前 我们需要回顾一下上节课的函数的动静态库的优缺点 动态库的优点: 比较节省资源(这里说的资源不仅仅是磁盘资源 也包括网络资源 内存资源等等),不会出现太多的重复代码 缺点:对

    2024年02月05日
    浏览(43)
  • 【探索Linux】—— 强大的命令行工具 P.6(调试器-gdb、项目自动化构建工具-make/Makefile)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,今天博主带大家了解一下 —— Linux系统下的调试

    2024年02月12日
    浏览(38)
  • 【Linux】--- Linux编译器-gcc/g++、调试器-gdb、项目自动化构建工具-make/Makefile 使用

    格式: gcc [选项] 要编译的文件 [选项] [目标文件] , gcc / g++ 安装: sudo yum install -y gcc-c++ 。安装后的编译器默认的版本是较低的,我们可以 使用选项 -std=c99 (即使用c99标准), -std=c++11 (即使用c++11的标准)来进行版本提升 。使用 -o 选项,可以将编译生成的可执行重命名

    2024年03月10日
    浏览(103)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包