zoukankan      html  css  js  c++  java
  • Makefile文件(五)_使用变量

    参考原文http://blog.csdn.net/liang13664759/article/details/1771246/

    Makefile中变量如CC++中宏一样执行时候自动原模原样展开在使用的地方,与C/C++不同得失,Makefile中可以改变其值。Makefile中变量可以使用在“目标”,“依赖目标”,“命令”或其他部分。

    变量名可以包含字符数字下划线(可以数字开头),但是不应该含有“:”、“#”、“=”或是空字符,区分大小写。

    一、变量的基础

    声明时需要给予初始值,使用时加上“$”符号,最好用“()”或者“{}”把变量包括起来。而使用真是的“$”需要“$$”表示。

    变量可以用在许多地方,如规则中的目标、依赖、命令以及新的变量。

    二、变量中的变量

    ①使用“=”,左侧是变量,右侧是变量的值,右侧变量的值可以定义在文件的任何一处,也就是说右侧变量不一定是一已定义好的值,也可以使用后面定义的值。

    例如:

    foo = $(bar)

    bar = $(ugh)

    ugh = huh?

    all:

      echo $(foo)

    执行make all会打印出变量$(foo)的值“Huh?”。所以,变量是可以用后面的变量来定义的。

    注:这样可能会产生递归定义:

    A= $(B)

    B=$(A)

    这会让make陷入无限的变量展开过程中去,当然,make有检测这样的能力,并会报错。

    如果变量中使用函数,这也会让make运行时非常慢。他会使用make的“wildcard”和“shell”发生不可预知的错误。

    ②“:=”,前面的变量不能使用后面的变量,只能使用已定义好的变量。

    x:=foo

    y:=$(x) bar

    x:=later

    等价于

    y := foo bar

    x := later

    y := $(x) bar

    x := foo

    那么y的值是“bar”,而不是“foo, bar”

    系统变量“MAKELEVEL”表示,如果make有一个嵌套执行的动作,则该变量会记录当前的Makefile调用层数.

    (以下的我也还没懂,先标记)

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

    nullstring是一个Empty变量,其中什么也没有,而我们的space的值是一个空格。因为在操作符的右边是很难描述一个空格的,这里采用的技术很管用,先用一个Empty变量来标明变量的值开始了,而后面采用“#”注释符来表示变量定义的终止,这样,我们可以定义出其值是一个空格的变量。请注意这里关于“#”的使用,注释符“#”的这种特性值得我们注意,如果我们这样定义一个变量:

    dir := /foo/bar # directory to put the frobs in

    dir这个变量的值是“/foo/bar”,后面还跟了4个空格,如果我们这样使用这样变量来指定别的目录——“$(dir)/file”那么就完蛋了。

    ③、另外的赋值法,“?=”表示如果没有被定义过,则赋值。如果定义过,则什么也不做。

    FOO ?= bar

    等价于:

    ifeq ($(origin FOO), undefined)

    FOO = bar

    endif

    三、变量高级用法

    ①变量值的替换

    替换变量中的共有部分,格式“$(var:a=b)”或是“${var:a=b}”,表示吧变量var中的所有以“a”结尾的“a”替换成“b”

    例如:

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

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

    把“$(foo)”中的所有“.o”结尾全部替换为“.c”,所以“$(bar)”的值就是“a.c b.c c.c”。

    另外一种前面记录过得静态模式,

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

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

    ②、“把变量的值在当成变量”

    x = y

    y = z

    a:=$($(x))

    例子中,$(x)=y, 所以$($(x))就是$(y),于是$(a)的值就是z

    “函数”于“条件语句”一同使用的例子:

    ifdef do_set

      func := sort

    else

      func := strip

    endif

    bar := a b d g q c

    foo := $($(func) $(bar))

    示例中如果定义了"do_sort",foo:=$(sort a d b g q c),于是$(foo)就是“a b c d g q”。如果没有定义“do_sort”,则foo:=$(strip a d b g q c),调用strip函数。

    “把变量的值当成变量”同样可以用在操作符的左边:

    dir = foo

    $(dir)_sources := $(wildcard $(dir)/*.c)

    define $(die)_print

      lpr $($(dir)_sources)#该命令表示把文件发送给打印机

    endef

    四、追加变量

    使用“+=”给变量追加值,如:

    objects = main.o foo.o bar.o utils.o

    objects += another.o

    于是,$(objects)值就变成:“main.o foo.o bar.o utils.o another.o"

    等价于:

    objects = main.p foo.o bar.o utils.o 

    objects := $(objects) another.o

    但“+=”更为简洁,且如果前面没有定义过该变量。“+=”自动变成“=”,如果 有定义过,“+=”汇集成前次操作的赋值符。如果前一次的是“:=”,那么“+=”会以“:=”为其赋值符,如:

    variable := value

    variable += more

    等价于:

    variable := value

    variable := $(variable) more

    但是“=”情况却不一样,例如:

    variable = value

    variable += more

    由于前次的赋值符是“=”,所以“+=”也会以“=”作为赋值,那么岂不会发生变量的递补归定义,这是很不好的,所以make会自动为我们解决这个问题,我们不必担心这个问题。(没懂)

    五、override指示符

    如果有变量是通常的make命令行参数设置,那么Makefile中对这个变量的赋值会被忽略。如果想在Makefile中设置这类参数的值,可使用“override”指示符。

    override <variable>=<value>

    override <variable>:=<value>

    还可以追加

    override <variable>+=<more text>

    对于多行的变量定义,可以使用define指示符,而define指示符前,也同样可以使用override,如:

    override define foo

    bar

    endef

    定义变量foo bar

    六、多行变量

    使用define关键字设置变量的值可以有换行,有利于一系列的命令。(命令包就是利用该关键字)

    define指示符后面跟变量的名字,重起一行定义变量的值,定义以关键字endef结束。工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字或是其他变量。define定义的命令变量中同样要以【Tab】键开头

    define two-lines

      echo foo

      echo $(bar)

    endef

    七、环境变量

    make运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中,但是如果Makefile中定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变量的值将被覆盖(如果make指定了“-e”参数,那么系统环境变量将覆盖Makefile中定义的变量,-e, --environment-overrides环境变量覆盖Makefile文件)

    因此,如果我们在环境变量中设置了“CFLAGS”环境变量,那么我们就可以在所有的Makefile中使用这个变量。这对于使用统一的编译参数很方便。如果Makefile中定义了CFLAGS,那么会使用Makefile中的这个变量,如果没有定义则使用系统的环境变量。

    当make嵌套调用时,上层Makefile中定义的变量会以系统环境变量的方式传递到下层的Makefile中。默认情况下,只有通过命令行设置的变量会被传递。定义在文件中的变量传递需要export。

    不推荐许多的变量定义在系统环境中,这样执行不用的Makefile拥有同一套系统变量,可能会有麻烦。

    八、目标变量

    前面所述的Makefile中定义的变量都是“全局变量”,整个文件中都可以访问这些变量。当然“自动化变量”除外("$<"、“$@”、“$^”)属于“规则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。

     当然,也可以为某个目标设置局部变量,成为“Target-specific Variable”,它可以和“全局变量”同名,因为他的作用范围只在这条规则以及连带规则中,其值也只在作用范围内有效,不会影响规则链以外的全局变量的值。如下:

    <target...>:<variable-assignment>

    <target...>:overide<vatiable-assignment>

    <vatiable-assignment>可以是前面的各种赋值表达式。“=”、“:=”、“+=”、“?=”。第二条是make命令行带入的变量或是系统环境变量。

    示例:

    prog:CFLAGS=-g

    prog:prog.o foo.o bar.o

      $(CC) $(CFLAGS) prog.o foo.o bar.o

    prog.o:prog.c

      $(CC) $(CFLAGS) prog.c

    foo.o:foo.c

      $(CC) $(CFLAGS) foo.c

    bar.o:bar.c

      $(CC) $(CFLAGS) bar.c

    实例中,不管全局的$(CFLAGS)的值是什么,在prog以及所引发的所有规则中(prog.o foo.o bar.o),$(CFLAGS)的值都是“-g”

    九、模式变量

    在GNU的make中,还支持模式变量(Pattern-speific Variable),通过前面,变量可以定义在某个目标上,模式变量的好处就是可以给定一种“模式”,可以把变量定义在符合这种模式的所有目标上。

    示例:%.o:CFLAGS=-o

    <pattern...>:<variable-assignment>

    <pattern...>:override<variable-assignment>

    make命令行指定变量override针对系统环境传入变量。

  • 相关阅读:
    SQL存储过程:取出自定义条数的数据
    删除新闻类别的SQL触发器代码!
    文字上下滚动
    bcp生成excel文件优化方案
    Flickr.net傻瓜教程(一)
    关于jquery的ajax编码的另类解决方案,巨简便
    Flickr.net傻瓜教程(三)打造自己的图片搜索引擎2
    Flickr.net傻瓜教程(二)
    PowerDesigner对列增加注释
    Flickr.net傻瓜教程(三)打造自己的图片搜索引擎
  • 原文地址:https://www.cnblogs.com/weiyi-mgh/p/6986413.html
Copyright © 2011-2022 走看看