好记性不如铅笔头

linux, 操作系统, 编程

Makefile的eval的一些网址记录

最近在搞Makefile的时候掉进了一个大坑里,爬了好久。这里简单的笔记下Makefile的一些概念:。

CONTENTS

eval:

官方DEMO:

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

"It's important to realize that the eval argument is expanded twice; first by the eval function, then the results of that expansion are expanded again when they are parsed as makefile syntax."


Take the example from GNU Make for example:
------------------------------------------------


     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)


--------------------------------
How to understand the twice replace for eval:
In foreach:
  "eval $(call PROGRAM_template, server)"
1st time replacement, 'PROGRAM_template' is executed as shell:
  "server: $(server_OBJS) $(server_LIBS:%=-l%)
2nd time replacement, execute as makefile:
  server: $server_OBJS -l$server_LIBS
--------------------------------

网址参考1

http://blog.csdn.net/eddy_liu/article/details/8210804
函数功能:函数“eval”是一个比较特殊的函数。使用它我们可以在我们的Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。函数“eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。
返回值:函数“eval”的返回值时空,也可以说没有返回值。

函数说明:“eval”函数执行时会对它的参数进行两次展开。第一次展开过程发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。
实际使用时,当函数的展开结果中存在引用(格式为:$(x))时,那么在函数的参数中应该使用“$$”来代替“$”。因为这一点,所以通常它的参数中会使用函数“value”来取一个变量的文本值。

网址参考2

http://blog.csdn.net/brooknew/article/details/8452358  】

函数原型 $(eval text)
它的意思是 text 的内容将作为makefile的一部分而被make解析和执行。

比如这样一个makefile:

$(eval xd:xd.c a.c)
#将会产生一个这样的编译
cc   xd.c a.c -o xd

这样一个makefile:

define MA
aa:aa.c
 gcc  -g -o aa aa.c
endef 
$(eval $(call MA) )

#会产生一个这样的编译:
gcc -g -o aa aa.c

这样的makefile:

OBJ=a.o b.o c.o d.o main.o

define MA
main:$(OBJ)
 gcc  -g -o main $$(OBJ)
endef 

$(eval $(call MA) )

#会产生这样的编译过程:
cc -c -o a.o a.c
cc -c -o b.o b.c
cc -c -o c.o c.c
g++ -c -o d.o d.cpp
cc -c -o main.o main.c
gcc -g -o main a.o b.o c.o d.o main.o

请注意到$$(OBJ) ,因为make要把这个作为makefile的一行,要让这个地方出现$,就要用两个$,因为两个$,make才把把作为$字符。

网址参考3

【 http://blog.csdn.net/crylearner/article/details/17271195
eval有两个特点
1. 做两次变量展开;以$(eval var),首先会对var做一次变量展开,然后对展开后的结果,再执行一次变量展开。
2. $(eval var)返回为空。这个特性被大量使用于宏定义define中。

#函数返回
# $(1): [IN] BASE_DIR
# return: SRC_FILE_ARR
define add_source_file_from_base_dir
	$(eval SRC_DIRS = $(1) ) \
	$(eval TMP_FILE_ARR = $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c)) ) \
	$(TMP_FILE_ARR)
endef

 

发表评论

2 + 3 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据