示符。其 语法是:
override
override
当然,你还可以追加:
override
对于多行的变量定义,我们用define指示符,在define指示符前,也同样可以使用ovveri de指示符,如:
override define foo bar endef
六、多行变量
还有一种设置变量值的方法是使用define关键字。使用define关键字设置变量的值可以有
换行,这有利于定义一系列的命令(前面我们讲过―命令包‖的技术就是利用这个关键字 )。
define 指示符后面跟的是变量的名字,而重起一行定义变量的值,定义是以endef关键字
结束。其工作方式和―=‖操作符一样。变量的值可以包含函数、命令、文字,或是其它变
量。因为命令需要以[Tab]键开头,所以如果你用define定义的命令变量中没有以[Tab]键
开头,那么make就不会把其认为是命令。
下面的这个示例展示了define的用法:
define two-lines echo foo echo $(bar) endef
七、环境变量
make 运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中,但是如果M
akefile中已定义了这个变量,或是这个变量由make命令行带入,那么系统的环境变量的值
将被覆盖。(如果make指定了―-e‖参数,那么,系统环境变量将覆盖Makefile中定义的 变量)
因此,如果我们在环境变量中设置了―CFLAGS‖环境变量,那么我们就可以在所有的Make
file中使用这个变量了。这对于我们使用统一的编译参数有比较大的好处。如果Makefile
中定义了CFLAGS,那么则会使用Makefile中的这个变量,如果没有定义则使用系统环境变
量的值,一个共性和个性的统一,很像―全局变量‖和―局部变量‖的特性。
当make嵌套调用时(参见前面的―嵌套调用‖章节),上层Makefile中定义的变量会以系
统环境变量的方式传递到下层的Makefile中。当然,默认情况下,只有通过命
令行设置的
变量会被传递。而定义在文件中的变量,如果要向下层 Makefile传递,则需要使用expro
t关键字来声明。(参见前面章节)
当然,我并不推荐把许多的变量都定义在系统环境中,这样,在我们执行不用的Makefile
时,拥有的是同一套系统变量,这可能会带来更多的麻烦。
八、目标变量
前面我们所讲的在Makefile中定义的变量都是―全局变量‖,在整个文件,我们都可以访
问这些变量。当然,―自动化变量‖除外,如―$<‖等这种类量的自动化变量就属于―规
则型变量‖,这种变量的值依赖于规则的目标和依赖目标的定义。
当然,我样同样可以为某个目标设置局部变量,这种变量被称为―Target-specific Vari
able‖,它可以和―全局变量‖同名,因为它的作用范围只在这条规则以及连带规则中,
所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。
其语法是:
是―?=‖。第二个语法是针对于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-specific Variable),通过上面的目标变量
中,我们知道,变量可以定义在某个目标上。模式变量的好处就是,我们可以给定一种―
模式‖,可以把变量定义在符合这种模式的所有目标上。
我们知道,make的―模式‖一般是至少含有一个―%‖的,所以,我们可以以如下方式给所
有以[.o]结尾的目标定义目标变量:
%.o : CFLAGS = -O
同样,模式变量的语法和―目标变量‖一样:
override同样是针对于系统环境传入的变量,或是make命令行指定的变量。
使用条件判断 ——————
使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支。条件表达式可以
是比较变量的值,或是比较变量和常量的值。
一、示例
下面的例子,判断$(CC)变量是否―gcc‖,如果是的话,则使用GNU函数编译目
标。
libs_for_gcc = -lgnu normal_libs =
foo: $(objects) ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc) else
$(CC) -o foo $(objects) $(normal_libs) endif
可见,在上面示例的这个规则中,目标―foo‖可以根据变量―$(CC)‖值来选取不同的函
数库来编译程序。
我们可以从上面的示例中看到三个关键字:ifeq、else和endif。ifeq的意思表示条件语句
的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括
起。else表示条件表达式为假的情况。endif表示一个条件语句的结束,任何一个条件表达
式都应该以endif结束。
当我们的变量$(CC)值是―gcc‖时,目标foo的规则是:
foo: $(objects)
$(CC) -o foo $(objects) $(libs_for_gcc)
而当我们的变量$(CC)值不是―gcc‖时(比如―cc‖),目标foo的规则是:
foo: $(objects)
$(CC) -o foo $(objects) $(normal_libs)
当然,我们还可以把上面的那个例子写得更简洁一些:
libs_for_gcc = -lgnu normal_libs =
ifeq ($(CC),gcc) libs=$(libs_for_gcc) else
libs=$(normal_libs) endif
foo: $(objects)
$(CC) -o foo $(objects) $(libs)
二、语法
条件表达式的语法为:
其中
第一个是我们前面所见过的―ifeq‖
ifeq (, ) ifeq '' '' ifeq \>\\>\ifeq \>\>' ifeq '' \>\
比较参数―arg1‖和―arg2‖的值是否相同。当然,参数中我们还可以使用make的函数。 如:
ifeq ($(strip $(foo)),)
这个示例中使用了―strip‖函数,如果这个函数的返回值是空(Empty),那么 -empty>就生效。 第二个条件关键字是―ifneq‖。语法是: ifneq (, ) ifneq '' '' ifneq \>\\>\ifneq \>\'' ifneq '' \>\ 其比较参数―arg1‖和―arg2‖的值是否相同,如果不同,则为真。和―ifeq‖类似。 第三个条件关键字是―ifdef‖。语法是: ifdef 如果变量 able-name>同样可以是一个函数的返回值。注意,ifdef只是测试一个变量是否有值,其并 不会把变量扩展到当前位置。还是来看两个例子: 示例一: bar = foo = $(bar) ifdef foo frobozz = yes else frobozz = no endif 示例二: foo = ifdef foo frobozz = yes else frobozz = no endif 第一个例子中,―$(frobozz)‖值是―yes‖,第二个则是―no‖。 第四个条件关键字是―ifndef‖。其语法是: ifndef 这个我就不多说了,和―ifdef‖是相反的意思。 在 开始(不然就被认为是命令)。而注释符―#‖同样也是安全的。―else‖和―endif‖也 一样,只要不是以[Tab]键开始就行了。 特别注意的是,make是在读取Makefile时就计算条件表达式的值,并根据条件表达式的值 来选择语句,所以,你最好不要把自动化变量(如―$@‖等)放入条件表达式中,因为自 动化变量是在运行时才有的。 而且,为了避免混乱,make不允许把整个条件语句分成两部分放在不同的文件中。 使用函数 ———— 在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智 能。make所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,函数的返 回值可以当做变量来使用。 一、函数的调用语法 函数调用,很像变量的使用,也是以―$‖来标识的,其语法如下: $( ${ 这里, 以逗号―,‖分隔,而函数名和参数之间以―空格‖分隔。函数调用以―$‖开头,以圆括 号或花括号把函数名和参数括起。感觉很像一个变量,是不是?函数中的参数可以使用变 量,为了风格的统一,函数和变量的括号最好一样,如使用―$(subst a,b,$(x))‖这样的 形式,而不是―$(subst a,b,${x})‖的形式。因为统一会更清楚,也会减少一些不必要的 麻烦。 还是来看一个示例: comma:= , empty:= space:= $(empty) $(empty) foo:= a b c bar:= $(subst $(space),$(comma),$(foo)) 在这个示例中,$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空格,$( foo)的值是―a b c‖,$(bar)的定义用,调用了函数―subst‖,这是一个替换函数,这 个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个参数是替 换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号,所以$(bar)的值是― a,b,c‖。 二、字符串处理函数 $(subst 名称:字符串替换函数——subst。 功能:把字串 $(subst ee,EE,feet on the s