zoukankan      html  css  js  c++  java
  • [make]makefile使用积累

    【注】:文中所指手册皆为GNU make Version 4.1

     

     1、make的一般特性

    1.1、Makefiles的构成

      Makefiles包含五种元素: 显式规则(explicit rules), 隐式规则(implicit rules), 变量定义(variable definitions),指令(directives), 和注释(comments)。其中没有提到函数,函数应该归于变量之中吧。

    • 显式规则:指导何时和怎样更新一个或多个文件(targets)。
      • 显式规则
    • 隐式规则

    1.2、make如何读入makefile【手册3.7节】

      GNU通过两步完全分离的步骤来完成这项工作。(其实我觉得是三步,因为第一步明显地分成两个阶段)第一阶段(read-in),make读所有相关的makefile(包括include makefiles),建立起其中的变量和规则(makefile就是由变量和规则组成的?);然后构建target和prerequisites的依赖关系;第二阶段(target-update),make利用前一步整理的关系决定哪个target需要重建,从而调用相应的规则。

      make的这种“两步”工作方式决定了变量和函数的两种不同的展开方式:立即展开、延迟展开。立即展开是在第一阶段前期做的,(个人理解就是边读边展开);延迟展开是在第一阶段后期甚至第二阶段才做的(个人理解是在所有makefile都读入以后,整理各变量和规则依赖关系时展开)

    变量赋值

    • immediate = deferred
    • immediate ?= deferred
    • immediate := immediate
    • immediate ::= immediate
    • immediate += deferred or immediate
    • immediate != immediate

    变量名都是理解展开的,变量值则分情况了。

    规则定义(规则都是一种展开方式,不管它是什么形式的)
    immediate : immediate ; deferred
      deferred

    2、变量

    一般规则:

    • 变量是一个字符序列,这个序列绝对不能包含‘:’, ‘#’, ‘=’,和空白这四类字符,除数字、字母、下划线的自它字符也要小心使用;
    • 变量名区分大小写;
    • 变量引用使用变量引用符号'$'加圆括号或大括号。如‘$(foo)’ or ‘${foo}’都是对foo变量的引用;
    • 如果变量名只有一个字符,引用变量时括号可以省去,譬如$x,但官方不建议这样做,这个做法是保留给自动变量使用的;

    两种变量:递归变量、简单变量 (非常重要)

    • 递归展开变量是用“=”符号或define指令定义的变量;
    • 简单展开变量是用‘:=’ or ‘::=’符号定义的变量,这两种符号对GNU是一样的,但POSIX只认‘::=’
    • 简单变量在定义时就对它的值进行展开,而递归变量只有在需要展开时才对它的值进行展开;
    • 递归变量的优点在于它可以引用后面定义的变量,因为它的展开在make读makefile的第二阶段

    【例1】:递归变量与简单变量定义

    3、规则

    3.1、规则一般特性:

    targets(目标) ... : prerequisites (依赖)... ; recipes
      recipes
      ...

    • recipe在prerequisites的下一行以tab键开始(tab键可以使用.RECIPEPREFIX变量的第一个值代替,【手册6.14节】);
    • recipe还可以紧跟在prerequisites的同一行,以“;”分隔。这个方法在定义“空recipe”时非常有效;
    • 规则除了用于编译程序,还能用来干其它事情,见【手册2.7节】;

    3.1、规则分类

    • 规则分显式规则、隐式规则;
    • 隐式规则又分为内建隐式规则(built-in implicit rules)和自定义隐式规则,又叫模式规则(pattern rules)【手册10】;
    • 自定义隐式规则还有一种方法叫后缀规则(Suffix rules)【手册10】;
    • 和模式规则相比,后缀规则有使用限制,但它是老技术,使用它可以保留兼容性【手册10】;
    • 隐式规则可以链式调用(譬如:a.c -> a.y -> a.o)【手册10】;

    3.3、显式规则

    3.4、隐式规则

    • 很多文件的remake工作都是标准的,依照惯例的,所以我们可以不用为这些文件的更新制定规则,这就是隐式规则;
    • 我们想要target使用隐式规则,唯一要做的就是不要给target指定recipe(空recipe规则)甚至不给target写规则;
    • 事实上,很多时候我们要做的是阻止隐式规则发挥作用;

    规则做什么

    规则还能做什么

      

    3.2、Prerequisites

    4、符号

    4.1、@

      @出现在recipe的最前面用于关闭recipe回显,见【手册5.2节】

      $@

    4.2、$

      变量的引用符号

    4.3、通配符

    • 跟Bourne Shell一样,make的通配符也是‘*’, ‘?’ and ‘[...]’(...表示[]中的内容很丰富);
    • 规则中的通配符:targets和prerequisites中的通配符展开是由make来完成的;recipes中的通配符展开则是由shell来完成的;
    • 变量中的通配符make是不展开的;
    • 但含有通配符的变量用在规则中,变量和通配符都会被展开;
    • 要让变量中的通配符生效,可以使用wildcard函数;
    • 文件名中的通配符'*',譬如*.o
      • 代表匹配所有的“o”文件;
      • 如果搜索目录里没有任何一个“o"文件,则“*.o”代表它的字面意思;
      • 如果搜索目录里也没有“*.o”文件(几乎是一定的),则make可能会报错;
    • wildcard函数
      • 可以用于make不进行通配符展开的地方,譬如变量和函数参数;
      • 跟直接使用通配符相比,它也有优势,当没有匹配时它输出空,不会出现使用字面含义的情况;

    【4.3例1】

      objects = *.o

      解释: 由于通配符是在变量的值中,所以这个变量就是字面的意思,而不是代表所有的“o”文件,但是,如果这个变量出现在prerequisites,“*”就是通配符。

    【4.3例2】

      objects := $(wildcard *.o)

    4、依赖

      依赖类型

  • 相关阅读:
    django 项目需要注意的一些点
    VUE之路
    Oracle 表格碎片的查看方法
    RHEL 6.x or 7.x 使用分区绑定ASM 磁盘的方法
    RMAN 修复主库 nologging 操作导致物理备库的坏块
    Oracle 数据库19c 回退降级到 11.2.0.4 方案
    如何评估oracle 数据库rman全备和增量备份大小
    在将Oracle GI和DB升级到19c或降级到以前的版本之前需要应用的补丁 (Doc ID 2668071.1)
    Oracle 数据库坏块处理
    opatch auto 安装11.2.0.4.20190115 PSU遇到 OUI-67133: Execution of PRE script failed,with returen value 1 报错
  • 原文地址:https://www.cnblogs.com/victor-ma/p/5711948.html
Copyright © 2011-2022 走看看