3.1 make 命令的使用

make为UNIX系统下的一个工具程序,可以根据预先准备的makefile计算文件间的依赖关系,由源文件生成目标并保证目标的版本不落后与源文件,大量用于软件构建。GNU make为make的一种实现,并在标准之上增加了许多额外功能。 文档

必要知识

Makefile中文件的生成规则由运行环境的命令行解释器执行。在多数UNIX系统上,该解释器为/bin/sh。除此之外,生成中使用到的命令也需要分别指定参数。因此,首先需要对Shell以及所使用的构建工具有基本的了解。

基础

make与makefile

Makefile中包括文件间的相互关系,说明了如何使用工具从一个文件生成另一个文件。在目录下执行make命令并不指定makefile时,make将会搜索合适的文件(文件名为makefileMakefile)并作为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 $@ $<

Last updated