GNU make手册说eval函数扩展了参数,然后将扩展的结果提供给make解析器。以下摘自GNU make手册。
The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax.
Run Code Online (Sandbox Code Playgroud)
我不太了解make解析器如何处理eval输入的文本,因此我编写了以下makefile进行测试。
define myprint
echo "this is a line"
endef
goal:
$(eval $(call myprint))
gcc -o goal test.c
Run Code Online (Sandbox Code Playgroud)
我知道正确的调用myprint应该只使用call函数:$(call myprint)在回显之前删除'Tab'字符。我以这种形式编写makefile只是为了测试eval函数。
我的期望:首先,eval函数扩展myprint,这是一个以'Tab'开头的echo命令,并且'Tab'用于使扩展的文本成为合法的配方。然后eval将扩展的文本输入到制造商解析器,后者将识别该文本为配方并运行它。由于该命令是合法的,因此makefile应该正确运行。
但是,我遇到这样的错误:
Makefile:6: *** recipe commences before first target. Stop.
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么使产生这样的错误吗?
扩展的结果被解析为makefile语法
您对的使用eval有所不同:您希望将其解析为shell语法。你可以写:
define myprint
echo "this is a line"
endef
goal:
$(myprint)
gcc -o goal test.c
Run Code Online (Sandbox Code Playgroud)
要么:
define myprint
echo "this is a $(1)"
endef
goal:
$(call myprint,line)
gcc -o goal test.c
Run Code Online (Sandbox Code Playgroud)
因为在进行扩展后,配方是有效的Shell语法。但不是您编写的内容,因为的扩展eval仍被解释为make语法,而不是shell。为了说明evaland 的典型用法call,请考虑以下事项:
define myprint
echo "this is a $(1)"
endef
define mygoal
$(1):
$$(call myprint,line)
gcc -o $(1) $(2).c
endef
$(eval $(call mygoal,goal,test))
Run Code Online (Sandbox Code Playgroud)
它比前两个示例(没有eval)更加棘手,但它说明了的真正目的eval:以编程方式实例化make构造。步骤如下:
在其两阶段算法的第一阶段,make扩展$(eval...函数调用,即:
$(eval...函数($(call...函数)的参数:
$(call...函数的参数(goal和test)。对我们的情况没有影响。$(1)和$(2)。mygoal在这种情况下,取代可变$(1),$(2)和$$(call...通过goal,test并$(call...分别。实例化结果(在内存中)为make结构,在这种情况下,这是一个完整规则:
goal:
$(call myprint,line)
gcc -o goal test.c
Run Code Online (Sandbox Code Playgroud)第一阶段继续进行,但是它对此实例化规则没有影响,因为在第二阶段中,配方通过make进行了扩展。
在第二阶段中,当需要构建goal目标时,make在执行它之前先扩展配方,即:
$(call myprint...参数(line,无效)。$(1)。myprint在这种情况下扩展变量,将产生:
echo "this is a line"
Run Code Online (Sandbox Code Playgroud)因此,所有这些都与我们编写规则相同:
goal:
echo "this is a line"
gcc -o goal test.c
Run Code Online (Sandbox Code Playgroud)
需要注意的双重$$中的初始定义mygoal:
重要的是要认识到eval参数被扩展了两次。首先通过eval函数,然后在将扩展结果解析为makefile语法时再次进行扩展。这意味着在使用eval时,您可能需要为“ $”字符提供额外的转义级别。
$(eval \xe2\x80\xa6)需要一个语法完整的 makefile 片段。它不能用于将标记粘贴到其他 makefile 结构中。也许手册对此解释得不够清楚,但它是通过读取其参数来实现的,就像它是一个包含的 makefile 一样。
| 归档时间: |
|
| 查看次数: |
1294 次 |
| 最近记录: |