Linux的make/Makefile和进度
make基本使用
在第一次使用make后在make就不行了,因为.c文件是没有改动的,还是原来的,如果可以一直make,那么就会有bug,因为会产生开销,明明什么没做只是make,所以只有modify时间改变了,才可以make,可以通过stat查看文件的modify。
root@iZbp1be068ksa92vuf0kbdZ:~/zym# vim makefile
root@iZbp1be068ksa92vuf0kbdZ:~/zym# make
gcc -o myproc myproc.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym# ./myproc
hello everyoneroot@iZbp1be068ksa92vuf0kbdZ:~/zym# vim myproc.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym# make
gcc -o myproc myproc.c
root@iZbp1be068ksa92vuf0kbdZ:~/zym# ./myproc
hello everyone
root@iZbp1be068ksa92vuf0kbdZ:~/zym#
Access是查看文件的时间
Modify是记录改变内容的时间
Change是记录属性改变的时间
文件=内容+属性
把内容改了属性也会改变
所以make是通过modify来判断文件是否更新,而.PHONY:clean右边为伪目标,是不受限制的,可以一直clean,还需要知道写在最前面要调用方法是make,而后面就要make加名字。
root@iZbp1be068ksa92vuf0kbdZ:~/zym# stat myproc.c
File: myproc.c
Size: 76 Blocks: 8 IO Block: 4096 regular file
Device: fc03h/64515d Inode: 792311 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-11-25 22:35:16.566692439 +0800
Modify: 2024-11-25 22:35:13.158558491 +0800
Change: 2024-11-25 22:35:13.162558648 +0800
Birth: 2024-11-25 22:35:13.158558491 +0800
root@iZbp1be068ksa92vuf0kbdZ:~/zym#
连续查看是不变的,要过一些时间查看才会变,因为文件被访问会更新时间,导致产生大量IO操作。
推导过程
这里make,会找不到myproc.o文件所以会把实现方法入栈,然后走第二个,但是也找不到myproc.s文件把这个的依赖方法也入栈,后面的也一样,直到最后一个有myproc.c文件,这是走了它的依赖方法,会把栈里面的依赖方法出栈并实现。
1 myproc:myproc.o
2 gcc myproc.o -o myproc
3 myproc.o:myproc.s
4 gcc -c myproc.s -o myproc.o
5 myproc.s:myproc.i
6 gcc -S myproc.i -o myproc.s
7 myproc.i:myproc.c
8 gcc -E myproc.c -o myproc.i
9
10 .PHONY:clean
11 clean:
12 rm -f *.i *.s *.o myproc
13
~
~
-rw-r--r-- 1 root root 76 Nov 25 22:35 myproc.c
-rw-r--r-- 1 root root 17966 Nov 25 22:59 myproc.i
-rw-r--r-- 1 root root 1504 Nov 25 23:00 myproc.o
-rw-r--r-- 1 root root 668 Nov 25 23:00 myproc.s
-rw-r--r-- 1 root root 58 Nov 24 09:47 test.cpp
变量法
BIN :生成的目标文件
CC:编译器
SRC:来源文件
FLAGS:选项
RM:删除操作
¥@:指代BIN %^:指代SRC
变量引用:在 Makefile 的规则中,你可以通过 $(变量名)
的形式来引用变量的值。这种引用方式允许你在规则中使用变量的值。
1 BIN=proc.exe
2 CC=gcc
3 SRC=myproc.c
4 FLAGS=-o
5 RM=rm -f
6
7 $(BIN):$(SRC)
8 $(CC) $(FLAGS) $@ $^
9
10 .PHONY:
11 clean:
12 $(RM) $(BIN)
13
14
15
16
面对多个文件
版本一
%.o:%.c
是把当前路径下的所有.o/.c依次展开,如果都各有100份,那么就会指向100次依赖方法,$<是格式搭配%.o:%.c的。
1 BIN=proc.exe
2 CC=gcc
3 SRC=myproc.c
4 OBJ=myproc.o
5 FLAGS=-c
6 RM=rm -f
7 LFLAGS=-o
8
9 $(BIN):$(SRC)
10 $(CC) $(FLAGS) $@ $^
11
12 %.o:%.c
13 $(CC) $(LFLAGS) $@ $^
14 .PHONY:
15 clean:
16 $(RM) $(BIN)
17
版本二
@可以隐藏执行命令时的信息
1 BIN=proc.exe
2 CC=gcc
3 #SRC=$(shell ls *.c)
4 SRC=$(wildcard *.c)
5 OBJ=$(SRC:.c=.o)
6 LFLAGS=-o
7 FLAGS=-c
8 RM=rm -f
9
10 $(BIN):$(OBJ)
11 @$(CC) $(LFLAGS) $@ $^
12 @echo "linking ··· $^ to $@"
13
14 %.o:%.c
15 @$(CC) $(FLAGS) $<
16 @ehco "compling ··· $< to $@"
17
18
19 .PHONY:clean
20 clean:
21 $(RM) $(OBJ) $(BIN)
22 .PHONY:test
23 test:
24 @echo $(SRC)
25 @echo $(OBJ)
进度条
回车概念:回到所在行的开头
换行概念:换行并继承上一行所在位置
用printf函数打印,如果此时用sleep函数来休眠,则会发生休眠后才打印,不管printf是否在sleep函数前面,代码执行是从上往下的,因为printf会把要打印的字符放到缓冲区里面,程序结束时会自动刷新缓冲区,这时才打印出来,要想不管sleep打印可以用fflush函数,参数为要刷新到那里,可以手动刷新,(显示:显示器只认识字符--字符设备)
进度条代码
process.c
3 #include "process.h"
4 #include <string.h>
5 #include <unistd.h>
6
7 #define NUM 101
8 #define STYLE '='
9
10
11 // verison2
12 void FlushProcess(double total, double current)
13 {
14 char buffer[NUM];
15 memset(buffer, 0, sizeof(buffer));
16 const char *lable="|/-\\";
17 int len = strlen(lable);
18
19 static int cnt = 0;
20
21 // 不需要自己循环,填充#
22 int num = (int)(current*100/total); // 11.0 / 1000
23 int i = 0;
24 for(; i < num; i++)
25 {
26 buffer[i] = STYLE;
27 }
28 double rate = current/total;
29 cnt %= len;
30 printf("[%-100s][%.1f%%][%c]\r", buffer, rate*100, lable[cnt]);
31 cnt++;
32 fflush(stdout);
33 }
~
~
~
~
process.h
1 #pragma once
2 #include<stdio.h>
3
4 void FlushProcess(double total,double current);
~
main.c
1 #include "process.h"
2 #include <stdio.h>
3
4 double total = 1024.0;
5 double speed = 1.0;
6
7 void DownLoad()
8 {
9 double current = 0;
10 while(current <= total)
11 {
12 FlushProcess(total, current);
13 // 下载代码
14 usleep(3000); // 充当下载数据
15 current += speed;
16 }
17 printf("\ndownload %.2lfMB Done\n", current);
18 }
19
20 int main()
21 {
22 DownLoad();
23 DownLoad();
24 DownLoad();
25 DownLoad();
26 //DownLoad();
27 //DownLoad();
28 //DownLoad();
29 //DownLoad();
30 return 0;
31 }
32
~
~
~