一、项目自动化构建工具 make
和Makefile
1、概览
make
:一条命令
Makefile
:一个文件
如何编译代码,形成可执行程序
[root@hcss-ecs-2ff4 l240807]# touch Makefile
[root@hcss-ecs-2ff4 l240807]# ll
total 4
-rw-r--r-- 1 root root 0 Aug 9 09:33 Makefile
-rw-r--r-- 1 root root 193 Aug 9 09:27 proc.c
[root@hcss-ecs-2ff4 l240807]# vim Makefile
[root@hcss-ecs-2ff4 l240807]# cat Makefile
proc:proc.c
gcc -o proc proc.c
[root@hcss-ecs-2ff4 l240807]# ll
total 8
-rw-r--r-- 1 root root 32 Aug 9 09:35 Makefile
-rw-r--r-- 1 root root 193 Aug 9 09:27 proc.c
[root@hcss-ecs-2ff4 l240807]# make
gcc -o proc proc.c
[root@hcss-ecs-2ff4 l240807]# ll
total 20
-rw-r--r-- 1 root root 32 Aug 9 09:35 Makefile
-rwxr-xr-x 1 root root 8360 Aug 9 09:35 proc
-rw-r--r-- 1 root root 193 Aug 9 09:27 proc.c
在底行模式下,使用
:s
命令进行替换。基本格式如下:
:[range]s/pattern/replacement/[flags]
- 若要在整个文件中进行全局替换,使用
:%s/old/new/g
,其中 old 是旧字符串,new 是新字符串,g 表示全局替换- 若要在特定范围内进行替换,可以指定行号范围。例如,在第 10 行到第 20 行之间替换 “old” 为 “new”
- 如果你想在替换每个匹配项之前都确认一次,可以使用 c 标志
2、重要性和基本语法
【依赖关系】proc:proc.c //依赖文件列表
【依赖方法】 gcc -o proc proc.c //以tab开头
Makefile
本质是依赖关系和依赖方法的集合
.PHONY:clean
声明伪目标(clean
是伪目标名称,可以任取):让目标文件对应的方法总是被执行的
倒数第二行依赖关系,依赖文件列表为空
如果要形成clean
目标文件,就要执行它的依赖方法
@
用于关闭命令显示
依赖方法可以是任意指令
3、基本原理
Makefile
文件,会被make
从上到下开始扫描,第一个目标名,是缺省形成的,如果想执行其他组的依赖关系和依赖方法,make name即可make Makefile
在执行gcc命令时,如果发生了语法错误,就会终止推导过程make
解释Makefile
时是会自动推导的:一直推导,推导过程中不执行依赖方法,直到推导到有依赖文件存在,然后再逆向执行所有依赖方法make
默认只形成一个可执行程序
(1)编译问题
【Q】有时候需要重新编译,有时候不需要,为什么?
【A】根据对比文件各自的ModifyTime实现的
- 可执行程序Mtime比源文件更新,不需要编;
- 源文件Mtime比可执行程序更新,需要重新编
.PHONY:
让依赖方法忽略时间对比,让目标文件对应的方法总是被执行的
rm -f
指令本来就不关心时间,无论加不加.PHONY:
,总是会被执行
修改内容有可能连带着属性也被修改
stat
命令在 Linux 和其他类 Unix 系统中用于显示文件或文件系统的状态信息。这包括文件的大小、权限、所有者、组、最后修改时间等详细信息
语法:stat [选项] 文件...
(2)构建Makefile
//一直推导,推导过程中不执行依赖方法,直到推导到有依赖文件存在,然后再逆向执行所有依赖方法
proc:proc.o
gcc proc.o -o proc
proc.o:proc.s
gcc proc.s -o proc.o
proc.s:proc.i
gcc proc.i -o proc.s
proc.i:proc.c
gcc proc.c -o proc.i
proc:proc.o
gcc proc.o -o proc
%.o:%.c
gcc -c $<
.PHONY:clean
clean:
rm -f proc.o proc
%
Makefile语法中的通配符
%.c
把当前目录下所有的.c文件,展开到依赖列表中
$<
依赖关系:右侧的依赖文件,一个一个地交给gcc -c
选项,形成同名的.o
文件
Makefile
语法中支持定义变量,但没有类型
bin=proc
src=proc.c
$(bin):$(src)
gcc $^ -o $@
.PHONY:clean
clean:
rm -f $(bin)
$^
所有依赖文件列表
$@
目标文件
突破make
只生成一个可执行程序的限制
bin1=proc
src1=proc.c
bin2=code
src2=code.c
.PHONY:all
all:$(bin1) $(bin2)
$(bin1):$(src1)
gcc $^ -o $@
$(bin2):$(src2)
gcc $^ -o $@
.PHONY:clean
clean:
rm -f $(bin1) $(bin2)
二、进度条
1、回车换行
新起一行\r\n
的本质:先回车\r
(回到本行第一个字符),再换行\n
2、缓冲区
(1)引入
#include <stdio.h>
#include <unistd.h>
int main(){
printf("HALO");
sleep(2);
return 0;
}
【Q】先执行printf
还是sleep
?
【A】永远都是先执行printf
,再执行sleep
【Q】在程序执行sleep
2秒期间,字符串在哪里?
【A】输出缓冲区中
\n
强制刷新:行刷新
(2)倒计时
#include <stdio.h>
#include <unistd.h>
int main(){
int count = 9;
while(count>=0){
printf("%d\r", count); // \r回车,但是没有换行,也就没有刷新
count--;
sleep(1);
}
printf("\r\n");
return 0;
}
在printf
下添加fflush(stdout);
强制刷新
【注】显示器没有类型的概念,显示的是一个个字符
printf
要把整数 12345 转换成 1 2 3 4 5 依次显示(格式化输出)
为了确保
10
9
8
...
设置左对齐%-2d
(3)进度条 ver.1
#include <stdio.h>
#include "process.h"
#include <string.h>
#include <unistd.h>
#define NUM 101
#define STYLE '#'
// v1
void Process(){
const char* label = "|/-\\";
int len = strlen(label);
char bar[NUM];
memset(bar,'\0',sizeof(bar));
int cnt = 0;
while(cnt <= 100){
printf("[%-100s][%d%%][%c]\r", bar, cnt, label[cnt%len]);
bar[cnt] = STYLE;
fflush(stdout);
cnt++;
usleep(60000);
}
printf("\r\n");
}