Makefile 详解

Makefile和进度条

Makefile

  • 背景

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

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

    • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。

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

    • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

eg

hello:hello.o 
	gcc hello.o -o hello 
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 hello.i

.PHONY:clean
clean:
 	rm -f hello.i hello.s hello.o hello

Makefile原理

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

    • 什么是modify time -> 这里要引入ACM时间的概念

      candy:~ $  touch test.cc
      candy:~ $  stat test.cc
        File: test.cc
        Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
      Device: fc02h/64514d	Inode: 524168      Links: 1
      Access: (0664/-rw-rw-r--)  Uid: ( 1002/   candy)   Gid: ( 1002/   candy)
      Access: 2024-08-07 17:48:38.762385715 +0800
      Modify: 2024-08-07 17:48:38.762385715 +0800
      Change: 2024-08-07 17:48:38.762385715 +0800
       Birth: 2024-08-07 17:48:38.762385715 +0800
      

    1. 访问时间 (Access Time,简称 atime)

    atime 表示文件上一次被读取或访问的时间。例如,当你使用 cat 命令查看文件内容时,文件的访问时间就会更新。需要注意的是,有些文件系统为了性能考虑,可能会关闭访问时间的自动更新。

    2. 修改时间 (Modification Time,简称 mtime)

    mtime 记录的是文件内容上一次被修改的时间。例如,当你使用编辑器修改并保存文件内容时,文件的修改时间会更新。这个时间仅仅反映文件数据的变动,不包括文件元数据的改变。

    3. 状态改变时间 (Change Time,简称 ctime)

    ctime 反映的是文件状态上一次被改变的时间,包括但不限于文件内容的修改、权限的改变、所有者的改变等。例如,如果你使用 chmod 命令改变文件的权限,文件的 ctime 会更新。需要注意的是,ctime 不会因为文件内容的读取而改变。

Makefile 一些通配符

  • %.o用于统配所有的.o文件,$@用于目标文件 $<用于将依赖文件依次展开 $^用于将所有的依赖文件展开

进度条

缓冲区与输出机制

  • C语言中的标准I/O库(stdio.h)使用了三种缓冲策略:
  1. 全缓冲(Fully Buffered):输出数据会先存储在一个缓冲区中,只有当缓冲区满了或显式调用刷新函数(如fflush)时,才会实际写入输出设备。这种方式常用于文件I/O。
  2. 行缓冲(Line Buffered):这种方式对终端输出特别常见。数据会存储在缓冲区中,直到遇到换行符(\n)或者缓冲区满了,才会刷新并输出。这种方式适用于终端的行输入输出操作。
  3. 无缓冲(Unbuffered):数据直接写入输出设备,而不经过缓冲区。这种方式一般用于错误信息的输出(如stderr)。
  • 缓冲区的刷新时间
  1. 缓冲区满了:当缓冲区中的数据达到其容量时,会自动刷新。

  2. 显式刷新:调用fflush(stdout)函数可以显式刷新标准输出缓冲区。

  3. 程序正常结束:当程序正常结束时(如调用return 0;exit(0);),缓冲区会自动刷新。

  4. 遇到换行符:对于行缓冲,遇到换行符(\n)时会刷新缓冲区。

\r和\n

  • 在c语言中\r表示的是回车,就是将光标移动到最前面的位置,\n代表的是换行,一般的\n都是回车+换行

代码:

using namespace std;

constexpr size_t NUM = 101;
constexpr char TYPE = '#';

int main(){
	char process[NUM];
	string cartoon = "|/-\\";
	size_t sz = cartoon.size();
	//将process的所有元素都置空
	memset(process, '\0', strlen(process));
	for(int i = 0; i < NUM; ++i){
		printf("[%-100s][%d%%][%c]\r",process, i, cartoon[i%sz]);
		process[i] = TYPE;
		fflush(stdout);
		usleep(50000);
	}
	cout << "\r\n";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值