为什么我需要eval在makefile函数中设置变量?

时间:2019-08-14 15:01:40

标签: makefile gnu

如果我在gnu makefile的顶部有以下内容:

$(if _,a:=1)
$(info a=$a)

编译失败(make-3.81: *** No rule to make target '=1', needed by 'a'. Stop.;如果排除冒号,则*** missing separator. Stop.)。我知道我可以使用eval来解决这个问题,但是我不明白为什么需要这样做。

难道不应该将其扩展为a:=1,进行解析并将a设置为1吗?

2 个答案:

答案 0 :(得分:0)

在您的情况下,https://coderwall.com/p/ewxn9g/storing-and-retrieving-objects-with-localstorage-html5 函数的值作为第二个参数(if),但此函数不作为make变量赋值。对于您的make版本,这已成为规则。这可能是由于make在语法上解析makefile的方式所致。它不认为此a:=1语句可以是变量赋值,因为(在扩展之前)它看起来好像都不是有效的make变量赋值。因此,if语句得到了扩展,但是对于将结果视为变量赋值来说,现在为时已晚。

您可以使用:

if

或:

a := $(if _,1)

或:

ifneq (_,)
a := 1
endif

或:

$(if _,$(eval a := 1))

后两种形式之所以起作用,是因为根据定义,$(eval $(if _,a := 1)) 函数的自变量扩展结果将作为纯make语句处理。

答案 1 :(得分:0)

  

我不明白为什么要这么做

嗯,就是这样的设计。

评估过程始终执行(递归)扩展(“初始评估”可通过=有效地停止后续扩展,即“惰性分配”),但是扩展过程从不进行评估,除非它是明确指出了这一点(基本上,$(eval ...)是从扩展转换为评估的命令)。

考虑一下:

x := 0
y := 1
# z is set to "y<space><equal><space><dollar>x"
z = y = $x

# [0] [1] [y = $x]
$(info [$x] [$y] [$(value z)])

# error as "y = $x" will not be re-evaluated
#$z

# effectively sets y to "0"
$(eval $z)

# [0] [0] [y = $x]
$(info [$x] [$y] [$(value z)])

从制造商的角度来看,$(if cond,x=y)$z并没有太大的区别---它已扩展但未评估。不管它站在哪里。只需将$(...)形式的任何内容都视为“数据”,而不是“代码”。