如何使用Make改善$(call $(eval $(call)))范例?

时间:2019-06-05 20:39:01

标签: makefile gnu-make

为方便用户,我编写了通用的makefile和函数,因此它们自然应该具有最简单的接口。在定义函数时,我使用以下范例:

define FUNCTION
target: $1
endef

FUNCTION2 = $(eval $(call FUNCTION,$1))

现在,不要告诉他们这样做

$(eval $(call FUNCTION,参数))

我可以告诉他们这样做

$(call FUNCTION2,参数)

更简单。

这一直很吸引人,直到有人决定使用.EXPORT_ALL_VARIABLES,这样我们的总代码(SSCCE)如下所示:

define FUNCTION
target: $1
endef

FUNCTION2 = $(eval $(call FUNCTION,$1))

.EXPORT_ALL_VARIABLES:

all:    
    echo OK

现在make,您得到:

Makefile:5: *** prerequisites cannot be defined in recipes.  Stop.

好吧,我想这是因为配方echo子进程评估了“变量” FUNCTION2,然后意外地将前提行放入了配方中。或类似的东西。

所以我的问题是,应该责怪谁?

我的范例是否有误,我不应该使用它,因为用户随后无法使用.EXPORT_ALL_VARIABLES?如果是这样,有没有办法解决问题,以便用户仍然可以调用简单的FUNCTION2

或者.EXPORT_ALL_VARIABLES是邪恶的功能,不应该使用吗?

3 个答案:

答案 0 :(得分:1)

我个人认为.EXPORT_ALL_VARIABLES是一个邪恶的功能,不应使用。但是,我认为这值得对GNU make进行增强请求:扩展用于导出的变量时,它不应运行eval

答案 1 :(得分:1)

使用unexport FUNCTION FUNCTION2消除此错误。

但是我必须同意@MadScientist的观点,.EXPORT_ALL_VARIABLES是邪恶的。

在执行每个配方之前,它会强制执行所有递归变量的扩展,因此可以轻松破坏任何复杂的构建系统。

IMO,有一种方法可以停止自动导出变量的任何扩展

唯一的安慰是几乎没有人使用.EXPORT_ALL_VARIABLES这种东西。

答案 2 :(得分:-1)

在我的非递归构建系统prorab中,我使用eval,但没有call

我通过this_前缀变量传递参数,如下所示:

include prorab.mk

this_name := myapp

this_cxxflags += -Wall
this_cxxflags += -DDEBUG
this_cflags += -Wall

this_ldlibs += -lpthread

this_srcs += main.cpp myapp.cpp legacy.c

$(eval $(prorab-build-app))

因此,eval仍然存在,但是插入变量而不是call使其更短,并且用户不必记住call的哪个参数意味着什么,因为{{ 1}}变量具有描述性名称。