好记性不如铅笔头

linux, 操作系统

Makefile的二次解析简单笔记

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

makefile中的“立即展开”与“延后展开”

本文参考【 http://blog.csdn.net/shyanyang/article/details/7529795

GUN make的执行过程分为两个阶段。

第一阶段:读取所有的makefile文件(包括“MAKEFILES”变量指定的、指示符“include“指定的、以及命令行选项“-f(–file)“指定的makefile文件),内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间关系结构链表。

第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则來重建这些目标。

1.在make执行的第一阶段如果变量和函数被展开,那么称此展开是“立即“的,其他的展开称之为“延后“的。
2.变量定义解析规则如下:

    IMMEDIATE = DEFERRED  
    IMMEDIATE ?= DEFERRED  
    IMMEDIATE := IMMEDIATE  
    IMMEDIATE += DEFERRED or IMMEDIATE  
    define IMMEDIATE  
            DEFERRED  
    Endef  

当变量使用追加符 += 时,如果此前这个变量是一个简单变量(使用:=定义的)则认为它是立即展开的,其他情况时都被认为是“延后“展开的变量。

3.所有使用到条件语句在产生分支的地方,make程序会根据预设条件将正确的分支展开。即条件分支的展开是“立即“的。其中包括:“ifdef”、“ifeq“、”ifndef“和“ifneq“所确定的所有分支命令

4.所有的规则在make执行时,都按照如下的模式展开:

    IMMEDIATE:IMMEDIATE;DEFERRED  
            DEFERRED 

注:上面的IMMEDIATE表示立即展开,DEFERRED表示延后展开

这里立即和延后的示例如下:

VAL1  = 1
VAL2 := 2
VAL3  =  $(abspath .)
VAL4 :=  $(abspath .)

VAL5  = $(VAL3)
VAL6 := $(VAL3)
VAL3 = 3

SHOWARGS:
	@echo "VAL1: $(VAL1)" 
	@echo "VAL2: $(VAL2)" 
	@echo "VAL3: $(VAL3)" 
	@echo "VAL4: $(VAL4)" 
	@echo "VAL5: $(VAL5)" 
	@echo "VAL6: $(VAL6)" 	

执行结果如下:

cstriker1407-T450-ubuntu:~/MakefileTest$ make
VAL1: 1 #延后展开,但由于是简单变量,因此无所谓
VAL2: 2 #立刻展开,但由于是简单变量,因此无所谓
VAL3: 3 #延后展开,而且被改了值
VAL4: /home/cstriker1407/MakefileTest #立刻展开
VAL5: 3 #延后展开,VAL3的值改变会更新,即第一次展开为VAL5=$(VAL3), 第二次展开为VAL5=3
VAL6: /home/cstriker1407/MakefileTest 
#立刻展开,第一次展开为VAL6=/home/cstriker1407/MakefileTest,虽然后面VAL3被修改了,但是VAL6已经展开了,不会在变动

 

发表评论

5 × 1 =

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