首页 > 其他 > 详细

关于Makefile的各种赋值符号和标签执行规律

时间:2014-04-06 22:41:12      阅读:1082      评论:0      收藏:0      [点我收藏+]


之前面试被问到Makefile中":="和"="的区别,真没说上来,只是通过读一些现成的Makefile猜测大概意思——”反正就是赋值呗~“

其实不光这两个, "=" ":=" "?=" "+="这几个都是常用赋值运算符,那么他们有什么区别呢?


做个试验,新建一个make文件,文件名自拟——[makefilename](默认Makefile),结构有点像switch加case:


ifdef DEFINE_VALUE
    VALUE = “Hello World!”
else
endif


ifeq ($(OPT),define)
    VALUE ?= “Hello World! First!”
endif


ifeq ($(OPT),add)
    VALUE += “Hu!”
endif


ifeq ($(OPT),recover)
    VALUE := “Hello World! Again!”
endif


all:
    @echo $(VALUE)



这是参考定义:

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

下面进行测试:


首先尝试"?=",如果他表示未赋值则赋值,设立如下对照组
make -f makefilename DEFINE_VALUE=true OPT=define
make -f makefilename DEFINE_VALUE=false OPT=define
make -f makefilename OPT=define
通过对照组的结果得知,所谓未赋值,并不是不为true,false一样算赋值,所以需要空掉,这时候"?="就会赋值。


现在尝试"+=",比较容易理解——在后边追加,和C语言字符串操作差不多,输入如下命令:
make -f makefilename DEFINE_VALUE=true OPT=add
make -f makefilename DEFINE_VALUE=false OPT=add
make -f makefilename OPT=define
没什么需要解释的,前两个结果一样,最后一个相当于给空“字符串”加了个尾巴——只有尾巴存在。


接下来是我被问到的,也是最容易碰到的问题,":="和"=":
make -f makefilename DEFINE_VALUE=false OPT=recover
make -f makefilename OPT=recover
结果一样~
如果我在ifeq ($(OPT),recover)前边加个echo或者根本不加OPT赋值,很容易就发现区别,证明":="是覆盖初始赋值。
其实"="也能赋值,此处并不能很好的表现":="的特性,而相应的比较有代表性的是这种情况:
            A := first
            B := $(A) add
            A := final
all:
@echo $(B)


            A = first
            B = $(A) add
            A = final
all:
@echo $(B)


透过结果可以看出,使用"="时,B中A的值要看最后一次定义"final",而使用":="时,B中A的值要只取决于之前的"first"。也就是说有":="的更像C语言有先后顺序,注重过程和顺序;而"="则更像我们体验到的依赖关系,是个大展开,注重结果。

PS:ifeq和后边的括号之间有空格,命令tab开头,注释#开头,依赖关系(或者判断语句?)顶格

小疑惑:
all:代表什么?代表目标all什么都不依赖就直接执行,但是产生了all文件么?也不产生!类似于#make clean是通过clean:标识实现的,同样也可以#make all(反正默认到最后
也会执行),它和#make的区别绝不是一个跳过去直接执行all,一个不执行,那样的话忽略了前边的赋值过程,#make all结果都出不来(结果是能出来)——或者不严谨的说,至少这句依赖的语句或者叫赋值过程,是都要执行的。
具体含义需深挖,但不太属于本次探讨了,本次主要关系各赋值语句区别。


做个例子吧,至少能探知使用时的规律:
#test
a=1
b=2
c=$(a)+$(b)
a:
@echo $(a)
b:
@echo $(b)
#让a总共有3次赋值(包括":=")。另加一次屏显,可以看到谁被执行了而谁被忽略了
#b=100
@echo "test"
#a=10
c:
@echo $(c)
#a:=20


输入命令:
#make a
#make b
#make c

#make a b c

#make

测试结果:
首先是执行规律,凭空的加@echo不好用,直接归类到"b:"下了,而如果试图使用b=100分割这两个echo,后边的直接无效,就是说任何命令还是要依托于类似"flag:"的形式。
除此,基本还是按选项来的,你不加参数选项"a"、"b"、"c"它自己不会执行(其实通过#make可以看出,它默认执行了a选项,也就是第一个标签,假如只有一个"all:",当然就自
动执行它了),也就是相当于#make c直接跳到"c:"标识去执行。但是依赖的参数,比如a,都会找到并且使用。

是相当于#make c直接跳到"c:"标识去执行。但是依赖的参数,比如a,都会找到并且使用
首先,凭空的@echo “test"不好用,直接归类到"b:"下了,而如果试图使用b=100分割这两个echo,后边的直接无效,就是说任何命令还是要依托于类似"flag:"的形式。
除此,基本还是按选项来的,你不加参数它自己不会执行,也就是相当于#make c直接跳到"c:"标识去执行。但是依赖的参数,比如a,都会找到并且使用


如果让a多加两次赋值(注释"#"去掉),会发现最后的c值受影响了~而且是按"a:=20"算的!好像推翻了之前的认知了??????
因为在最后加了个“按顺序执行的”冒号等于"a:=20",如果真按顺序的话,这次赋值在最后,应该不生效。哪出了错误???


其实仔细分辨,会发现研究的对象错了。


对比两例发现:
之前是B := $(A) add,本次是c=$(a)+$(b)
可以发现:
其实关键点不应该是"a:=20",是c=$(a)+$(b)

修改为:
c:=$(a)+$(b)
之后可以发现
#make c
的结果不再受后边a值变化的影响了,也就是说,在遇到关键点":="时发生一次判定,研究的目标应该是被赋值的c,而不是变量a。



关于Makefile的各种赋值符号和标签执行规律,布布扣,bubuko.com

关于Makefile的各种赋值符号和标签执行规律

原文:http://blog.csdn.net/huqinwei987/article/details/23035583

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!