liunx之make/makefile的使用

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);
}
相关推荐
默|笙2 小时前
【Linux】线程概念与控制(4)_线程封装
linux
仍然探索未知中2 小时前
【Linux内核源码分析】内核数据结构
linux·数据结构
chxii2 小时前
linux 下用 acme.sh 搞定 Nginx 免费 SSL 证书自动续期(下) 对于acme.sh命令安装详解
linux·运维·服务器
Bert.Cai2 小时前
Linux more命令详解
linux·运维
minji...2 小时前
Linux 多线程(四)线程等待,线程分离,线程管理,C++多线程,pthread库
linux·运维·开发语言·网络·c++·算法
ZGUIZ3 小时前
Ubuntu 25.10 无法外接显示器解决方案
linux·运维·ubuntu
QJtDK1R5a3 小时前
V4L2 vs GStreamer vs FFmpeg:Linux多媒体处理的三个层级
linux·运维·ffmpeg
倔强的石头1063 小时前
【Linux指南】基础IO系列(四):文件描述符 fd——Linux 文件操作的 “万能钥匙”
linux·运维·服务器
wzb563 小时前
把 Vim 打造成 Nginx 开发 / 调试 IDE(WSL Ubuntu 完整教程)
linux·ide·nginx·ubuntu·vim·c/c++