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

文章详细介绍了Makefile中如何自定义函数,包括使用`define...endef`定义函数,`call`函数的调用及参数传递,以及`eval`函数的两次展开过程。通过示例解释了$()的展开规则,并展示了如何在Makefile中使用这些函数进行更复杂的构建逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值