Makefile赋值符号的使用——"=" ":=" "?=" "+="
2014-04-06 17:38
375 查看
之前面试被问到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。
其实不光“:=”和“=”, "=" ":=" "?=" "+="这几个都是常用赋值运算符,都应该知道,那么他们有什么区别呢?
做个试验,新建一个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。
相关文章推荐
- Makefile赋值符号的使用——"=" ":=" "?=" "+="
- Makefile赋值符号的使用——"=" ":=" "?=" "+="
- linux gdb 没有符号表被读取。请使用 "file" 命令。
- makefile 中":"和":="赋值的区别
- Regex.Split 在分割 "|" 符号时出现问题,应该使用 "[|]" 才可以分组
- 使用jquery attr 赋值后 "&" 变成了"&"
- 使用log4cplus时遇到的链接错误:无法解析的外部符号 "public: __thiscall log4cplus::RollingFileAppender::RollingFileAppende
- 坑爹的radio 多次操作 赋值无效 得使用 prop("checked", true);
- SHELL 数组:数组赋值中符号使用不正确(应该严格按"()"赋值),赋值后不能正确求出数组的长度。
- linux gdb 没有符号表被读取。请使用 "file" 命令。
- makefile文件的使用-"自动化编译"
- codeblock无法进行调试,没有符号表被读取。请使用 "file" 命令。
- 开发日志:使用jquery读取id含./"等特殊符号的对象
- 对于String对象,可以使用"="赋值,也可以使用"new"关键字赋值,两种方式有什么区别?
- makefile中"-"符号的使用
- 这段程序中 R "找不到符号",是什么原因,请帮助,谢谢!
- 无法启动链接服务器 "........" 的 OLE DB 访问接口 "SQLNCLI10" 的嵌套事务。由于 XACT_ABORT 选项已设置为 OFF,因此必须使用嵌套事务。
- 使用Retrofit时出现 java.lang.IllegalArgumentException: URL query string "t={type}&p={page}&size={count}" must not have replace block. For dynamic query parameters use @Query.异常原因
- extern "c"使用
- 使用Axis插件来从WSDL文件生成代码时"An error occurred while completing process -java.lang.reflect.InvocationTargetException"的错误