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、依赖

      依赖类型

  • 相关阅读:
    学习进度条05
    构建之法阅读笔记03
    子数组和最大值算法
    学习进度条04
    学习进度条03
    定制小学四则运算
    单元测试示例
    构建之法阅读笔记02
    学习进度条02
    decimal扩展方法(转换为字符串,去掉末尾的0)
  • 原文地址:https://www.cnblogs.com/victor-ma/p/5711948.html
Copyright © 2011-2022 走看看