gnu make知识整理
make是什么
make是一个编译工具,能够方便我们对大型程序进行自动化的编译管理。
make官网
https://www.gnu.org/software/make/
make资料
- make的官方文档 https://www.gnu.org/software/make/manual/make.html
- make中文教程 https://www.zhaixue.cc/makefile/makefile-intro.html
知识速查
规则
- 规则是Makefile的基本组成单元。一个规则通常由目标、目标依赖和命令三部分构成。
- 命令则是如何将这些目标依赖生成对应的目标,一般是gcc命令、链接命令、objcopy命令,一些shell命令等。
- 一个Makefile文件里通常会有多个目标,一般会选择第一个作为默认目标。
- 伪目标可以看做是一个标签,仅仅是为了执行某些操作。
目标:目标依赖
命令
a.out: hello.c
gcc -o a.out hello.c
.PHONY: clean
clean:
rm -f a.out
变量
使用
定义变量val,使用 $(val)
或 ${val}
定义
形式 | 格式 | 含义 | 用途 |
---|---|---|---|
条件赋值 | ?= | 条件赋值是指一个变量如果没有被定义过,就直接给它赋值;如果之前被定义过,那么这条赋值语句就什么都不做。 | |
追加赋值 | += | 追加赋值是指一个变量,以前已经被赋值,现在想给它增加新的值 | |
立即变量 | := | 立即展开变量 | 普通变量 |
延迟变量 | = | 解析阶段不会立即展开,而是等到实际使用这个变量时才展开,获得其真正的值 | 引用变量,始终指向最新值 |
自动变量
在Makefile中,大家经常会见到类似\(@、\)^、$<这种类型的变量。这种变量一般称为自动变量,自动变量是局部变量,作用域范围在当前的规则内,它们分别代表不同的含义:
- $@:当前目标
- $^:所有目标依赖
- $<:目标依赖列表中的第一个依赖
- $?:所有目标依赖中被修改过的文件
- $%:当规则的目标是一个静态库文件时,
- $%代表静态库的一个成员名
- \(+:类似\)^,但是保留了依赖文件中重复出现的文件
- \(*:在模式匹配和静态模式规则中,代表目标模式中%的部分。比如hello.c,当匹配模式为%.c时,\)表示hello
- $(@D):表示目标文件的目录部分
- $(@F):表示目标文件的文件名部分
- $(*D):在模式匹配中,表示目标模式中%的目录部分
- $(*F):在模式匹配中,表示目标模式中%的文件名部分
- -:告诉make在编译时忽略所有的错误
- @:告诉make在执行命令前不要显示命令
环境变量
- 若Makefile中有用户自定义的同名变量,系统环境变量将会被用户自定义的变量覆盖。
- 若用户在命令行中传递跟系统环境变量同名的变量,系统环境变量也会被传递的同名变量覆盖。命令行中传递的变量会覆盖Makefile中定义的变量,使用override指示符可防止被覆盖。
- 用户通过export命令定义变量,1. make执行前export,2.Makefile文件中export。
条件判断
ifeq、ifneq、ifdef、ifndef
等关键字来进行条件判断。
例如,ifeq一般和变量结合使用,条件判断语句由三个关键字组成:ifeq、else、endif。ifeq后面的比较语句使用小括号抱起来,ifeq和小括号之间要用空格隔开,小括号里的两个参数用逗号隔开。当小括号里的条件满足时,make就会执行这个分支的命令,否则执行else部分。endif表示一个条件语句的结束。
函数
函数的使用和变量引用的展开方式相同:
$(function arguments)
${function arguments}
关于函数的使用格式,有以下需要注意的地方:
-
函数主要分为两类:
make内嵌函数
和用户自定义函数
。对于 GNU make内嵌的函数,直接引用就可以了;对于用户自定义的函数,要通过make的call函数来间接调用。 -
函数和参数列表之间要用空格隔开,多个参数之间使用逗号隔开。
-
如果在参数中引用了变量,变量的引用建议和函数引用使用统一格式:要么是一对小括号,要么是一对大括号。
-
自定义函数
define func
@echo "pram1 = $(0)"
@echo "pram2 = $(1)"
endef
all:
$(call func, hello, zhaixue.cc)
用户自定义函以define开头,endef结束,给函数传递的参数在函数中使用\((0)、\)(1)引用,分别表示第1个参数、第2个参数…
对于用户自定义函数,在Makefile中要使用call函数间接调用,各个参数之间使用空格隔开。
函数 | 格式 | 作用 |
---|---|---|
subst | $(subst old,new,text) | 将字符串text中的old替换为new,\((subst .c,.o,\)(SRC)) |
patsubst | $(patsubst PATTERN, REPLACEMENT, TEXT) | 模式替换 |
strip | STRIP_STR = $(strip STRS...) | strip函数用来将多个连续的空字符合并成一个,并去掉字符串开头、末尾的空字符,空字符包括:空格、多个空格、tab等不可显示的字符。 |
findstring | $(findstring FIND, IN) | findstring函数会在字符串IN中查找“FIND”字符串,如果找到,则返回字符串FIND,否则,返回空。 |
filter | $(filter PATTERN…,TEXT) | filter函数用来过滤掉字符串TEXT中所有不符合PATTERN模式的单词,只留下符合PATTERN格式的单词。 |
filter-out | $(filter-out %.c, FILES) | 该函数会过滤掉所有符合PATTERN模式的单词,保留所有不符合此模式的单词。 |
dir | $(dir NAMES…) | dir函数用来从一个路径名中截取目录的部分 |
notdir | $(notdir NAMES..) | 取文件名 |
suffix | $(suffix NAMES…) | 取文件名前缀 |
basename | $(basename NAMES…) | 取文件名后缀,包含路径部分 |
addsuffix | $(addsuffix SUFFIX, NAMES…) | 给文件列表添加后缀 |
addprefix | $(addprefix PREFIX, NAMES…) | 给文件列表添加前缀 |
wildcard | $(wildcard PATTERN) | 列出当前目录下所有符合PATTREN模式的文件名 |
foreach | $(foreach VAR,LIST,TEXT) | 把LIST中使用空格分割的单词依次取出并赋值给变量VAR,然后执行TEXT表达式。重复这个过程,直到遍历完LIST中的最后一个单词。 |
reference
https://www.gnu.org/software/make/manual/make.html#Functions
error和warning
make提供了两个可以控制make运行方式的函数:error和warning。当make执行过程中检测到某些错误,就可以给用户提供一些信息,并且可以控制make的是否继续执行下去。
-
error 函数
error函数是在函数被调用时才会提示信息并
终止make的继续执行
。
$(error TEXT…)
- warning函数
warning函数跟error函数类似,也会给用户提示信息,唯一的区别是:warning函数不会终止make的运行,make会继续运行下去。
$(warning TEXT…)