Linux —— 自动化构建工具make/makefile

makefile

  • 定义了一系列编译规则的文档,使用make命令可“自动编译”,极大提供开发效率;
  • 一个工程中,源文件按类型、功能、模块会分别存放在若干个目录中,哪些文件需先编译、哪些文件需后编译、哪些文件需重新编译,甚至更复杂的功能操作,均可在makefile中指定;

make

  • 是一个解释makefile中指令的命令工具,大多数IDE都有此命令;
  • 执行make时,会在当前目录下搜索makefile,找到目标及其依赖,然后执行相关命令;
[wz@VM-4-4-centos ~]$ which make
/usr/bin/make
[wz@VM-4-4-centos ~]$ whereis make
make: /usr/bin/make /usr/share/man/man1/make.1.gz
[wz@VM-4-4-centos ~]$ whatis make
make (1)             - GNU make utility to maintain groups of programs

GNU make工作流程

  • 读入主makefile,主makefile中可引用其他makefile;
  • 读入被include的其他makefile;
  • 初始化文件中的变量;
  • 推导隐含规则,并分析所有规则;
  • 为所有目标文件创建依赖关系链;
  • 根据依赖关系,决定哪些文件需要重新生成;
  • 执行命令;

makefile规则

基本格式

target : prerequisites 
    [前缀]command
//或
target : prerequisites; command 
    [前缀]command
  • target,目标文件(可以是object file,也可是可执行文件,还可为标签);
  • prerequisites,生成目标文件所依赖的文件或目标(可以多个,或没有);
  • command,make时执行的命令(任意shell命令,可以有多条);
  • [前缀]
    • 不加,打印命令及命令结果,出错停止执行;
    • @,只打印命令结果,出错停止执行;
    • -,忽略命令出错,继续执行;

显示规则:说明如何生成一个或多个目标文件(包括生成的文件、依赖的文件,命令);

隐含规则:make自动推导功能所执行的规则;

变量定义:makefile中定义的变量;

文件指示:makefile中引用的其他makefile,指定makefile中有效部分,定义一个多行命令;

注释:行注释“#”,转义注释符“\#”;

工作流程

  • make,默认执行第一个目标;
  • target不存在,会依据其规则创建;
  • target存在,其依赖src比target“更新”,会重新编译;
  • target存在,其依赖src不比target“更新”,什么都不做;

通配符

  • *,表示零个或任意个字符;
  • ?,表示任意一个字符;
  •  ex. [abcd] ,表示a,b,c,d中任意一个字符;
  • [^abcd],表示除a,b,c,d以外的字符;
  • [0-9],表示 0~9中任意一个数字;
  • %,匹配任意字符;
  • ~,表示家目录;

变量定义及赋值

  • VAR_LIST =  val1 val2 val3 ...
  • :=,简单赋值;
  • =,递归赋值;
  • ?=,条件赋值;
  • +=,追加赋值;

自动化变量

  • $@,目标文件名;
  • $<,第一个依赖文件名;
  • $^,所有依赖文件列表;
  • $?,所有比目标文件新的依赖文件列表;

搜索路径

  • 默认在makefile当前路径下搜索源文件;
  • 特殊变量VPTH,可指定路径;
    • VPATH ,当前目录未找到,则会在此目录下查找;
    • VPATH  ,符合pattern格式的文件,在此目录下查找;
    • VPATH ,清除符合pattern格式的文件查找目录;
    • VPATH,清除查找目录; 
  • 关键字vpth,可指定路径;
    • VPATH  ,符合pattern格式的文件,在此目录下查找;
    • VPATH ,清除符合pattern格式的文件查找目录;
    • VPATH,清除查找目录; 
//当前目录未找到会在../dir1和../dir2中查找
VPATH = ../dir1 : ../dir2 
VPATH = ../dir1 ../dir2 
vpath ../dir1 : ../dir2 //当前目录未找到会在../dir1和../dir2中查找
vpath %.d ./header //以.h结尾的文件都从./header内查找
vpath %d //清除.h结尾的文件的查找规则
vpath //清除所有查找规则

Linux —— 自动化构建工具make/makefile_第1张图片

隐含规则

[wz@VM-4-4-centos ~]$ ls
makefile  src.c
[wz@VM-4-4-centos ~]$ cat makefile 
target:src.o
	gcc $^ -o $@
[wz@VM-4-4-centos ~]$ make
cc    -c -o src.o src.c
gcc src.o -o target
[wz@VM-4-4-centos ~]$ ls
makefile  src.c  src.o  target

上述makefile文件缺少生成src.o命令,但make后,依然可生成src.o、target,是因为隐含规则的作用;

执行make的过程中,找到隐含规则,提供此目标的基本依赖关系,确定目标的依赖文件和使用命令;隐含规则提供的依赖文件只是基本的文件,需增加依赖文件时则要额外给出;

target:src.o
	gcc $^ -o $@
target:src.h

条件判断

  • ifeq,判断参数是否相等,相等为true;
    • ifeq(arg1,arg2)
  • ifneq,判断参数是否不相等,不相等为true;
    • ifneq(arg1,arg2)
  • ifdef,判断是否有值,有值为true;
    • ifdef variablename
  • ifndef,判断是否无值,无值为true;
    • ifndef variablename
[wz@VM-4-4-centos tmp]$ cat makefile 
arg = no
all:
ifeq ($(arg),yes)
		@echo $(arg)=yes	
else
		@echo $(arg)=no
endif
[wz@VM-4-4-centos tmp]$ make
no=no

伪目标

  • 伪目标即并非一个目标,不生成目标文件;
  • 声明伪目标即将目标作为.PHONY的依赖;
    • 如.PHONY:clean
    • 不加此声明可能会与真正目标文件产生冲突
.PHONY:clean
clean:
    rm -rf *.o test

案例

倒计时

原位置刷新数字

  • 刷新方式
    • 直接刷新,不缓冲;
    • 缓冲区写满,在刷新,即全缓冲;
    • 遇到\n刷新,行刷新;
    • 强制刷新,fflush(stdout);
  1 #include
  2 #include
  3 
  4 int main()
  5 {
  6   int count = 10;
  7   while(count >= 0)                                                                                     
  8   {
  9      printf("%2d\r",count);
 10      fflush(stdout);
 11      count--;
 12      sleep(1);
 13   }
 14      return 0;
 15 }

进度条

  1 #include
  2 #include
  3 #include
  4 
  5 #define NUM 100
  6 
  7 int main()
  8 {
  9   int i = 0;
 10   char bar[NUM+2];                                                                                                         
 11   memset(bar,0,sizeof(bar)); 
 12   const char* label = "|/-\\";
 13   while(i<=NUM)
 14   {
 15     bar[i] = '#';
 16     printf("[%-101s][%d%%][%c]\r",bar,i,label[i%4]);
 17     fflush(stdout);
 18     i++;
 19     usleep(100000);
 20   }
 21   printf("\n");
 22   return 0;
 23 }

你可能感兴趣的:(操作系统,linux)