Makefile override 指示符
一个变量可以定义在Makefile中,也可以在执行make时通过命令行定义。一个在Makefile中定义的变量,如果在执行make命令时又定义了一次,那么它将替代在Makefile中出现的同名变量。也就是说,在一个Makefile中使用define、:=、= 定义的变量,我们可以在执行make命令时重新指定这个变量的值。
.PHONY: all
web = www.zhaixue.cc
all:
@echo "web = $(web)"
在上面的Makefile中,我们定义了一个变量:web,在执行make时如果重新给web赋值,然后在Makefile中就可以打印出重新赋的值:
# make
web = www.zhaixue.cc
# make web=wanglitao.taobao.com
web = wanglitao.taobao.com
如果不希望在命令行指定的变量值替代在Makefile中的原来定义,那么我们可以在Makefile中使用指示符 override 对这个变量进行声明:
.PHONY: all
override web = www.zhaixue.cc
all:
@echo "web = $(web)"
一个变量使用override修饰后,用户在命令行中重新赋值,不会对Makefile中的变量定义产生影响,无论用户在命令行中如何修改,make始终打印的是Makefile中定义的值:
# make web=wanglitao.taobao.com
web = www.zhaixue.cc
追加赋值
Makefile中的变量分为多种:追加变量、立即变量、展开变量、使用define定义的变量,它们都可以使用override修饰:
override VARIABLE = VALUE
override VARIABLE := VALUE
override VARIABLE += MORE TEXT
override define foo
当一个追加变量在定义时使用了override,后续对它的值进行追加时,也需要使用带有override指示符的追加方式。否则对此变量值的追加不会有效。
.PHONY: all
override fruits = apple
fruits += banana
all:
@echo "fruits = $(fruits)"
如上面定义的fruits变量,在定义时因为使用了override修饰,在对其追加赋值时,因为没有使用override修饰,所以追加是无效的“
# make
fruits = apple
override存在的意义
override的主要目的是为了使用户可以改变或者追加哪些使用make命令行指定的变量的定义。从另一个角度上看,就是实现了在Makefile中增加或者修改命令行参数的一种机制。
我们在编译程序时,可能会有这样一些需求:通过命令行来指定一些额外的编译参数。而对于一些通用或者必需的参数则在Makefile中指定,一些特殊的参数则在命令行中指定。
比如在编译程序时,无论在命令行指定什么参数,编译器在编译时必需打开 -Wall选项,那么在Makefile中的CFLAGS应该这样定义:
.PHONY: all
override CFLAGS += -Wall
all:
@echo "CFLAGS = $(CFLAGS)"
当执行make命令时,默认的CFLAGS是-Wall;当执行make CFLAGS=-g时,CFLAGS就变成了 -Wall -g:
# make
CFLAGS = -Wall
# make CFLAGS=-g
CFLAGS = -g -Wall
如果在Makefile中定义CFLAGS变量时,不使用override修饰:
.PHONY: all
CFLAGS += -Wall
all:
@echo "CFLAGS = $(CFLAGS)"
再次执行上面的make命令,运行结果就发生了变化:
# make
CFLAGS = -Wall
# make CFLAGS=-g
CFLAGS = -g
这就跟我们预先设定的不一致了:当在命令行中给CFLAGS追加赋值时,原来的-Wall选项就被覆盖掉了。而使用override修饰就不会发生这种情况。