在 makefile 中是支持程序设计语言中变量的概念的,makefile 中的变量只代表文本数据(字符串)。那么在 makefile 中的变量名的规则又有哪些呢?a> 变量名可以包含字符、数字以及下划线;b> 不能包含 ":" , "#" , "=" 或 " ";c> 变量名大小写敏感。下来我们来看看变量的定义和使用,如下
下来我们以代码为例来进行分析说明
CC := gcc TARGET := hello.out $(TARGET) : func.o main.o $(CC) -o $(TARGET) func.o main.o func.o : func.c $(CC) -o func.o -c func.c main.o : main.c $(CC) -o main.o -c main.c .PHONY : rebuild clean all rebuild : clean all all : $(TARGET) clean : rm *.o $(TARGET)
我们来看看编译结果是否和之前一样
效果和之前是一样的,那么我们为何这样定义变量呢?在一些大型的工程项目中,我们可能要编译好几个版本,因此定义不同的 TARGET 便会编译出不同的版本。而且这种方法还有个好处就是编译器可以由我们自定义选择,比如我们将上面的 gcc 编译器换成 g++,则只需将 CC := gcc 换成 CC := g++,下来我们来看看编译效果
我们看到编译器已经换为 g++ 了。下来我们来讲讲 makefile 中变量的赋值方式,分为四种:a> 简单赋值(:=);b> 递归赋值(=);c> 条件赋值(?=);d> 追加赋值(+=)。那么不同的赋值方式其意义是不同的!下来我们来对这四种赋值方式进行一一的解释说明
a> 简单赋值(:=):程序设计语言中的通用的赋值方式,只针对当前语句的变量是有效的。其用法如下
b> 递归赋值(=):赋值操作可能影响多个其他变量,所有与目标变量相关的其他变量都将受到影响。其用法如下
c> 条件赋值(?=):如果变量未定义,使用赋值符号中的值定义变量;如果变量已经定义,则赋值无效。其用法如下
d> 追加赋值(+=):原变量值之后加上一个新值,原变量值与新值之间由空格隔开。其用法如下
下来我们还是以代码为例来进行说明
# ex1 (:=) x := foo y := $(x)b x := new .PHONY : test test : @echo "# ex1 (:=)" @echo "x => $(x)" @echo "y => $(y)"
经过简单赋值后,x 就为 new 了,而 y 则应该为 foob。我们来看看编译效果
我们看到结果和我们所分析的是一样的。下来我们来看看递归赋值
# ex2 (=) x = foo y = $(x)b x = new .PHONY : test test : @echo "# ex2 (=)" @echo "x => $(x)" @echo "y => $(y)"
我们分析下,因为递归赋值是与目标相关的其他变量都会受到影响,那么 x 最后应该为 new,y 就应该为 newb。我们来看看编译结果
为了更加形象对递归赋值进行说明,我们编写代码如下
a = $(b) b = $(c) c = hello-makefile .PHONY : test test : @echo "# ex2 (=)" @echo "x => $(x)" @echo "y => $(y)" @echo "a => $(a)" @echo "b => $(b)" @echo "c => $(c)"
我们定义 a 依赖于 b,而 b 依赖于 c。此时 c 为 hello-makefile,那么依赖于它的 b 也就变为 hello-makefile 了,此时依赖于 b 的 a 也就变为 hello-makefile 了。x 和 y 此时没定义,看看编译会报错吗?
编译是通过的,证明在 makefile 中是支持这样的写法的,x 和 y 没定义,自然也就为空了。那么 a,b,c 和我们所分析的是一样的。所以在 makefile 中我们一般是很少直接用递归赋值的,因为有可能会意想不到地改变依赖于它的目标。下来我们来看看条件赋值
# ex3 (?=) x := foo y := $(x)b x ?= new .PHONY : test test : @echo "# ex3 (?=)" @echo "x => $(x)" @echo "y => $(y)"
我们在最后对 x ?= new,意思是如果前面没定义的话,此时它便为 new。所以 x 最后应该为 foo,y 就应该为 foob。我们来看看编译结果
结果确实是这样的,一般我们会在新定义变量时采用这样的写法,以防止改变之前定义时的语义。最后看看追加赋值
# ex4 (+=) x := foo y := $(x)b x += new .PHONY : test test : @echo "# ex4 (+=)" @echo "x => $(x)" @echo "y => $(y)"
根据追加赋值的定义,它是直接在后面加上,但是有一个空格。所以 x 最后应该为 foo new,y 就应该为 foob。我们来看看编译结果
我们看懂啊效果确实是这样的,通过对四种赋值方式的学习,我们发现简单赋值是跟 C 语言中是一样的。追加赋值和 C++ 语言中的语义也是一样的,一般在大型项目中是不会采用递归赋值这种写法的。
欢迎大家一起来学习 makefile,可以加我QQ:243343083。
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/182962.html