文章目录
一、变量基础
<variable_name>=<value>
<variable_name>:表示变量名,可以由任意字符,包括字母、数字和下划线,但第一个字符必须是字母,不能包含特殊符号,区分大小写
<value>:表示变量的值
#引用方式
$(<variable_name>)
示例↓
CFLAGS=-g -Wall
gcc $(CFLAGS) -c -o main.o main.c
变量也可以在运行过程中改变赋值
<variable_name>:=<value>
<variable_name>?=<value>
":="表示覆盖式赋值,即覆盖原先的变量
“?=“表示条件式赋值,即变量不存在时,该语句会为变量赋值
如果要使用”$“符号本身,则需要使用”$$”
"()“也可以用”{}"替换
二、变量替换
在Makefile中,可以使用变量值的替换来修改变量中保存的字符串
1、"$(var:a=b)"
将变量var中的所有以a结尾的字符串替换成以b结尾的对应字符串(结尾表示所有空格和结束符)
2、"$(var: a:=b)"
将变量var中的所有以a结尾的字符串替换成以b结尾的对应字符串,并将原始变量var中的内容替换成修改后的内容
3、"${var/a/b}"
将变量var中第一次出现的a字符串替换成b字符串
4、"${var//a/b}"
将变量var中所有a字符串替换成b字符串
foo:=a.o b.o c.o
#下两者等价 第二个使用了静态模式%
bar:=$(foo:.o=.c)
bar:=$(foo:%.o=%.c)
上述示例中,定义了一个"$(foo)“变量,再把把”$(foo)“中所有以”.o"字符结尾的字符串全部替换成".c"结尾的字符串,也就是"a.c b.c c.c”
CFLAGS = -Wall -Werror
CXXFLAGS = $(CFLAGS)
#将CFLAGS中的-Werror选项替换成-Woo-error
CXXFLAGS := \$(CXXFLAGS:-Werror=-Wno-error)
#将CFLAGS中的-Wall选项替换成-Wextra
CFLAGS := \$(CFLAGS:/Wall=/Wextra)
#将CXXFLAGS中的-std=c++11选项替换成-std=++14
CXXFLAGS := \$(subst -std=c++11,std=c++14,\$(CXXFLAGS))
5、" ( ) " 或 " ()"或" ()"或"{}"
该变量可以用在操作符的左右两边,即"$(a)=$(b)"
A := B
B := C
C := $(A)D
#输出C
x := $($(A))
#输出BD
y := $($($(A)))
#替换字符串函数$(subst <from>,<to>,<text>)
#<from>替换前的字符串
#<to>替换后的字符串
#<text>等待替换的字符
x = var1
var2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
上述示例中,将赋值式子"$($($(z)))“展开得到”$($(y))“→”$($(subst 1,2,$(x)))“→”$($(subst 1,2,var1))“→”$(var2)“→"Hello”
first_second = Hello
a = first
b = second
all = $($a_$b)
"$()"也可以用于字符串的拼接
a_obj := a.o b.o c.o
b_obj := 1.o 2.o 3.o
#x:= a or x:= b
c_obj := $($(x)_obj:.o=.c)
上述示例中,通过给变量"x"不同赋值来决定"c_obj"的值为"a.c b.c c.c"或者"1.c 2.c 3.c"
ifdef x
foo := sort
else
foo := strip
endif
bar := m a k e f i l e
x := $($(foo) $(bar))
上述示例中,展开为"$($(func) m a k e f i l e)"
如果"x"定义了,就会调用"sort"函数,“x := $(sort m a k e f i l e)”
如果"x"没定义,就会调用"strip"函数,“x := $(strip m a k e f i l e)”
注:"sort"函数用于对一组字符串列表进行字母排序并去重;“strip"函数用于去除变量值开头和接退的空白字符,并将多个空白字符替换成单个空格,即整理为单个空格为间隔的多个字符串(如"abc def ghi”)
6、"+="
#以下三者等价
#1
obj = main.o foo.o bar.o new.o
#1
obj = main.o foo.o bar.o
obj += new.o
#1
obj = main.o foo.o bar.o
obj := $(obj) new.o
7、“override”
在Makefile中,"override"命令用于强制覆盖变量的值,例如一些由make的命令行参数设置的变量,正常情况下对这些变量赋值会被忽略
override <variable> = <value>
<variable>:表示要覆盖赋值的变量名
<value>:表示新的变量
LIB := lib.a
override LIB := lib.so
#或
override LIB ;= lib.so
上述例子中,两者作用相同,区别在于":=“表示覆盖变量的值时会立即将表达式右边的值展开赋值给左边;”;="则是延迟展开,只有在变量被使用的时才会展开
override define x
obj
endef
也能和define搭配使用
三、目标变量
目标变量是一种特殊的变量,只在某些特定的目标上生效,例如忽视全局变量的值而使用自己设定的值
假设有一个Makefile文件,其中定义了"all"、“debug”、"release"三个目标,这些目标编译的源文件不同,需要使用不同的编译选项,就可以使用目标变量为每个目标设置不同的编译选项
CC = gcc
DEBUG_FLAGS = -g -Wall -Wextra
RELEASE_FLAGC = -O2
all:debug release
debug:CFLAGS = $(DEBUG_GLAGS)
debug:main_debug.o util_debug.o
$(CC) $(CFLAGS) -o debug main.o util_debug.o
release:CFLAGS = $(RELEASE_GLAGS)
release:main_release.o util_release.o
$(CC) $(CFLAGS) -o release main.o util_debug.o
main_debug.o:main.c
$(CC) $(DEBUG_FLAGS) -c main.c -o main_debug.o
util_debug.o:util.c
$(CC) $(DEBUG_FLAGS) -c util.c -o util_debug.o
main_release.o:main.c
$(CC) $(RELEASE_FLAGS) -c main.c -o main_release.o
util_release.o:util.c
$(CC) $(RELEASE_FLAGS) -c util.c -o util_release.o
在上述示例中,"all"目标依赖于"debug"和"release"目标,因此会编译两个目标文件
"debug"目标使用"DEBUG_FLAGS"变量作为编译选项
"release"目标使用"RELEASE_FLAGS"变量作为编译选项
在"debug"和"release"规则中,使用了目标变量"CFLAGS",并对其进行了设置
当编译"debug"目标时,"CFLAGS"被设置为"DEBUG_FLAGS"的值
当编译"release"目标时,"CFLAGS"被设置为"RELEASE_FLAGS"的值
这样就可以根据需要为每个目标编写不同的规则,使用不同的编译选项得到不同的编译结果
四、模式变量
模式变量是一种特殊的变量,通常用于将通用的模式匹配规则用于多个目标、多个源文件或多个命令
SRC = src/%.c
OBJ = obj/%.o
上述例子中,“SRC"模式变量定义了”.c"源文件在"src/"目录下,“OBJ"模式变量定义了”.o"目标文件在"obj/"目录下
$(OBJ):$(SRC)
$(CC) $(CFLAGS) -c $< -o $@
上述示例中,将两个模式变量编写了一个通用规则来生成目标文件