20230425Makefile变量

本文详细介绍了Makefile中的变量基础,包括变量赋值、替换规则,如"$(var:a=b)"和"${var//a/b}"等,并探讨了目标变量和模式变量的使用,展示了如何根据目标和源文件自定义编译选项和规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、变量基础

<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 $@

上述示例中,将两个模式变量编写了一个通用规则来生成目标文件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值