如何在使用 Make 时改进 $(call $(eval $(call))) 范式?

how to improve $(call $(eval $(call))) paradigm in using Make?

我编写通用的 makefile 和函数是为了方便用户,所以它们自然应该具有尽可能简单的界面。在定义函数时,我使用这种范式:

define FUNCTION
target: 
endef

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

现在,而不是告诉他们这样做

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

我可以告诉他们这样做

$(call FUNCTION2,参数)

哪个更简单。

在有人决定使用 .EXPORT_ALL_VARIABLES 之前,这一直很有效,因此我们的总代码 (SSCCE) 如下所示:

define FUNCTION
target: 
endef

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

.EXPORT_ALL_VARIABLES:

all:    
    echo OK

现在当你 make 这个时,你会得到:

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

好吧,我想这是因为配方 echo 子流程评估 "variable" FUNCTION2,然后意外地将先决条件行放入配方中。或类似的东西。

所以我的问题是,谁应该受到指责?

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

或者 .EXPORT_ALL_VARIABLES 是一个邪恶的特性,不应该被使用?

在我的 non-recursive 构建系统 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 的哪个参数是什么意思,因为this_ 变量具有描述性名称。

我个人认为.EXPORT_ALL_VARIABLES是一个邪恶的特性,不应该被使用。但是,我认为这值得 GNU make 的增强请求:在扩展导出变量时不应该是 运行 eval

使用 unexport FUNCTION FUNCTION2 消除此错误。

然而我不得不同意@MadScientist 的观点.EXPORT_ALL_VARIABLES 是邪恶的。

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

IMO,有一种方法可以停止 auto-exported 变量的任何扩展

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