makefile中的函数包括预定义函数,如wildcard、subst等,除此之外,我们还可以像c语言那样自定义函数以便于我们使用。
    
     目录
    
   
    一、函数定义 —— define … endef
   
    自定义函数一般是
    
     命令的集合
    
    ,搭配不同的函数可以定义不同的内容。函数使用的符号是 define。语法格式如下:
   
define 函数名
    ...
endef示例:定义一个myFunc函数
define myFunc
    @echo "func name is $(0)\n"
    @echo "first param is $(1)\n"
    @echo "second param is $(2)\n"
endef- 
     
 $(0):表示函数名
 
- 
     
 $(1):表示传给函数的第一个参数
 
- 
     
 $(2):表示传给函数的第二个参数
 
    二、call 函数
   
    1、call 函数格式
   
call 函数能够 给自定义函数传递参数,并展开。 call 调用自定义函数的步骤是
- 
     
 先给自定义函数传参(如果有的话)
 
- 
     
 在call调用的位置直接展开自定义函数
 
调用格式如下。
$(call 函数名 参数1, 参数2, ...)
    
     
      注意:
     
    
    一般而言,call 本身并不具备编译功能,
    
     call 只是将自定义函数在当前位置展开
    
    ,遇到
    
     Makefile内置函数会自动执行
    
    (比如 info,warning等)
   
    2、call 函数展开过程分析
   
我们可以使用 info 函数打印一下 call 展开自定义函数以后的结果。我们要测试如下几点是否会被展开,即是否会展开 $()
- 自定义变量:$(BUILD_DIR)
- 函数:$(info hello world)
- 预置变量:$@
# 无论你把函数定义或者调用放在哪
# Makefile 在编译的时候,一定会把目标对象的生成放到最后。
all:
    
# 自定义变量
BUILD_DIR			= build
# 自定义函数foo
define foo
$(info hello world)
$$(info hello world)
echo $(BUILD_DIR)
ps jax | grep tcp
target:main.c
	gcc -o $@ $^
endef
###############################################
# 打印 call 展开自定义函数的内容
$(info $(call foo))
     
   
    
     $(info hello world)
    
    :去掉 $,变成 info hello world,函数自动执行,打印结果是 hello world
   
    
     $$(info hello world):
    
    去掉一层 $,展开结果是 $(info hello world)
   
    
     echo $(BUILD_DIR)
    
    :变量被展开(去掉 $), 展开的结果是echo build
   
    
     ps jax | grep tcp
    
    :无需展开
   
    
     target: main.c
    
    :无需展开
   
    
     gcc -o $@ $^
    
    :
    
     $@ 被展开
    
    (去掉 $),
    
     因为call 只是展开,他也不知道 $@ 代表啥,展开结果为空
    
   
###############################################
# 打印 call 展开自定义函数的内容
$(info \
    hello world
    
    $(info hello world)
    echo build
    ps jax | grep tcp
    target: main.c
        gcc -o  
)
    三、eval 函数
   
    1、eval 函数格式
   
    eval 可以将 <text> 中的内容作为makefile的一部分,然后按照makefile的语法解析这些内容,无返回值。该函数在执行时会对参数
    
     展开两次
    
    ,可以理解为第一次是eval函数检查<text>语法,第二次是解析并执行 <text>内容。
   
$(eval <text>)
    2、eval 函数展开过程分析
   
因为每展开一次会去掉一层 $,因此有些地方需要加两层 $
# echo $$(BUILD_DIR)   展开以后eval无法解析
# ps jax | grep tcp    展开以后eval无法解析
# 自定义变量
BUILD_DIR			= build
define foo
$(info $(BUILD_DIR))
$(info $$(BUILD_DIR))
$$(info $$(BUILD_DIR))
target:main.c
	gcc -o $$@ $$^	
endef
$(eval $(call foo))
     
   
第一次展开
    
     $(info $(BUILD_DIR))
    
    :去掉一层 $ 变成 info build,直接执行info函数,打印 build
   
    
     $(info $$(BUILD_DIR))
    
    :去掉一层 $ 变成 info $(BUILD_DIR),直接执行info函数,打印 $(BUILD_DIR)
   
    
     $$(info $$(BUILD_DIR))
    
    :去掉一层 $ 以后变成了 $(info $(BUILD_DIR)),此时的info 函数无法执行,继续下一行。
   
    
     target:main.c
    
    :不做任何处理,无需展开,继续下一行
   
    
     gcc -o $$@ $$^
    
    :去掉一层 $ 变成 gcc -o $@ $^
   
# build 
# $(BUILD_DIR)
$(info $(BUILD_DIR))
target:main.c
    gcc -o $@ $^
第二次展开
第一次展开以后,注释部分表示打印到控制台,剩下的就是待解析的部分。剩余部分交由Makefile解析,得到的结果就是
# build 
# $(BUILD_DIR)
build
gcc -o target main.c 
