GNU make
make为UNIX系统下的一个工具程序,可以根据预先准备的makefile计算文件间的依赖关系,由源文件生成目标并保证目标的版本不落后与源文件,大量用于软件构建。GNU make为make的一种实现,并在标准之上增加了许多额外功能。 文档
必要知识
Makefile中文件的生成规则由运行环境的命令行解释器执行。在多数UNIX系统上,该解释器为/bin/sh
。除此之外,生成中使用到的命令也需要分别指定参数。因此,首先需要对Shell以及所使用的构建工具有基本的了解。
基础
make与makefile
Makefile中包括文件间的相互关系,说明了如何使用工具从一个文件生成另一个文件。在目录下执行make
命令并不指定makefile
时,make将会搜索合适的文件(文件名为makefile
或Makefile
)并作为makefile读取。因此,一般把它取名为Makefile
,置于需构建的项目目录。
make执行时,首先读取makefile,解析其中的规则。若在命令行上指定了构建的目标,make则会尝试生成该目标;否则,make一般会选择文件中的第一个目标进行生成。
通过传给make -j <任务数>
参数,可以使make同时构建多个目标,加快构建速度。
目标规则
目标规则指定了生成一个文件时所需要的其他文件和所运行的命令。生成规则的一般结构为:
target: [prereq...]
[<tab> command...]
其中,target
为该规则的“目标”,亦即所需要生成的文件名;prereq
为生成target
的所有依赖,可以为其他目标或文件;command
为生成target
所要执行的一系列命令(在所有的命令左侧都必须有一个Tab)。
make生成一个目标时,首先会生成它依赖中的所有目标,然后执行命令进行该目标的生成。但若一规则的目标文件存在并且其修改时间晚于任何一个依赖,则该规则未过期,生成该目标时make就会跳过命令执行阶段。生成依赖目标时,make一般会同时进行多个目标的生成。
特殊目标
在makefile中,有一部分特殊的目标并不对应生成的文件,而是用来进行配置。这类目标一般以.
开头。
.PHONY
:该目标声明其所有依赖均不对应生成的文件.MAIN
:该目标存在时,make将其作为默认目标.SUFFIXES
: 见后缀规则
变量
变量可以出现在makefile的各处。当make遇到变量时,会首先将其展开,然后再继续解析。使用变量的方式为:
$(varname)
或${varname}
。当变量名仅有一个字符时,括号可以省略。
通过设定变量,Makefile可以将重复的内容省略至一处,也可以在运行时通过执行命令确定规则的细节。设定变量的一般方式为:
var <mod>= value
其中,var
为变量名,value
为需要设定的值。根据符号mod
的不同,var
的赋值效果不同。常见的赋值符号有:
mod
为空,即var = value
:以value
替换var
的值mod
为+
,即var += value
:在var
后附加value
mod
为?
,即var ?= value
:若var
之前未定义,则以value
替换mod
为!
,即var != value
:将value
作为命令执行,然后取其输出替换var
的值
在规则中,有一部分变量为预定义:
$@
:目标的文件名$*
:不含后缀的目标文件名
后缀规则
后缀规则用来定义不同类型文件之间的转换规则,以避免针对每一个文件都要明确制定规则的麻烦。使用后缀规则时,首先需要将需要写入规则的文件类型的后缀列在.SUFFIXES
特殊目标的依赖中,例如:
.SUFFIXES: .c .o
后缀规则的结构为:
sfxrule:
[<tab> command...]
其中,sfxrule
为转换的两种类型的后缀名的连接,若目标类型无后缀则只用一个类型的后缀。在后缀规则的命令中,可以使用预定义的变量$<
用来表示该规则的依赖。例如:
.c.o:
$(CC) $(CCFLAGS) -c -o $@ $<
.o:
$(CC) $(LDFLAGS) -o $@ $<