现在的位置: 首页 > 综合 > 正文

makefile函数集锦及条件判断

2017年08月28日 ⁄ 综合 ⁄ 共 9488字 ⁄ 字号 评论关闭

Makefile  常用函数表
一、字符串处理函数
1.$(subst FROM,TO,TEXT)
函数名称:字符串替换函数—subst。
函数功能:把字串“TEXT”中的“FROM”字符替换为“TO”。
返回值:替换后的新字符串。
2.$(patsubst PATTERN,REPLACEMENT,TEXT)
函数名称:模式替换函数—patsubst。
函数功能:搜索“TEXT”中以空格分开的单词,将否符合模式“TATTERN”替换为“REPLACEMENT”。参数“PATTERN”中可以使用模
式通配符“%”来代表一个单词中的若干字符。如果参数“REPLACEMENT”中也包含一个“%”,那么“REPLACEMENT”中的“%”将是
“TATTERN”中的那个“%”所代表的字符串。在“TATTERN”和“REPLACEMENT”中,只有第一个“%”被作为模式字符来处理,后续的作为字符本上来处理。在两个参数中当使用第一个“%”本是字符本身时,可使用反斜杠“\”对它进行转义处理。
返回值:替换后的新字符串。
函数说明:参数“TEXT”单词之间的多个空格在处理时被合并为一个空格,但前导和结尾空格忽略。
3.$(strip STRINT)
函数名称:去空格函数—strip。
函数功能:去掉字串(若干单词,使用若干空字符分割)“STRINT”开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符。
返回值:无前导和结尾空字符、使用单一空格分割的多单词字符串。
函数说明:空字符包括空格、[Tab]等不可显示字符。
4.$(findstring FIND,IN)
函数名称:查找字符串函数—findstring。
函数功能:搜索字串“IN”,查找“FIND”字串。
返回值:如果在“IN”之中存在“FIND”,则返回“FIND”,否则返回空。
函数说明:字串“IN”之中可以包含空格、[Tab]。搜索需要是严格的文本匹配。
5.$(filter PATTERN…,TEXT)
函数名称:过滤函数—filter。
函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
函数说明:“filter”函数可以用来去除一个变量中的某些字符串,我们下边的例子中就是用到了此函数。
6.$(filter-out PATTERN...,TEXT)
函数名称:反过滤函数—filter-out。
函数功能:和“filter”函数实现的功能相反。过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。。
返回值:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。
函数说明:“filter-out”函数也可以用来去除一个变量中的某些字符串,(实现和“filter”函数相反)。
7.$(sort LIST)
函数名称:排序函数—sort。
函数功能:给字串“LIST”中的单词以首字母为准进行排序(升序),并取掉重复的单词。
返回值:空格分割的没有重复单词的字串。
函数说明:两个功能,排序和去字串中的重复单词。可以单独使用其中一个功能。
8.$(word N,TEXT)
函数名称:取单词函数—word。
函数功能:取字串“TEXT”中第“N”个单词(“N”的值从1开始)。
返回值:返回字串“TEXT”中第“N”个单词。
函数说明:如果“N”值大于字串“TEXT”中单词的数目,返回空字符串。如果“N”为0,出错!
9.$(wordlist S,E,TEXT)
函数名称:取字串函数—wordlist。
函数功能:从字串“TEXT”中取出从“S”开始到“E”的单词串。“S”和“E”表示单词在字串中位置的数字。
返回值:字串“TEXT”中从第“S”到“E”(包括“E”)的单词字串。
函数说明:“S”和“E”都是从1开始的数字。
当“S”比“TEXT”中的字数大时,返回空。如果“E”大于“TEXT”字数,返回从“S”开始,到“TEXT”结束的单词串。如果“S”大于“E”,返回空。
10.$(words TEXT)
函数名称:统计单词数目函数—words。
函数功能:字算字串“TEXT”中单词的数目。
返回值:“TEXT”字串中的单词数。
11.$(firstword NAMES…)
函数名称:取首单词函数—firstword。
函数功能:取字串“NAMES…”中的第一个单词。
返回值:字串“NAMES…”的第一个单词。
函数说明:“NAMES”被认为是使用空格分割的多个单词(名字)的序列。函数忽略“NAMES…”中除第一个单词以外的所有的单词。
二、文件名处理函数
1.$(dir NAMES…)
函数名称:取目录函数—dir。
函数功能:从文件名序列“NAMES…”中取出各个文件名目录部分。文件名的目录部分就是包含在文件名中的最后一个斜线(“/”)(包括斜线)之前的部分。
返回值:空格分割的文件名序列“NAMES…”中每一个文件的目录部分。
函数说明:如果文件名中没有斜线,认为此文件为当前目录(“./”)下的文件。
2.$(notdir NAMES…)
函数名称:取文件名函数——notdir。
函数功能:从文件名序列“NAMES…”中取出非目录部分。目录部分是指最后一个斜线(“/”)(包括斜线)之前的部分。删除所有文件名中的目录部分,只保留非目录部分。
返回值:文件名序列“NAMES…”中每一个文件的非目录部分。
函数说明:如果“NAMES…”中存在不包含斜线的文件名,则不改变这个文件名。以反斜线结尾的文件名,是用空串代替,因此当“NAMES…”中存在多个这样的文件名时,返回结果中分割各个文件名的空格数目将不确定!这是此函数的一个缺陷。
3.$(suffix NAMES…)
函数名称:取后缀函数—suffix。
函数功能:从文件名序列“NAMES…”中取出各个文件名的后缀。后缀是文件名中最后一个以点“.”开始的(包含点号)部分,如果文件名中不包含一个点号,则为空。
返回值:以空格分割的文件名序列“NAMES…”中每一个文件的后缀序列。
函数说明:“NAMES…”是多个文件名时,返回值是多个以空格分割的单词序列。如果文件名没有后缀部分,则返回空。
4.$(basename NAMES…)
函数名称:取前缀函数—basename。
函数功能:从文件名序列“NAMES…”中取出各个文件名的前缀部分(点号之后的部分)。前缀部分指的是文件名中最后一个点号之前的部分。
返回值:空格分割的文件名序列“NAMES…”中各个文件的前缀序列。如果文件没有前缀,则返回空字串。
函数说明:如果“NAMES…”中包含没有后缀的文件名,此文件名不改变。如果一个文件名中存在多个点号,则返回值为此文件名的最后一个点号之前的文件名部分。
5.$(addsuffix SUFFIX,NAMES…)
函数名称:加后缀函数—addsuffix。
函数功能:为“NAMES…”中的每一个文件名添加后缀“SUFFIX”。参数“NAMES…”为空格分割的文件名序列,将“SUFFIX”追加到此序列的每一个文件名的末尾。
返回值:以单空格分割的添加了后缀“SUFFIX”的文件名序列。
6.$(addprefix PREFIX,NAMES…)
函数名称:加前缀函数—addprefix。
函数功能:为“NAMES…”中的每一个文件名添加前缀“PREFIX”。参数“NAMES…”是空格分割的文件名序列,将“SUFFIX”添加到此序列的每一个文件名之前。
返回值:以单空格分割的添加了前缀“PREFIX”的文件名序列。
7.$(join LIST1,LIST2)
函数名称:单词连接函数——join。
函数功能:将字串“LIST1”和字串“LIST2”各单词进行对应连接。就是将“LIST2”中的第一个单词追加“LIST1”第一个单词字后合并为一个单词;将“LIST2”中的第二个单词追加到“LIST1”的第一个单词之后并合并为一个单词,……依次列推。
返回值:单空格分割的合并后的字(文件名)序列。
函数说明:如果“LIST1”和“LIST2”中的字数目不一致时,两者中多余部分将被作为返回序列的一部分。
8.$(wildcard PATTERN)
函数名称:获取匹配模式文件名函数—wildcard
函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
函数说明:“PATTERN”使用shell可识别的通配符,包括“?”(单字符)、“*”(多字符)等。
三、其它函数
1.$(foreach VAR,LIST,TEXT)
函数功能:函数“foreach”不同于其它函数。它是一个循环函数。类似于Linux的shell中的循环(for语句)。这个函数的工作过程是这样
的:如果必要(存在变量或者函数的引用),首先展开变量“VAR”和“LIST”;而表达式“TEXT”中的变量引用不被展开。执行时把“LIST”中使
用空格分割的单词依次取出赋值给变量“VAR”,然后执行“TEXT”表达式。重复直到“LIST”的最后一个单词(为空时结束)。“TEXT”中的变量
或者函数引用在执行时才被展开,因此如果在“TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开式将会到的不同的值。
返回值:空格分割的多次表达式“TEXT”的计算的结果。
2.$(if CONDITION,THEN-PART[,ELSE-PART])
函数功能:函数“if”提供了一个在函数上下文中实现条件判断的功能。就像make所支持的条件语句—ifeq。第一个参数“CONDITION”,在函
数执行时忽略其前导和结尾空字符并展开。“CONDITION”的展开结果非空,则条件为真,就将第二个参数“THEN_PATR”作为函数的计算表达
式,函数的返回值就是第二表达式的计算结果;“CONDITION”的展开结果为空,将第三个参数
“ELSE-PART”作为函数的表达式,返回结果为第三个表达式的计算结果。
返回值:根据条件决定函数的返回值是第一个或者第二个参数表达式的计算结果。当不存在第三个参数“ELSE-PART”,并且“CONDITION”展开为空,函数返回空。
函数说明:函数的条件表达式“CONDITION”决定了,函数的返回值只能是“THEN-PART”或者“ELSE-PART”两个之一的计算结果。
3.$(call VARIABLE,PARAM,PARAM,...)
函数功能:“call”函数是唯一一个可以创建定制参数化的函数的引用函数。我们可以将一个变量定义为一个复杂的表达式,用“call”函数根据不同的参数对它进行展开来获得不同的结果。
在执行时,将它的参数“PARAM”依次赋值给临时变量“$(1)”、“$(2)”(这些临时变量定义在“VARIABLE”的值中,参考下边的例
子)……
call函数对参数的数目没有限制,也可以没有参数值,没有参数值的“call”没有任何实际存在的意义。执行时变量“VARIABLE”被展开为在函数
上下文有效的临时变量,变量定义中的“$(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“$(2)”一样被赋值为函数的第二个
参数值;依此类推(变量$(0)代表变量“VARIABLE”本身)。之后对变量“VARIABLE” 表达式的计算值。
返回值:参数值“PARAM”依次替换“$(1)”、“$(2)”…… 之后变量“VARIABLE”定义的表达式的计算值。
函数说明:1.
函数中“VARIBLE”是一个变量名,而不是对变量的引用。因此,通常“call”函数中的“VARIABLE”中不包含“$”(当然,除了此变量名是
一个计算的变量名)。2.
当变量“VARIBLE”是一个make内嵌的函数名时(如“if”、“foreach”、“strip”等),对“PARAM”参数的使用需要注意,因
为不合适或者不正确的参数将会导致函数的返回值难以预料。3. 函数中多个“PARAM”之间使用逗号分割。4.
变量“VARIABLE”在定义时不能定义为直接展开式!只能定义为递归展开式。
4.value函数
$(value VARIABLE)
函数功能:不对变量“VARIBLE”进行任何展开操作,直接返回变量“VARIBALE”代表的值。这里“VARIABLE”是一个变量名,一般不包含“$”(当然,除了计算的变量名),
返回值:变量“VARIBALE”所定义文本值(不展开其中的变量或者函数应用)。
5.eval函数
函数功能:函数“eval”是一个比较特殊的函数。使用它我们可以在我们的Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其
它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含
一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。
返回值:函数“eval”的返回值时空,也可以说没有返回值。
函数说明:“eval”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容
时由make解析时展开的。明确这一点对于使用“eval”函数非常重要。在理解了函数“eval”二次展开的过程后。实际使用时,当函数的展开结果中存
在引用(格式为:$(x))时,那么在函数的参数中应该使用“$$”来代替“$”。因为这一点,所以通常它的参数中会使用函数“value”来取一个变量
的文本值。
6.origin函数
$(origin VARIABLE)
函数功能:函数“origin”查询参数“VARIABLE”(通常是一个变量名)的出处。
函数说明:“VARIABLE”是一个变量名而不是一个变量的引用。因此通常它不包含“$”(当然,计算的变量名例外)。
返回值:返回“VARIABLE”的定义方式。用字符串表示。
. undefined
变量“VARIABLE”没有被定义。
. default
变量“VARIABLE”是一个默认定义(内嵌变量)。如“CC”、“MAKE”、“RM”等变量。如果在Makefile中重新定义这些变量,函数返回值将相应发生变化。
. environment
变量“VARIABLE”是一个系统环境变量,并且make没有使用命令行选项“-e”(Makefile中不存在同名的变量定义,此变量没有被替代)。
. environment override
变量“VARIABLE”是一个系统环境变量,并且make使用了命令行选项“-e”。Makefile中存在一个同名的变量定义,使用“make -e”时环境变量值替代了文件中的变量定义。
. file
变量“VARIABLE”在某一个makefile文件中定义。
. command line
变量“VARIABLE”在命令行中定义。
. override
变量“VARIABLE”在makefile文件中定义并使用“override”指示符声明。
. automatic
变量“VARIABLE”是自动化变量。
7.shell函数
不同于除“wildcard”函数之外的其它函数。make可以使用它来和外部通信。
函数功能:函数“shell”所实现的功能和shell中的引用(``)相同。实现了命令的扩展。意味着需要一个shell
命令作为它的参数,而返回的结果是此命令在shell中的执行结果。make仅仅对它的回返结果进行处理;make将函数的返回结果中的所有换行符
(“\n”)或者一对“\n\r”替换为单空格;并去掉末尾的回车符号(“\n”)或者“\n\r”。函数展开式时,它所调用的命令(它的参数)得到执
行。除了对它的引用出现在规则的命令行中和递归的变量定义引用以外,其它决大多数情况下,make在读取Makefile时函数shell就被扩展。
返回值:函数“shell”的参数在shell中的执行结果。
函数说明:函数本身的返回值是其参数的执行结果,没有进行任何处理。对结果的处理是由make进行的。当对函数的引用出现在规则的命令行中,命令行在执行
时函数引用才被展开。展开过程函数参数的执行时在另外一个shell进程中完成的,因此对于出现在规则命令行的多级“shell”函数引用需要谨慎处理,
否则会影响效率(每一级的“shell”函数的参数都会有各自的shell进程)。
8.error 函数
$(error TEXT…)
函数功能:产生致命错误,并提示“TEXT…”信息给用户,之后退出make的执行。需要说明的是:“error”函数是在函数展开式(函数被调用时)才
提示信息并结束make进程。因此如果函数出现在命令中或者一个递归的变量定义中时,在读取Makefile时不会出现错误。而只有包含
“error”函数引用的命令被执行,或者定义中引用此函数的递归变量被展开时,才会提示致命信息“TEXT…”同时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) 


二、语法 

条件表达式的语法为: 

    <conditional-directive>; 
    <text-if-true>; 
    endif 

以及: 

    <conditional-directive>; 
    <text-if-true>; 
    else 
    <text-if-false>; 
    endif 

其中<conditional-directive>;表示条件关键字,如“ifeq”。这个关键字有四个。 

第一个是我们前面所见过的“ifeq” 

    ifeq (<arg1>;, <arg2>;)  
    ifeq '<arg1>;' '<arg2>;'  
    ifeq "<arg1>;" "<arg2>;"  
    ifeq "<arg1>;" '<arg2>;'  
    ifeq '<arg1>;' "<arg2>;"  

比较参数“arg1”和“arg2”的值是否相同。当然,参数中我们还可以使用make的函数。如: 

    ifeq ($(strip $(foo)),) 
    <text-if-empty>; 
    endif 

这个示例中使用了“strip”函数,如果这个函数的返回值是空(Empty),那么<text-if-empty>;就生效。 

第二个条件关键字是“ifneq”。语法是: 

    ifneq (<arg1>;, <arg2>;)  
    ifneq '<arg1>;' '<arg2>;'  
    ifneq "<arg1>;" "<arg2>;"  
    ifneq "<arg1>;" '<arg2>;'  
    ifneq '<arg1>;' "<arg2>;"  

其比较参数“arg1”和“arg2”的值是否相同,如果不同,则为真。和“ifeq”类似。 

第三个条件关键字是“ifdef”。语法是: 

    ifdef <variable-name>;  

如果变量<variable-name>;的值非空,那到表达式为真。否则,表达式为假。当然,<variable-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 <variable-name>; 

这个我就不多说了,和“ifdef”是相反的意思。 

在<conditional-directive>;这一行上,多余的空格是被允许的,但是不能以[Tab]键做为开始(不然就被认为是命令)。而注释符“#”同样也是安全的。“else”和“endif”也一样,只要不是以[Tab]键开始就行了。 

特别注意的是,make是在读取Makefile时就计算条件表达式的值,并根据条件表达式的值来选择语句,所以,你最好不要把自动化变量(如“$@”等)放入条件表达式中,因为自动化变量是在运行时才有的。 

而且,为了避免混乱,make不允许把整个条件语句分成两部分放在不同的文件中。

 

抱歉!评论已关闭.