Makefile Introduction
基本概念
Makefile最重要的三个概念是目标、依赖和命令,所有的目标都是通过命令来生成,而执行命令的顺序则是由依赖关系确定。基本语法如下所示。
target: dependency
command
另外一个比较重要的是可以在Makefile中定义变量,定义的方式就是直接用等号赋值,引用变量则要用$(varname)
来表示。
基本语法
符号与规则
基本符号
- @
- 如果在命令开头,表示编译时不显示当前命令,这样可以减少不必要的输出
- -
- 如果在命令开头,表示忽略该行的错误
- $@
- 表示规则中的目标
- $*
- 目标主文件名,即去除后缀
- $^
- 表示规则中的所有依赖
- $+
- 所有依赖,未对重复项清理
- $<
- 表示规则中的第一个依赖
- $?
- 时间戳在目标之后的所有依赖
.PHONY: all all: dep1 dep2 dep3 @echo "\$$@ = $@" @echo "$$^ = $^" @echo "$$< = $<" dep1 dep2 dep3:
要输出$
符号就需要用两个,注意$@
在Bash shell中有特殊含义,所以必须要转义。
- .PHONY
- 设定假目标,防止发现和目标相同的文件时不去编译
- CURDIR
- 自动设置为当前目录
- MAKE
- 处理Makefile的命令。
- MAKECMDGOALS
- Makefile构建的目标名。
- MAKE_VERSION
- 版本号
- MAKEFILE_LIST
- 程序make读入的Makefile文件名列表
- .VARIABLES
- 程序make读入的变量列表
精简规则
如下写法表示目标文件的生成规则,避免手动输入大量重复规则。
%.o: %.c $(CC) -c $^ -o $@
更局部的一种写法是如下这样,这样可以更好的指定规则作用的范围:
$(OBJECTS): %.o: %.c $(CC) -c $^ -o $@
条件判断
条件判断包括ifdef
ifndef
ifeq
和ifneq
几个,使用必须记住以endif
结束。中间可以插入else
分支。
变量赋值
基本变量赋值
- =
- 递归赋值,调用时展开。
- :=
- 简单赋值,赋值时展开。
- ?=
- 条件赋值,调用时展开,如果已经定义就保持不变。
x = one y = $(x) two x = three a := one b := $(a) two a := three all: @echo "x = $(y), a = $(b)"
x = three two, a = one two
除了这里提到的变量定义方法,还有另外两种变量定义方式,一种是通过命令行传递,这种方法会覆盖Makefile中的定义,另外一种方式是通过shell来导出变量,即使用export定义。
高级变量赋值
如下这段代码实现批量后缀替换。
src = a.c b.c c.c header = $(src:.c=.h) all: @echo "header: $(header)"
header: a.h b.h c.h
- overide
- 用于强制避免变量被覆盖。
函数
字符串处理
- strip text
- 删除首尾空白字符,并合并多个连续空格
- first list
- 取第一个单词
- findstring str,text
- 查询文本中的字符串,没找到返回空
- sort list
- 对列表中单词排序
- subst from,to,text
- 替换文本
- patsubst regex,to,text
- 按规则替换文本
- word n,text
- 取第n个单词
- wordlist b,e,text
- 取索引在
[b,e)
范围内的单词 - words text
- 统计单词数
- filter regex list
- 从列表中获取匹配的项
- filter-out regex list
- 返回列表中不匹配的项
路径处理
- abspath path
- 将路径名转换为绝对路径名
- realpath path
- 获取真实路径
- dir list
- 获取从列表路径中解析目录名
- notdir list
- 取路径中非目录部分
- suffix list
- 取后缀
- basename list
- 取文件名去除后缀部分
- addprefix pre,list
- 增加前缀
- addsuffix suf,list
- 增加后缀
- join list1,list2
- 将两组单词对应拼接
- wildcard regex
- 获取当前目录中满足规则的文件/目录列表
其他操作
- eval text
- 相当于将文本/变量展开作为Makefile的一部分执行
- if cond,then-do[,else-do]
- 条件执行
- foreach var,list,cmd
- 将列表元素依次赋值给变量并执行命令
- call func[,vars]
- 调用函数
- shell cmd
- 执行命令
- origin var
- 返回变量来源,可以用来测试变量是否定义
- value var
- 不对变量展开,直接返回
- warning text
- 打印警告信息
- error text
- 打印错误信息,会退出执行