1.make和makefile的基本介绍
1.make是一个命令/makefile是一个文件(要自己创建)
makefile内部:
code(目标文件):code.c(依赖文件列表,可以有很多个,也可以一个也没有)//这里叫做依赖关系
//这里是tab键 gcc -o code code.c //这里叫做依赖方法
还有一种:
.PHONY:clean//这里是伪目标
clean://这里是可以有文件的
rm -f code
右边依赖文件列表没有文件或该关系是伪目标时该关系可以被反复执行,否则不行。
[fengyouyinli@VM-0-2-centos lesson]$ make
gcc -o code code.c
[fengyouyinli@VM-0-2-centos lesson]$ make
make: `code' is up to date.
原因:老代码不做重新编译
时间属性中:
1.access:查找文件内容就更新
2.modify:修改文件内容就更新
3.change:修改文件属性就更新
access又有着查找一定次数才更新的特殊情况(防止频繁更新占用大量cpu内存)
此时可以解释了
当code的modify时间在code.c之后时,code的时间比code.c新,此时就无法继续make了,但当code.c发生了更新使其的modify比code新时就可以继续更新了。而依赖文件列表没有文件时,这种比较关系不会发生,自然不会有矛盾。
或该关系是伪目标时,就可以强行忽视时间的矛盾继续make。
(touch的功能本质时修改一个文件的所有时间)
[fengyouyinli@VM-0-2-centos lesson]$ stat code.c
File: 'code.c'
Size: 71 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 666057 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1001/fengyouyinli) Gid: ( 1001/fengyouyinli)
Access: 2026-04-06 12:24:21.978458195 +0800
Modify: 2026-04-06 12:24:20.846453787 +0800
Change: 2026-04-06 12:24:20.846453787 +0800
Birth: -
[fengyouyinli@VM-0-2-centos lesson]$ touch code.c
[fengyouyinli@VM-0-2-centos lesson]$ stat code.c
File: 'code.c'
Size: 71 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 666057 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1001/fengyouyinli) Gid: ( 1001/fengyouyinli)
Access: 2026-04-06 13:03:56.977551872 +0800
Modify: 2026-04-06 13:03:55.102544826 +0800
Change: 2026-04-06 13:03:55.102544826 +0800
Birth: -
makefile中使用#来注释代码
2.依赖关系链与入栈逻辑
code:code.o
gcc code.o -o code
code.o:code.s
gcc code.o -o code.o
code.s:code.i
gcc code.i -o code.s
code.i:code.c
gcc code.c -o code.i
每一个依赖关系当右侧的文件列表不存在时,会先入一个类似于栈的地方,直到右侧的文件列表存在为止,如果走完关系链右侧的文件列表还不存在就会报错。
3.定义变量(和#define很像)
BIN = test#将右侧定义一个新名字
CC = gcc
SRC = test.c
FLAGS = -o
RM = rm -f
$(BIN):$(SRC)
@echo"set $(BIN)"
//@代表后面的内容不打印
$(CC) $(FLAGS) $(BIN) $(SRC)
//$代表里面的内容使用内部变量的数据(类似于解引用)
.PHONY:clean
clean:
$(RM) $(BIN)
echo"remove $(BIN)"
在依赖方式中@永远代表了要被生成的文件,^代表了所有被指定的文件且命令方式是可以有很多行的。
$(BIN):$(SRC)
$(CC) $(FLAGS) $@ $^
// $@为$(BIN) $^为$(SRC)
echo "linking &^ to $@"
//字符内部的也会被替换
%.o:%.c
$(CC) $(FLAGS) $<
//%.c表示makefile所在路径的所有.c文件
//%.o表示所有生成的文件后缀为.o
//$<表示依次将***.c文件转换为***.o(同名文件)
1步可以说一次性的将所有的.o文件转换为可执行文件。
2步可以说一次性将所有的.c文件转换为.o文件。
makefile中也可以执行命令,要加shell前缀(SRC和QBJ都为开头定义的变量名)
SRC = $(shell ls *.c)
SRC = $(wildcard *.c)//这条是特定拿取当前路径所有.c文件的
QBJ = $(SRC:.c=.o)
自动得到SRC.o文件
2.进度条的实现
回车换行是两个动作:回车是回到当前行的第一个字符,换行是去到下一行。
\r回车 \n换行(vim 中的)
fflush():刷新缓冲区的函数(\n也有刷新缓冲区的功能,\r没有)
printf的底层是fprintf(stdout , ...);本质就是向显示器这个文件写入。
usleep():一微秒为单位睡眠。
sleep的头文件为unistd.h.
核心代码:
void flushprint(double current,double total)//从外部传进来,以便实时更新
{
char buffer[101];
//留一个保'\0';
memset(buffer,0,sizeof(buffer);
//实时更新,覆盖之前的字符
const char lable* = "/\-|";
//右侧加载界面
int len = strlen(lable);
static int cnt = 0;
//记录lable的旋转情况
int num = (int)(current*100/total);
for(int a =0;a < num;a++)
{
buffer[a] = '#';
//体现当前的下载情况
}
double rate = current/total;
cnt %= len;
printf("[%-100s][%/lf%%][%c]\r",buffer,rate*100,lable[cnt]);
cnt++;
fllush(stdout);
}