【makefile函数】makefile 自定义函数、call 函数、eval函数

  • Post author:
  • Post category:其他


makefile中的函数包括预定义函数,如wildcard、subst等,除此之外,我们还可以像c语言那样自定义函数以便于我们使用。



目录


一、函数定义 —— define … endef


二、call 函数


1、call 函数格式


2、call 函数展开过程分析


三、eval 函数


1、eval 函数格式


2、eval 函数展开过程分析


一、函数定义 —— 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



版权声明:本文为challenglistic原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。