Makefile基本概念
下面这些是在项目的Makefile中会用到的, 主要就说一下赋值和$
方法
赋值=
, :=
, ?=
, +=
Makefile中的赋值, 可以赋值一个列表, 例如VAR = dir1 dir2 dir3
= 赋值
make会将整个Makefile展开后, 再决定变量的值, 也就是说变量的值会是整个 Makefile 中最后被指定的值
x = foo
y = $(x) bar
x = xyz
y的值会是 xyz bar ,而不是 foo bar
:= 赋值
表示变量的值等于 Makefile 执行到此处时的值, 而不是整个 Makefile 展开后的最终值
x := foo
y := $(x) bar
x := xyz
y的值将会是 foo bar ,而不是 xyz bar
:=赋值可以用来避免递归问题, 例如下面的赋值
CC = gcc
CC = ${CC}
all:
@echo ${CC}
会报错
$ make
Makefile:8: *** Recursive variable 'CC' references itself (eventually). Stop.
如果改成:=赋值就没问题了
CC := gcc
CC := ${CC}
all:
@echo ${CC}
?= 赋值
- 如果已经赋值, 就不变
- 如果没有被赋值过, 就赋予等号后面的值
+= 赋值
添加等号后面的值
Makefile 中$
的用法
$
在Makefile中是一种重要的符号
(...)或(...)或{...}的方法
$()
和${}
是一样的, 执行括号内的内容, 类似于eval, 将整个$(...)替换为执行的结果字符串
直接执行
例如$(VAR = 4)
表示执行shell命令VAR = 4
, 因为无返回, 所以不会有任何操作
shell 执行shell命令
$(shell cc $(SDK_TOOLS)/wm_getver.c -Wall -O2 -o $(VER_TOOL))
这个命令表示, 在shell下执行后面的命令
abspath 返回绝对路径
PATH = $(abspath $(TOP_DIR))
获取绝对路径
dir 返回目录字符串
SUBDIRS ?= $(patsubst %/,%,$(dir $(wildcard */Makefile)))
, 获取所有Makefile的目录, 并去除结尾的斜杆
substr 字符串替换
TARGET ?= $(subst FROM, TO, TEXT)
, 这个命令会将字符串TEXT中的子串FROM变为TO后返回, 然后返回的值赋值给TARGET
patsubst 匹配替代
patsubst是patten substitude的缩写,匹配替代的意思
OBJ = $(patsubst %.c, %.o, $(SRC))
, 在SRC中找到所有.c 结尾的文件,然后把所有的.c换成.o。
与使用OBJ = $(SRC:%.c=%.o)
效果一样.
wildcard 列出文件
$(wildcard pattern)
是用于用于匹配列出文件名的方法
SRCS := $(wildcard *.c)
这个表达式中, 所有以.c结尾的文件名都会被赋值给变量SRCS
.CCFILES += $(wildcard src/*.cpp)
, 将匹配后面通配符的文件都列出, 并追加赋值给CCFILES
$(变量名:% = %) 替代
BINS := $(SRCS:%.c=%)
这种方式属于替代赋值, 在这个表达式中, 如果变量 SRCS 的值为 'foo.c bar.c', 变量 BINS 将被赋值 'foo bar'.
notdir 去除目录信息
SRC = $(notdir wildcard)
, 去除所有的目录信息,SRC里的文件名列表将只有文件名
foreach 循环处理
格式为 $(foreach var, list, express)
, 把参数list
中的单词逐一取出放到参数var
所指定的变量中, 然后再执行express
所包含的表达式. 每一次express
会返回一个字符串, 循环过程中express
的所返回的每个字符串会以空格分隔, 最后当整个循环结束时, express
所返回的每个字符串所组成的整个字符串(以空格分隔)就是foreach函数的返回值.
所以: var
是一个变量, list
可以是一个表达式或者一个列表变量, 而express
一般是一个命令表达式, 用于处理var
.
例子一
在递归编译中常用的 $(foreach d, $(SUBDIRS), $(MAKE) -C $(d);)
, 将SUBDIRS中收集到的目录, 值依次执行$(MAKE) -C $(d)
.
例子二
names := a b c d
files := $(foreach n,$(names),$(n).o)
将names中的值依次加上.o, 再赋值给files, $(files)的值变为a.o b.o c.o d.o