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

余生颓废 提交于 2020-05-18 03:46:08

问题


I write general makefiles and functions for users' convenience, so naturally they should have the simplest interfaces possible . When defining functions, I use this paradigm:

define FUNCTION
target: $1
endef

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

Now, instead of telling them to do this

$(eval $(call FUNCTION,argument))

I can tell them to do this

$(call FUNCTION2,argument)

which is simpler.

This worked like a charm until somebody decided to use .EXPORT_ALL_VARIABLES, so that we have the total code (SSCCE) look like this:

define FUNCTION
target: $1
endef

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

.EXPORT_ALL_VARIABLES:

all:    
    echo OK

Now when you make this, you get:

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

Well, I guess this is because the recipe echo subprocess evaluates the "variable" FUNCTION2, which then unexpectedly puts the prerequisite line into the recipe. Or something like that.

So my question is, who is to blame?

Is my paradigm faulty and I should not be using it, because the users then cannot use .EXPORT_ALL_VARIABLES ? If so, is there a way to fix things, so that users can still call the simple FUNCTION2?

Or is .EXPORT_ALL_VARIABLES an evil feature and should not be used?


回答1:


My personal opinion is that .EXPORT_ALL_VARIABLES is an evil feature and should not be used. However, i think this is worth an enhancement request for GNU make: it shouldn't be running eval when expanding variables for export.




回答2:


Use unexport FUNCTION FUNCTION2 to get rid of this error.

Yet I have to agree with @MadScientist that .EXPORT_ALL_VARIABLES is evil.

It forcefully performs expansion of all recursive variables before executing every recipe, so it could easily break any complicated build system.

IMO, it could be useful to have a way to stop any expansion of auto-exported variables.

The only consolation is that almost no one uses that .EXPORT_ALL_VARIABLES thing.




回答3:


In my non-recursive build system prorab I use eval, but without call.

I pass parameters through this_-prefixed variables, something like 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))

So, eval is still there, but inserting variable instead of call makes it shorter and also user does not have to remember which argument of the call means what, because this_ variables have descriptive names.



来源:https://stackoverflow.com/questions/56467690/how-to-improve-call-eval-call-paradigm-in-using-make

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!