定义自定义GNU make函数

时间:2011-06-29 12:51:50

标签: makefile gnu-make

下面的示例代码中的dep2函数有什么问题?

dep1 = $(eval makefile_list_$1 := $(MAKEFILE_LIST))$(eval -include $1.mk)$(eval MAKEFILE_LIST := $(makefile_list_$1))

define dep2
$(eval makefile_list_$1 := $(MAKEFILE_LIST))
$(eval -include $1.mk)
$(eval MAKEFILE_LIST := $(makefile_list_$1))
endef

$(call dep1,test)
$(call dep2,test)

.DEFAULT_TARGET: all
.PHONY: all
all:
    @echo $@

GNU make 3.81和3.82生成Makefile:10: *** missing separator. Stop.指向dep2调用,dep1运行时没有错误。这两个变体之间的唯一区别是dep2中的换行符(以及为什么我要使用define的全部内容)。

4 个答案:

答案 0 :(得分:8)

你忘记了=
定义dep2 =

修改:
在每行末尾加一个分号。我已经对此进行了测试,并且它有效(在GNUMake 3.81中)。

define dep2
$(eval makefile_list_$1 := $(MAKEFILE_LIST));
$(eval -include $1.mk);
$(eval MAKEFILE_LIST := $(makefile_list_$1));
endef

为什么这些分号是必要的我不知道,但在文档中define似乎用于多行"变量"只有在定义要在配方中使用的shell命令序列时,才能生成命令,所以规则可能会有所不同。

答案 1 :(得分:2)

我会将$(eval ...)来电移到dep2之外。通过这种方式,dep2中不需要分号。这意味着将某些扩展的$标志加倍,以避免过早扩展。所以:

define dep2
makefile_list_$1 := $$(MAKEFILE_LIST)
-include $1.mk
MAKEFILE_LIST := $$(makefile_list_$1)
endef

$(eval $(call dep2,test))

# Quick checks for testing, to be removed from the final code...
$(info $(makefile_list_test))
$(info $(MAKEFILE_LIST))

.DEFAULT_TARGET: all
.PHONY: all
all:
    @echo $@

我已经测试了上面的代码,它适用于Gnu Make 4.0。我希望它可以回到Gnu Make 3.8x。 $(eval $(call ...))模式是我经常执行自定义函数的模式,现在已经使用了很长时间了。

答案 2 :(得分:0)

您可以执行以下行来消除错误:

FOO := $(call dep2, test)

我猜原因是gcc(3.8.1 / 2)的早期版本只能接受任何表达式的返回。

例如$(info string)不返回任何内容,但$(call dep2, test)会返回2个换行符。

答案 3 :(得分:-1)

您正在做的事情可以改善很多。首先,您确实希望将eval调用分配到顶部的单个调用。

然而,你的特殊问题源于不理解make的定义命令使用的多行递归字符串从不包括lady新行。编写可证实函数的最自然的惯例是

定义Foo 1号线 LINE2

endef

您可以查看eval正在查看的字符串,并通过info命令查看此操作,例如 $(info $(call Foo,x)$(call Foo,y))。