当前位置:   article > 正文

Linux —— 自动化构建工具make/makefile_使用自动生成工具生成makefile

使用自动生成工具生成makefile

目录

一,GNU make工作流程

二,makefile规则

基本格式

工作流程

通配符

变量定义及赋值

搜索路径

隐含规则

条件判断

伪目标

三,案例

倒计时

进度条


makefile

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

make

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

一,GNU make工作流程

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

二,makefile规则

基本格式

  1. target : prerequisites
  2. [前缀]command
  3. //或
  4. target : prerequisites; command
  5. [前缀]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 <directories> ,当前目录未找到,则会在此目录下查找;
    • VPATH <pattern> <directories>,符合pattern格式的文件,在此目录下查找;
    • VPATH <pattern>,清除符合pattern格式的文件查找目录;
    • VPATH,清除查找目录; 
  • 关键字vpth,可指定路径;
    • vpth <pattern> <directories>,符合pattern格式的文件,在此目录下查找;
    • vpth <pattern>,清除符合pattern格式的文件查找目录;
    • vpth,清除查找目录; 
  1. //当前目录未找到会在../dir1和../dir2中查找
  2. VPATH = ../dir1 : ../dir2
  3. VPATH = ../dir1 ../dir2
  1. vpath ../dir1 : ../dir2 //当前目录未找到会在../dir1和../dir2中查找
  2. vpath %.d ./header //以.h结尾的文件都从./header内查找
  3. vpath %d //清除.h结尾的文件的查找规则
  4. vpath //清除所有查找规则

隐含规则

  1. [wz@VM-4-4-centos ~]$ ls
  2. makefile src.c
  3. [wz@VM-4-4-centos ~]$ cat makefile
  4. target:src.o
  5. gcc $^ -o $@
  6. [wz@VM-4-4-centos ~]$ make
  7. cc -c -o src.o src.c
  8. gcc src.o -o target
  9. [wz@VM-4-4-centos ~]$ ls
  10. makefile src.c src.o target

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

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

  1. target:src.o
  2. gcc $^ -o $@
  3. target:src.h

条件判断

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

伪目标

  • 伪目标即并非一个目标,不生成目标文件,且总是可执行的;
    • make,如源文件没有更新,只执行一次;
  • 声明伪目标即将目标作为.PHONY的依赖;
    • 如.PHONY:clean;
    • 不加此声明可能会与真正目标文件产生冲突;
  1. //被.PHONY修饰的目标,均是总是可执行的
  2. .PHONY:clean
  3. clean:
  4. rm -rf *.o test

三,案例

倒计时

        原位置刷新数字;

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

进度条

注,可能打印的是多行,把终端窗口宽度调大即可打印为一行;

printf,有颜色控制;

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/965539
推荐阅读
相关标签
  

闽ICP备14008679号