Makefile中的变量
1. Makefile中变量的特征:
-
a) Makefile 中变量和函数的展开(除规则命令行中的变量和函数以外),是在 make读取 makefile
文件时进行的,这里的变量包括了使用“=”定义和使用指示符“define”定义的。
b) 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。
c) 变量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的.
d) 变量名是大小敏感的;
e) 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自动化变量。像“$<
”、“$@
”、“$?
”、“$
*”等 -
变量的引用方式:
$(VARIABLE_NAME)
或者${VARIABLE_NAME}
来引用一个变量的定义。 -
书写 Makefile 时,各部分变量引用的格式我们建议如下:
a) make 变量(Makefile 中定义的或者是 make 的环境变量)的引用使用“$(VAR)
”格式,无论“VAR”是单字符变量名还是多字符变量名
b) 出现在规则命令行中 shell 变量(一般为执行命令过程中的临时变量,它不属于Makefile 变量,而是一个 shell 变量)引用使用 shell 的“$tmp
”格式。
c) 对出现在命令行中的 make 变量我们同样使用“$(CMDVAR)” 格式来引用。 -
递归方式扩展的变量。这一类型变量的定义是通过“=”定义的。
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
执行“make”将会打印出“Huh?”。整个变量的替换过程时这样的:首先“$(foo)
”被替换为“$(bar)
”,接下来“$(bar)
”被替换为“$(ugh)
”,最后“$(ugh)
”被替换为“Hug?
”。
整个替换的过程是在执行“echo $(foo)
”时完成的。
-
递归变量的优点:
这种类型变量在定义时,可以引用其他的之前没有定义的变量。
缺点:
使用此风格的变量定义,可能会由于出现变量的递归定义而导致 make 陷入到无限的变量展开过程中,最终使 make 执行失败。这种风格的变量定义中如果使用了函数,那么包含在变量值中的函数总会在变量被引用的地方执行。 -
直接展开式,使用“:=”定义。在使用“:=”定义变量时,变量值中对其他量或者函数的引用在定义变量时被展开。所以变量被定义后就是一个实际需要的文本串,其中不在包含任何变量的引用。
-
和递归展开式变量不同,此风格变量在定义时就完成了对所引用变量和函数的展开,因此不能实现对其后定义变量的引用。
-
使用直接扩展式变量定义我们可以实现将一个前导空格定义在变量值中。一般变量值中的前导空格字符在变量引用和函数进行展开的特点,我们可以实现在一个变量中包含前导空格并在引用此变量时对空格加以保护。
-
在书写Makefile时,推荐将注释书写在独立的行或者多行。
-
“?=”操作符,被称为条件赋值,只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。
FOO ?= bar
其等价于:
ifeq(($origin FOO),undefined)
FOO = bar
endif
如果变量“FOO”在之前没有定义,就给它赋值“bar”。否则不改变它的值;
- override指示符,通常在执行make时,如果通过命令行定义了一个变量,那么它将替代在Makefile中出现的同名变量的定义。如果不希望命令行指定的变量值替代在makefile中的变量定义,那么我们需要在Makefile中使用指示符“override”来对这个变量进行声明。
override VARIABLE = VALUE
- 指示符“override”并不是用来调整Makefile和执行时命令参数的冲突,其存在的目的时为了使用户可以改变或者追加那些使用make的命令行指定的变量的定义。
- “=”和“:=”的区别在于,“:=”只能使用前面定义好的变量,“=”可以使用后面定义的变量。