makefile(条件语句)

7 makefile文件的条件语句

一个条件语句可以导致根据变量的值执行或忽略makefile文件中一部分脚本。条件语句可以将一个变量与其它变量的值相比较,或将一个变量与一字符串常量相比较。条件语句用于控制make实际看见的makefile文件部分,不能用于在执行时控制shell命令。

7.1条件语句的例子

下述的条件语句的例子告诉make如果变量CC的值是‘gcc’时使用一个数据库,如不是则使用其它数据库。它通过控制选择两命令行之一作为该规则的命令来工作。‘CC=gcc’作为make改变的参数的结果不仅用于决定使用哪一个编译器,而且决定连接哪一个数据库。
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
该条件语句使用三个指令:ifeq、else和endif。
Ifeq指令是条件语句的开始,并指明条件。它包含两个参数,它们被逗号分开,并被扩在圆括号内。运行时首先对两个参数变量替换,然后进行比较。在makefile中跟在ifeq后面的行是符合条件时执行的命令;否则,它们将被忽略。
如果前面的条件失败,else指令将导致跟在其后面的命令执行。在上述例子中,意味着当第一个选项不执行时,和第二个选项连在一起的命令将执行。在条件语句中,else指令是可选择使用的。
Endif指令结束条件语句。任何条件语句必须以endif指令结束,后跟makefile文件中的正常内容。
上例表明条件语句工作在原文水平:条件语句的行根据条件要么被处理成makefile文件的一部分或要么被忽略。这是makefile文件重大的语法单位(例如规则)可以跨越条件语句的开始或结束的原因。
当变量CC的值是gcc,上例的效果为:
foo: $(objects)
        $(CC) -o foo $(objects) $(libs_for_gcc)
当变量CC的值不是gcc而是其它值的时候,上例的效果为:
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)

7.2条件语句的语法

对于没有else指令的条件语句的语法为:
conditional-directive
text-if-true
endif
‘text-if-true’可以是任何文本行,在条件为‘真’时它被认为是makefile文件的一部分;如果条件为‘假’,将被忽略。完整的条件语句的语法为:
conditional-directive
text-if-true
else
text-if-false
endif
如果条件为‘真’,使用‘text-if-true’;如果条件为‘假’,使用‘text-if-false’。‘text-if-false’可以是任意多行的文本。
关于‘conditional-directive’的语法对于简单条件语句和复杂条件语句完全一样。有四种不同的指令用于测试不同的条件。下面是指令表:

ifeq (arg1arg2)

ifeq 'arg1' 'arg2'

ifeq "arg1" "arg2"

ifeq "arg1" 'arg2'

ifeq 'arg1' "arg2"

 扩展参数arg1、arg2中的所有变量引用,并且比较它们。如果它们完全一致,则使用‘text-if-true’,否则使用‘text-if-false’(如果存在的话)。您经常要测试一个变量是否有非空值,当经过复杂的变量和函数扩展得到一个值,对于您认为是空值,实际上有可能由于包含空格而被认为不是空值,由此可能造成混乱。对于此,您可以使用strip函数从而避免空格作为非空值的干扰。例如:
ifeq ($(strip $(foo)),)
text-if-empty
endif
即使$(foo)中含有空格,也使用‘text-if-empty’。

ifneq (arg1arg2)

ifneq 'arg1' 'arg2'

ifneq "arg1" "arg2"

ifneq "arg1" 'arg2'

ifneq 'arg1' "arg2"

扩展参数arg1、arg2中的所有变量引用,并且比较它们。如果它们不同,则使用‘text-if-true’,否则使用‘text-if-false’(如果存在的话)。

ifdef variable-name

如果变量‘variable-name’是非空值,‘text-if-true’有效,否则,‘text-if-false’有效(如果存在的话)。变量从没有被定义过则变量是空值。注意ifdef仅仅测试变量是否有值。它不能扩展到看变量是否有非空值。因而,使用ifdef测试所有定义过的变量都返回‘真’,但那些象‘foo=’情况除外。测试空值请使用ifeq($(foo),)。例如:
bar =
foo = $(bar)
ifdef foo
frobozz = yes
else
frobozz = no
endif

设置‘frobozz'的值为‘yes', 而::

foo =
ifdef foo
frobozz = yes
else
frobozz = no
endif

设置‘frobozz' 为‘no'。

ifndef variable-name

如果变量‘variable-name’是空值,‘text-if-true’有效,否则,‘text-if-false’有效(如果存在的话)。
在指令行前面允许有多余的空格,它们在处理时被忽略,但是不允许有Tab(如果一行以Tab开始,那么该行将被认为是规则的命令行)。除此之外,空格和Tab可以插入到行的任何地方,当然指令名和参数中间除外。以‘#’开始的注释可以在行的结尾。
在条件语句中另两个有影响的指令是else和endif。这两个指令以一个单词的形式出现,没有任何参数。在指令行前面允许有多余的空格,空格和Tab可以插入到行的中间,以‘#’开始的注释可以在行的结尾。
条件语句影响make使用的makefile文件。如果条件为‘真’,make读入‘text-if-true’包含的行;如果条件为‘假’,make读入‘text-if-false’包含的行(如果存在的话);makefile文件的语法单位,例如规则,可以跨越条件语句的开始或结束。
当读入makefile文件时,Make计算条件的值。因而您不能在测试条件时使用自动变量,因为他们是命令执行时才被定义(参阅自动变量)。
为了避免不可忍受的混乱,在一个makefile文件中开始一个条件语句,而在另外一个makefile文件中结束这种情况是不允许的。然而如果您试图引入包含的makefile文件不中断条件语句,您可以在条件语句中编写include指令。

7.3测试标志的条件语句

您可以使用变量MAKEFLAGS和findstring函数编写一个条件语句,用它来测试例如‘-t’等的make命令标志(参阅字符串替换和分析的函数)。这适用于仅使用touch标志不能完全更改文件的时间戳的场合。
findstring函数检查一个字符串是否为另一个字符串的子字符串。如果您要测试‘-t’标志,使用‘-t’作为第一个字符串,将变量MAKEFLAGS的值作为另一个字符串。例如下面的例子是安排使用‘ranlib –t’完成一个档案文件的更新:
archive.a: ...
ifneq (,$(findstring t,$(MAKEFLAGS)))
        +touch archive.a
        +ranlib -t archive.a
else
        ranlib archive.a
endif
前缀‘+’表示这些命令行是递归调用行,即使是用‘-t’标志它们一样要执行。参阅递归调用make
posted @ 2012-05-26 14:41  小鼬就是我  阅读(26895)  评论(0编辑  收藏  举报