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

13 篇文章 0 订阅
11 篇文章 0 订阅


之前面试被问到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。



  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值