zoukankan      html  css  js  c++  java
  • Makefile学习(一)变量

    鉴于之前有一些了解,还有自己的学习习惯,我一上来就看Makefile的变量这一章。主要脉络是根据GNU make中文手册。

    第六章:Makefile中的变量

    6使用变量

    定义:变量是一个名字,代表一个文本字符串;类似C语言中的宏

    区别在于这个变量在Makefile的目标、依赖、命令中引用的地方会被它的值所取代;

    特征:1.Makefile中变量和函数的展开(除了规则命令行)是在make读取makefile文件时进行的;

    2.变量可用于代表:一个文件名列表、编译选项列表、程序运行的选项参数列表(CFLAGS,LDFLAGS等等)、搜索源文件的目录列表、编译输出的目录列表以及任何能想象出的数据;

    3.变量名不包括“:”“#”“=”、前置空白和尾空白的任何字符串。注意:尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的字符可能会在make后续版本中被赋予特殊含义,并且这样命名的变量对于一些shell来说是不能被作为环境变量来使用的。

    4.变量名大小写敏感;推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表 objects)使用小写方式,而对于一些参数列表(例如:编译选项 CFLAGS )采用大写方式,但这并不是要求的。需要强调一点:对于一个工程,所有Makefile 中的变量命名应保持一种风格,否则会显得你是一个蹩脚的程序员(就像代码的变量命名风格一样)。

    5.另外有一些变量名只包含了一个或者很少几个特殊字符,称为自动化变量,$<,$@,$?,$*

    6.1变量的引用

    引用方式:$(变量名),${变量名}

    例子:objects = program.o foo.o utils.o

       program : $(objects)

          cc -o program $(objects)

       $(objects):defs.h

    一般在我们书写Makefile 时,各部分变量引用的格式我们建议如下:
    1. make变量(Makefile 中定义的或者是make的环境变量)的引用使用“$(VAR)”
    格式,无论“VAR ”是单字符变量名还是多字符变量名。
    2. 出现在规则命令行中shell变量(一般为执行命令过程中的临时变量,它不属于
    Makefile 变量,而是一个shell变量)引用使用shell的“$tmp”格式。

    3. 对出现在命令行中的make变量我们同样使用“$(CMDVAR)” 格式来引用。

    例子:

    SUBDIRS:=src foo

    .PHONY:subdir

    Subdir:

      @for dir in $(SUBDIRS);do

        $(MAKE) -C $$dir || exit 1;

      done

    这里的MAKE就是引用

    6.2两种变量定义(赋值)

    这两种风格的区别:1.定义方式2.展开时机

    6.2.1递归展开式变量

    使用”=“或者”define“定义,这种变量的引用是严格的文本替换过程,如果此变量定义中存在对其他变量的引用,这些被引用的变量会在它被展开的同时被展开;

    例子:

    foo=$(bar)

    bar=$(ugh)

    ugh=Huh?

    all:;echo $(foo)

    执行make将会打印HUh?

    优点是:这种类型变量在定义时,可以引用其他之前没有定义的变量;

    缺点是:由于出现变量的递归定义导致make陷入到无限的变量展开中,最终使make执行失败;

        如果使用了函数,在包含在变量值中的函数总会在变量被引用的地方执行:使make执行    效率降低,如果引用了”shell“”wildcard“函数,可能出现不可控制和难以预料的错误;

    6.2.2直接展开式变量

    这种风格的变量使用”:=“定义,这种方法使用中对其他变量或者函数的引用在定义变量时才被展开,因此例子如下:

    x:=foo

    y:=$(x) bar

    x:=later

    就等价于:

    y:=foo bar

    x:=later

    不能实现对其后定义变量的引用。

    6.2.3定义一个空格

    一般变量值中的前导空格字符在变量引用和函数调用时被丢弃。

    例子:

    nullstring:=

    space:=$(nullstring) #end of the line

    在space定义行中的注释使得我们的目的更清晰,注释和变量引用之间存在一个空格。

    以”nullstring“开始,采用”#“注释来结束,中间是一个空格字符;

    因此在定义变量时也要注意,没有空格的变量就不要把空格包含进去;

    例子:

    dir :=/foo/bar     #...

    这个变量本身没有空格,你把它包含空格了。

    6.2.4”?=“操作符

    这是条件赋值。

    FOO?=bar

    等价于:

    ifeq($(origin FOO),undefined)

    FOO =bar

    endif

    含义:如果FOO在之前没有定义,就给他赋值,否则不改变它的值;

    6.3变量的高级用法

    6.3.1变量的替换引用

    $(VAR:A=B),将VAR变量中所有A字符结尾的字替换为B结尾的字,对于其他部分的A不进行替换

    例子:foo:=a.o b.o c.o

    bar:=$(foo:.o=.c)

    变量的替换引用其实是函数”patsubst“的一个简化实现。另一种引用替换使用功能更强的函数。

    例子:foo:=a.o b.o c.o

    bar:=$(foo:%.o=%.c)

    和第一种实现功能一样,但是更通用。

    6.3.2变量的嵌套引用

    一个变量名之中可以包含对其他变量的引用,这就是”变量的嵌套引用“

    例子:

    x=y

    y=z

    a:=$($(x))

    6.4变量取值

    override

    赋值方式

    将变量设置为系统环境变量

    自动化变量

    隐含变量

    6.5如何设置变量

    就是定义,注意一些情况;

    6.6追加变量值

    使用”+=“来实现对一个变量值的追加操作。

    6.7override指示符

    执行make时,如果通过命令行定义了一个变量,则它将替代Makefile中出现的同名变量的定义。

    如果不希望命令行指定的变量值替代在Makefile中的变量定义,则需要使用override来对变量进行声明。

    override VARIABLE:=VALUE

    例子:

    无论命令行指定哪些编译参数,编译时必须打开-g,那么在在Makefile中bCFLAGS应该定义为:override CFLAGS+=-g

    6.8多行定义

    define 。。

    。。

    。。

    endif

    6.9系统环境变量

    make在运行时,系统中的所有环境变量对它都是可见的。在 Makefile 中,可以引
    用任何已定义的系统环境变量。

    例如CFLAGS,SHELL

    我们不推荐使用环境变量的方式来完成普通变量的工作,特别是在make 的递归调用
    中。任何一个环境变量的错误定义都对系统上的所有make产生影响,甚至是毁坏性的。

    6.10目标指定变量

    设置一个目标指定变量的语法为:

    TARGET ... : VARIABLE-ASSIGNMENT

    或者:

    TARGET ... : override VARIABLE-ASSIGNMENT 

    另外当使用make的“-e ”选项时,同名的环境变量

    也将覆盖目标指定的变量定义

    6.11模式指定变量

    设置一个模式指定变量的语法和设置目标变量的语法相似:

    PATTERN ... : VARIABLE-ASSIGNMENT

    或者:

    PATTERN ... : override VARIABLE-ASSIGNMENT

  • 相关阅读:
    VIM的强大功能
    BigDecimal.ROUND_HALF_XXX的各种用法
    拒绝服务攻击
    浅谈(接口)测试注意事项四
    jmeter 与 java http
    Xms Xmx PermSize MaxPermSize 区别
    Jquery过滤器
    JQ工具函数运用
    C#扩展方法
    LINQ TO XML基础
  • 原文地址:https://www.cnblogs.com/preorder69/p/3669678.html
Copyright © 2011-2022 走看看