一、条件语句
条件指令会导致根据变量的值服从或忽略 makefile 的一部分。条件可以将一个变量的值与另一个变量的值进行比较,或者将变量的值与常量字符串进行比较。条件控制 make 文件中实际"sees"的内容,因此它们不能用于在执行时控制配方。
1、条件句示例
下面的条件示例告诉 make,如果 CC 变量是 “gcc”,则使用一组不同的库,否则则使用另一组库。它的工作原理是控制两个配方行中的哪一个将用于该规则。结果是"CC=gcc"作为参数,不仅可以更改使用哪个编译器,还可以更改链接的库。
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 指令开始条件,并指定条件。它包含两个参数,用逗号分隔,用括号括起来。对两个参数执行变量替换,然后对它们进行比较。如果两个参数匹配,则遵循 ifeq 后面的 makefile 行;否则,它们将被忽略。
如果前一个条件失败,则 else 指令会导致遵循以下行。在上面的示例中,这意味着只要不使用第一个替代命令,就会使用第二个备选项链接命令。在条件句中使用else是可选的。
endif 指令结束条件指令。每个条件都必须以 endif 结尾。无条件的makefile文本如下。
如本例所示,条件作用于文本级:条件语句的行被视为 makefile 的一部分,或根据条件被忽略。这就是makefile中较大的语法单元(如规则)可能会跨越条件的开头或结尾的原因。
当变量 CC 的值为"gcc"时,上面的示例具有以下效果:
foo: $(objects)
$(CC) -o foo $(objects) $(libs_for_gcc)
当变量CC有任何其他值时,效果是这样的:
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)
2、条件语句的语法
没有其他条件的简单条件的语法如下:
conditional-directive
text-if-true
endif
text-if-true可以是任何文本行,如果条件为真,则被视为makefile的一部分。如果条件为 false,则不使用任何文本。
复杂条件的语法如下所示:
conditional-directive
text-if-true
else
text-if-false
endif
或
conditional-directive-one
text-if-one-is-true
else conditional-directive-two
text-if-two-is-true
else
text-if-one-and-two-are-false
endif
可以根据需要有尽可能多的"else 条件指令"子句。一旦给定条件为真,text-if-true就会被使用,而不使用其他子句;如果没有条件为真,则使用text-if-false。text-if-true和text-if-false可以是任意数量的文本行。
条件指令的语法是相同的,无论条件是简单的还是复杂的;在else或not后面。有四种不同的指令用于测试不同的条件。这是他们的一个表格:
ifeq (arg1, arg2)
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
- 将计算text-if-empty,即使$(foo)的展开包含空白字符。
ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"
- 展开arg1和arg2中的所有变量引用并比较它们。如果它们是不同的,text-if-true是有效的;否则,text-if-false(如果有的话)有效。
ifdef variable-name
- ifdef 形式以变量的名称作为参数,而不是对变量的引用。如果该变量的值为非空值,则text-if-true有效;否则,text-if-false(如果有的话)有效。未定义的变量值为空。文本变量名是展开的,因此它可以是展开为变量名的变量或函数。例如:
bar = true
foo = bar
ifdef $(foo)
frobozz = yes
endif
- 变量引用 $(foo) 被展开,产生bar,这被认为是变量的名称。变量 bar 不会展开,但会检查它的值,以确定它是否为非空。
- 注意,ifdef只测试变量是否有值。它不会展开变量以查看该值是否为非空值。因此,使用ifdef的测试对于除 foo =. 之外的所有定义都返回true。要测试空值,使用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(如果有的话)有效。变量名的扩展和测试规则与ifdef指令相同。
在条件指令行开始处允许和忽略额外的空格,但不允许使用制表符(如果行以一个制表符开始,它将被认为是规则的配方的一部分)。除此之外,插入额外的空格或制表符时,除了指令名或参数内,其他地方都不会有任何效果。以"#"开头的注释可能会出现在行的末尾。
在条件句中起作用的另外两个指令是else和endif。这些指令都写成一个单词,没有参数。行首允许和忽略额外的空格,行尾允许空格或制表符。以“#”开头的注释可能出现在行尾。
条件影响makefile的哪一行使用。如果条件为真,make 将读取 text-if-true 作为 makefile 的一部分;如果条件为 false,则 make 将完全忽略这些行。因此,makefile的语法单元(如规则)可以安全地拆分到条件的开头或结尾。
make 在读取 makefile 时计算条件。因此,您不能在条件测试中使用自动变量,因为只有在运行配方时才会定义这些变量。
为了防止不可容忍的混乱,不允许在一个makefile中启动一个条件文件,而在另一个makefile中结束它。但是,如果您不尝试在包含的文件中终止该条件,则可以在条件文件中编写include指令。
3、测试标志的条件
您可以编写一个条件,通过使用变量 MAKEFLAGS 和 findstring 函数来测试命令标志,例如 -t。当 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"标志,它们仍将被执行。
本文介绍了Makefile中的条件语句及其使用方法,包括如何根据不同条件选择性地执行某些任务,以及如何通过条件语句控制链接库的选择。还讨论了条件语句的语法和测试标志的方法。
158

被折叠的 条评论
为什么被折叠?



