gnu make知识整理


make是什么

make是一个编译工具,能够方便我们对大型程序进行自动化的编译管理。

make官网

https://www.gnu.org/software/make/

make资料

  1. make的官方文档 https://www.gnu.org/software/make/manual/make.html
  2. make中文教程 https://www.zhaixue.cc/makefile/makefile-intro.html

知识速查

规则

  1. 规则是Makefile的基本组成单元。一个规则通常由目标、目标依赖和命令三部分构成。
  2. 命令则是如何将这些目标依赖生成对应的目标,一般是gcc命令、链接命令、objcopy命令,一些shell命令等。
  3. 一个Makefile文件里通常会有多个目标,一般会选择第一个作为默认目标
  4. 伪目标可以看做是一个标签,仅仅是为了执行某些操作。
目标:目标依赖
    命令
a.out: hello.c
    gcc -o a.out hello.c

.PHONY: clean
clean:
    rm -f a.out

变量

使用

定义变量val,使用 $(val)${val}

定义

形式 格式 含义 用途
条件赋值 ?= 条件赋值是指一个变量如果没有被定义过,就直接给它赋值;如果之前被定义过,那么这条赋值语句就什么都不做。
追加赋值 += 追加赋值是指一个变量,以前已经被赋值,现在想给它增加新的值
立即变量 := 立即展开变量 普通变量
延迟变量 = 解析阶段不会立即展开,而是等到实际使用这个变量时才展开,获得其真正的值 引用变量,始终指向最新值

自动变量

在Makefile中,大家经常会见到类似\(@、\)^、$<这种类型的变量。这种变量一般称为自动变量,自动变量是局部变量,作用域范围在当前的规则内,它们分别代表不同的含义:

  1. $@:当前目标
  2. $^:所有目标依赖
  3. $<:目标依赖列表中的第一个依赖
  4. $?:所有目标依赖中被修改过的文件
  5. $%:当规则的目标是一个静态库文件时,
  6. $%代表静态库的一个成员名
  7. \(+:类似\)^,但是保留了依赖文件中重复出现的文件
  8. \(*:在模式匹配和静态模式规则中,代表目标模式中%的部分。比如hello.c,当匹配模式为%.c时,\)表示hello
  9. $(@D):表示目标文件的目录部分
  10. $(@F):表示目标文件的文件名部分
  11. $(*D):在模式匹配中,表示目标模式中%的目录部分
  12. $(*F):在模式匹配中,表示目标模式中%的文件名部分
  13. -:告诉make在编译时忽略所有的错误
  14. @:告诉make在执行命令前不要显示命令

环境变量

  1. 若Makefile中有用户自定义的同名变量,系统环境变量将会被用户自定义的变量覆盖。
  2. 若用户在命令行中传递跟系统环境变量同名的变量,系统环境变量也会被传递的同名变量覆盖。命令行中传递的变量会覆盖Makefile中定义的变量,使用override指示符可防止被覆盖。
  3. 用户通过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…)