makefile中的变量
1.变量的定义和使用
在makefile里的变量只有一种类型,字符串。
定义: var = hello
使用: $(var) 或 ${var} 变量名前使用$符号,并用中括号打大括号把变量名括起来。你可以在目标,依赖,更新方法等任何地方使用变量
var = hello |
$(info xxx) 这是一个函数,具体会在下一章讲, 大致用法就是把XXX替换为你想打印的东西就可以了。
var1 = hello |
2.不同的看待方式
对于makefile里的变量,它确确实实只能存放一种数据类型,那就是字符串,但makefile里的变量既可以是字符串,也可以是字符串数组。或者列表。
var1 = hello |
我们可以使用一些函数来对数组进行操作。
我们想要获取数组的第n个元素,可以使用word函数来进行操作。
var = hello world this is a array |
更多的关于列表的函数请看下一章。
3.变量展开
我们先讨论一下的make的工作方式,大致步骤如下:
- 读取所有makefile
- 读取include的makefile
- 初始化文件中的变量
- 推导隐式规则
- 为所有目标文件创建依赖
- 根据依赖关系,决定哪些目标要重新生成
- 执行命令
1-5为第一阶段,6-7为第二阶段。我们在这里只关心和变量有关的工作步骤。
在第一阶段展开的成为立即展开,第二阶段的成为延迟展开。
可能这么说你不是很清楚,我们看下具体的例子。
4.延迟展开
直接使用=,这种方式如果赋值的时候右边是其他变量引用或者函数调用之类的,将不会做处理,直接保留原样,在使用到该变量的时候再来进行处理得到变量值(Makefile执行的第二个阶段再进行变量展开得到变量值)
var2= $(var) |
我们根据make的工作方式来看看这个变量到底发生了什么。
- 读取这个makefile
- 没有include,忽略
- 初始化变量,根据从上往下
- 定义var2,延迟展开,此时var2的值为$(var)
- 定义var,值为world
- 推到隐式规则
- 创建依赖
- 决定生成all这个目标
- 执行all里的更新方法,打印var2
- $(info $(var2)) 这里要输出var2的值,延迟展开,找到定义var的地方,把var的值拿过来
5.立即展开
赋值使用:=或::=,这种方式如果等号右边是其他变量或者引用的话,将会在赋值的时候就进行处理得到变量值。(Makefile执行第一阶段进行变量展开)
var2:= $(var) |
- 读取这个makefile
- 没有include,忽略
- 初始化变量,根据从上往下
- 定义var2,立即展开,值为空,因为找不到var变量
- 定义var,值为world
- 推到隐式规则
- 创建依赖
- 决定生成all这个目标
- 执行all里的更新方法,打印var2
- $(info $(var2)) 这里要输出var2的值 空
6.条件赋值
条件赋值使用?=
,如果变量已经定义过了(即已经有值了),那么就保持原来的值,如果变量还没赋值过,就把右边的值赋给变量。
var1 = 100 |
7.追加赋值
使用+=在变量已有的基础上追加内容
files = main.cpp |
8.shell运行赋值
使用!=,运行一个Shell指令后将返回值赋给一个变量
gcc_version != gcc --version |
9.定义多行变量
前面定义的变量都是单行的。
变量值有多行,多用于定义shell指令
define <varable_name> # 默认为 = |
var = @echo This is the first line |
10.自动变量
$@:目标名
$<:依赖里第一个的名称
$?:比目标新的依赖(依赖的修改时间晚于目标)的名字
$^:所有依赖的名字(去重) 不包含order-only
$+:同上,包含重复,但不包含order-only
$|:order-only
$*:目标主干部分,不包含后缀名
demo:demo.o |
11.其他
清除变量
var = hello |
使用环境变量
系统中的环境变量可以直接在Makefile中直接使用,使用方法跟普通变量一样。
all: |
变量替换引用
语法:__$(var:a=b)__,意思是将变量var的值当中每一项结尾的a替换为b,直接上例子。
files = main.cpp hello.cpp |