eval
是一个比较特殊的函数。
可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。
函数"eval"对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。
展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。
也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。
返回值:函数"eval"的返回值时空,也可以说没有返回值。
函数说明:"eval"函数执行时会对它的参数进行两次展开。
第一次展开过程发是由函数本身完成的,
第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。
明确这一过程对于使用"eval"函数非常重要。
理解了函数"eval"二次展开的过程后。
实际使用时,如果在函数的展开结果中存在引用(格式为:$(x)),
那么在函数的参数中应该使用"$$"来代替"$"。
因为这一点,所以通常它的参数中会使用函数"value"来取一个变量的文本值。
我们看一个例子。例子看起来似乎非常复杂,因为它综合了其它的一些概念和函数。
不过我们可以考虑两点:
其一,通常实际一个模板的定义可能比例子中的更为复杂;
其二,我们可以实现一个复杂通用的模板,在所有Makefile中包含它,亦可作到一劳永逸。
相信这一点可能是大多数程序员所推崇的。
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
# Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template
$(1): $$($(1)_OBJ) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)
来看一下这个例子:它实现的功能是完成"PROGRAMS"的编译链接。
例子中"$(LINK.o)"为"$(CC) $(LDFLAGS)",意思是对所有的.o文件和指定的库文件进行链接。
"$(foreach prog,$(PROGRAM),$(eval $(call PROGRAM_template,$(prog))))"展开为:
server : $(server_OBJS) –l$(server_LIBS)
client : $(client_OBJS) –l$(client_LIBS)