1 makefile例子:关于自定义函数调用call,函数eval,foreach用法:
例子来源
https://www.gnu.org/software/make/manual/html_node/Eval-Function.html
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)_OBJS) $$($(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)
上面函数调用中会有一次call调用和一次eval调用第一个call调用后:
比如第一个参数:server,
server:$$(server_OBJS) $$(server_LIBS:%=-l%)
ALL_OBJS += $$(server_OBJS)
注意call左边那个
是函数调用的符号,不起任何其他作用然后是eval,在eval函数中如果需要
字符,那么需要输入两次
,相当于进行转义如果只有一个
,那么会将
括号里面的东西当做变量来进行替换,从而在最终展开时不存在这个
以及后面的东西
那么进行一次eval展开后:
server:$(server_OBJS) $(server_LIBS:%=-l%)
ALL_OBJS += $(server_OBJS)
由于eval是将语句展开成makefile语句,因此得到上面的语句后系统再会进行一次展开:
server:server.o server_priv.o server_access.o -lpriv -lprotocol
$(server_OBJS):对应server.o server_priv.o server_access.o
$(server_LIBS:%=-l%):对应-lpriv -lprotocol
因为foreach有一个返回值,最后面的那个处理结果,所以,有以下几个返回项:
返回字符,二返回的字符可以有以下几个作用,:
1 直接将foreach的左边是个变量,将处理的字符给到变量
2 如果foreach的左边不接变量,并且foreach的最后一项是调用了eval函数,那么作用相当于是在直接将eval中的内容展开成一条makefile语句,直接执行,而不是字符,由于eval没有返回值,因此foreach也没有返回值
3 将字符作为命令返回,需要注意的是:
make
出现“makefile:2: * 遗漏分隔符 。 停止。”问题,原因是在编写makefile文件时:
gcc、rm、cp前面是没有用tab分割符,不能用空格
另外,上面有自定义函数,个人理解自定义函数就是相当于一个宏替换
上面的代码中在函数中使用了eval函数
eval函数的作用是将一条语句展开成一条makefile语句,函数调用:
(evalxxxxxxxxx)一般函数的调用规则就是
(函数名 参数1,参数2,…)
eval注意事项:
foreach注意事项:
最好是在foreach最后面的那个括回前面加上一个分号,网上有说可加可不加,但是不加有些地方会出问题
比如下面这个例子,想循环对几个文件夹下的目录进行编译,需要注意以下几点:
1 需要将命令包起来,再加上分号,这样作为命令处理时命令之间会有分隔,否则,当前的语句会和下一句语句连接起来
2 用括号包起来还有一个作用,foreach返回这些命令时,在第二个命令cd及后面的cd命令前面会莫名其妙的加上空格,
而作为命令其前面是不能够有空格的,只能够是tab,因此包起来后加上strip,当然,将strip放在最前面也可以,经过测试,下面的没注释的是可用的,注释掉的是不能够用的
另外,下面的例子中就不要使用eval,理论上eval是可以的,但是问题出在加上eval后后面会自动的加上空格,导致出错
ADD_DIR := core
ADD_DIR += coress
.PHONY : make_all
make_all:
$(foreach dirss,$(ADD_DIR),$(strip)(cd $(dirss) && make -f $(dirss).make DELS);)
$(strip)$(foreach dirss,$(ADD_DIR),(cd $(dirss) && make -f $(dirss).make DELS);)
#$(foreach dirss,$(ADD_DIR),$(strip)cd $(dirss) && make -f $(dirss).make DELS;)
#$(foreach dirss,$(ADD_DIR),$(strip)(cd $(dirss) && make -f $(dirss).make DELS))
#$(foreach dirss,$(ADD_DIR),$(eval cd $(dirss) && make -f $(dirss).make DELS);)
#$(foreach dirss,$(ADD_DIR),$(eval $(strip)(cd $(dirss) && make -f $(dirss).make DELS));)