您的位置:首页 > 其它

Makefile赋值符号的使用——"=" ":=" "?=" "+="

2016-06-29 09:15 330 查看
原文地址:http://blog.csdn.net/huqinwei987/article/details/23035583

##############################################################################################################################

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

其实不光“:=”和“=”, "=" ":=" "?=" "+="这几个都是常用赋值运算符,都应该知道,那么他们有什么区别呢?

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



这是参考定义:
= 是最基本的赋值

:= 是覆盖之前的值

?= 是如果没有被赋值过就赋予等号后面的值

+= 是添加等号后面的值

下面进行测试:

首先尝试"?=",如果他表示未赋值则赋值,设立如下对照组:



关于ifdef语句,通过第一个对照组的结果得知,并不是

DEFINE_VRE=true

才算定义了,

DEFINE_VRE=false

一样算~!

这样的话就会执行ifdef中的给VRE赋“Hello World!”语句。



DEFINE_VRE=

代表未定义,在缺乏理论依据的前提下武断的说一下——这句写了等于没写。。。。

DEFINE_VRE

是不被允许的写法(好像意思是DEFINE_VRE也成了一个需要被make目标文件了)

所以只要不定义DEFINE_VRE,"?="就会起作用,我起了直观的名字——“未定义,则定义!”——这,就是缺省~!

现在尝试"+=",这个比较直观,比较容易理解——在后边追加,和C语言字符串的拼接效果差不多,输入如下命令:



关于true、false和空格,前边已经提到了。不管是默认的空字符串,还是HelloWorld字符串,“+=”都相当于加了个尾巴。

接下来是我被问到的,也是最容易碰到的问题,":="和“=”,先看看“:=”的效果:



结果一样~果断全都覆盖掉,overwrite名副其实。

======================================================================================================================================================================================================================================

这也引起了那个我被问到的问题,":="和“=”的区别?

如果我在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开头,注释#开头,@echo与echo的区别是"echo"四个字母是否显示出来,依赖关系(或者判断语句?)顶格

小疑惑:

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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: