一、项目自动化构建工具 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】在程序执行sleep2秒期间,字符串在哪里?
【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");
}


322

被折叠的 条评论
为什么被折叠?



