make 命令

用途

维护、更新和重新生成程序组。

语法

make [ -D变量 ] [ -d 选项 ] [ -e ] [ -i ] [ -j[作业]] [ -k ] [ -n ] [ -p ] [ -q ] [ -r ] [ -S ] [ -s ] [ -t ] [ -f MakeFile ... ] [ Target ... ]

描述

make 命令辅助您维护程序集。 输入 make 命令的是一个文件相关性规范列表。

在 makefile 中有四种类型的行:文件相关性规范、shell 命令、变量赋值和注释。 通常,各行可通过以一个 \ (反斜杠) 结束来继续到下一行。 以下行的末尾换行符和开头空白处都压缩成一个空格。

文件依赖性规范

相关性行由一个或多个目标、一个运算符和零或更多的先决条件(源)构成。 这就建立了一种关系,其中目标取决于先决条件且通常创建自先决条件。 在目标和先决条件之间的精确关系由分隔它们的运算符来确定。 运算符如下所示:

描述
: 如果目标的修改时间小于它的任何先决条件,那么将目标视为过期。 在使用此运算符时,目标的先决条件是通过相关性行积累的。 除非目标有 .PRECIOUS 属性,否则如果 make 命令中断,那么该目标将被删除。
:: 如果没有指定先决条件,那么始终重新创建目标。 否则,如果目标的任何先决条件都比目标修改得更晚,那么将该目标认为过期。 在使用此运算符时,目标的先决条件不通过相关性行积累。 如果 make 命令中断,那么不会删除目标。

文件相关性规范有两种类型的规则:推论和目标。 推论规则指定目标如何才是最新的。 这些规则有一个不带 /(斜杠)的目标和至少一个 . :NONE. 目标规则指定如何构建目标。 这些规则能够有多个目标。

Makefile 执行

make 命令逐行执行 makdfile 中的命令。 如同 make 执行每一条命令,它将命令写入标准输出(除非另外指定的,例如使用 -s 标志)。 makefile 在每一行的命令之前必须有一个制表符。

当一条命令通过 make 命令执行时,它使用 make 的执行环境。 它包含从命令行到 make 命令的任何宏和在 MAKEFLAGS 变量中指定的任何环境变量。 make 命令的环境变量覆盖现有环境中的任何同名变量。
注:make 命令迂到以单词 include 开头的行,后跟另一个单词,即 makefile 的名称 (例如, include 依赖项) 时, make 命令尝试打开该文件并处理其内容,就像在出现包含行的位置显示内容一样。 这种行为只有在由 make 命令读取的第一个 makefile 的第一个非注释行不是 .POSIX 目标时发生;否则,将出现一个语法错误。

注释:注释以字符 # 开始,可以放在除了 shell 命令行中的任何位置,并且到行尾结束。

环境:如果 MAKEFLAGS 环境变量存在的话,make 命令将使用它。

目标规则

目标规则具有以下格式:

target[target...] : [prerequisite...] [;command]
<Tab>command
多个目标和先决条件用空格分隔。 任何后面跟着 ;(分号)的文本和所有以制表符开始的随后各行都被认为是用来更新目标的命令。 一个新行不以制表符或 # 字符开始时,开始一个新的目标。
注: 先决条件列表可以为空。

特殊目标

特殊目标不能包含到其他目标中;即它们是指定的唯一目标。 这些目标控制 make 命令的操作。 这些目标是:

描述
。缺省值 这用作一些目标(只用作先决条件)的规则,这些目标是无法由 make 命令用其他任何方法创建的。 仅使用 shell 脚本。 继承 . 缺省值命令的目标的 < (左括号) 变量设置为目标自己的名称。
。忽略 此目标的先决条件是目标本身;这会导致忽略与它们自身关联的命令所生成的错误。 如果没有指定先决条件,那么等同于指定 -i 标志。
.POSIX 导致 make 命令使用不同的缺省规则文件。 文件 /usr/ccs/lib/posix.mk 提供 POSIX 标准中指定的缺省规则。
此目标的先决条件是目标本身。.PRECIOUS 将防止移除目标。 如果没有指定先决条件,那么 .PRECIOUS 属性将应用于文件中的每一个目标。 通常,当 make 被中断时(例如,使用 SIGHUPSIGTERMSIGINTSIGQUIT),它将删除所有未完全形成的目标。 如果 make 以带有 -n-p-q 标志来调用,那么认为目标具有 .PRECIOUS 属性。
.SCCS_GET 必须在没有先决条件的情况下指定这个特殊目标。 如果这个特殊目标包括在 makefile 中,那么与这个特殊目标关联的命令可以用来获取在当前目录中没有找到的所有 SCCS 文件。 将用来从 SCCS 获取源文件的缺省命令替换成与这个特殊目标关联的命令。 在依赖关系列表中指定源文件时, make 会像对待任何其他目标一样对待这些文件。 当目标没有依赖关系,但在目录中存在时, make 假定该文件是最新的。 但是,如果针对目标 source_file找到名为 SCCS/s.source_file 的 SCCS 文件,那么 make 还会进行检查以确保目标是最新的。 如果缺少目标,或者 SCCS 文件较新,那么 make 会自动发出为 .SCCS_GET 特殊目标指定的命令以检索最新版本。 但是,如果目标可由任何人写,那么 make 不会检索新版本。
.SILENT 目标的先决条件是目标本身。 这会导致执行与目标关联的命令之前不会将其写入标准输出。 如果没有指定先决条件,那么 .PRECIOUS 属性将应用于文件中的每一条命令。
.附件 使用此名称将更多的后缀添加到 make 识别的文件后缀列表中。 目标的先决条件被附加到已知后缀列表。 如果没有指定后缀,那么任何以前指定的后缀会被删除。 这些后缀由推论规则使用。 要更改后缀的顺序,需要指定一个空的 .SUFFIXES 条目,然后指定一个新的 .SUFFIXES 条目列表。 makefile 一定不能将命令与 .SUFFIXES 关联。

推理规则

make 命令有一个缺省的推论规则集,能够用 makefile 中的附加推论规则定义来补充或改写它。 缺省规则存储在外部文件 /usr/ccs/lib/aix.mk 中。 可以通过在命令行中将 MAKERULES 变量设置为自己的文件名来替换自己的规则文件。 下一行显示如何从命令行中更改规则文件:

make MAKERULES=/pathname/filename

推论规则由目标后缀和命令构成。 通过后缀,make 命令确定先决条件,通过后缀和它们的先决条件,make 命令确定如何使目标最新。 推论规则具有以下格式:

rule:
<Tab>command
...

其中rule具有下列其中一种格式:

描述
.s1 单后缀推论规则描述如何构建附加单后缀的目标。
.s1.s2 双后缀推论规则描述如何构建附加带有先决条件的 .s2 的目标,这个先决条件附加带有 .s1

.s1.s2 后缀定义为特殊目标 .SUFFIXES 的先决条件。 推论规则显示在 makefile 中时,后缀 .s1.s2 必须是已知的后缀。 推论规则按其在 .SUFFIXES 中指定的顺序使用后缀。 当新行未以<Tab>或 # 字符。

如果rule为空,例如:

rule: ;

执行不起作用且 make 命令识别出后缀已存在,但当目标过期时无任何操作。

在前面规则中的 ~(波浪号) 指的是 SCCS 文件。 因此,规则 .c~.o 将 SCCS C 语言先决条件文件转换成对象文件(.o)。 因为 SCCS 文件的前缀,它与 make 命令的后缀视图不兼容。 ~(波浪号) 是一个将任何文件引用都更改成 SCCS 文件引用的方法。

目标或先决条件也能够成为归档库的成员,即使名称中有圆括号也可以这样处理。 例如,library(name) 表示 name 是归档库 library 的一位成员。 要通过特殊的文件更新库的成员,可以使用格式 .s1.a,其中带有 .s1 后缀的文件用来更新归档库的成员。 .a 指的是归档库。

使用宏

在 makefile 中,宏定义按以下格式定义:

variable=value

宏能够通过 makefile 显示,如下:

  • 如果宏显示在目标行中,那么在读取目标行时给宏赋值。
  • 如果宏显示在命令行中,那么在执行命令行时给宏赋值。
  • 如果宏显示在宏定义行中,那么在新的宏显示于规则或命令中时给宏赋值。

如果宏没有定义,那么它缺省为 NULL。 新的宏定义会覆盖现有的同名宏定义。 宏可以按下面列示的顺序来赋值:

  1. 缺省的推论规则
  2. 环境的内容
  3. Makefile
  4. 命令行。
    注: -e 标志使环境变量覆盖 makefile 中定义的那些变量。
SHELL 宏比较特殊。 它是由 make 命令设置到 shell 命令解释器(/usr/bin/sh)的路径名上。 然而,如果在 makefile 中或命令行上重新定义 SHELL 宏,那么将覆盖它的缺省设置。
注: SHELL 宏不影响 SHELL 环境变量,也不受其影响。

Shell 命令

每个目标都可以具有与其关联的一系列 shell 命令,这些命令通常用来创建目标。 此脚本中的每一条命令都必须以制表符开始。 虽然任何目标都能够显示在相关性行上,但除非使用 :: 操作符,否则这些相关性中只有一个能够通过创建脚本来跟随。

如果命令行的第一个或前两个字符是 @ (at 符号)、-(连字符)和 +(加号)这几个符号之一或全部,那么将特别处理该命令,如下:

描述
@ 使命令在被执行前不被回显。
- 使任何命令行的任何非零退出状态都被忽略。
+ 使命令行可以通过指定 -n-q-t 选项来执行。

没有元字符的命令通过 make 命令直接执行。 例如, make 命令将以下示例中的第一个命令与 shell 连接,因为它包含> (大于符号) shell 元字符。 因为下例中的第二条命令不包含任何 shell 元字符,所以 make 命令直接执行它:

target: dependency
        cat dependency > target
        chmod a+x target

忽略 shell 程序可以节约时间,但是会导致某些问题。 例如,尝试通过将 SHELL 宏设置为/bin/csh除非命令行还包含至少一个 shell 元字符,否则将无法工作。

SHELL=/bin/csh
   
target: dependency
        my_csh_script

此 makefile 失败,因为 make 命令尝试运行my_csh_script而不是将其委托给 C shell。

变量分配

make 命令中的变量和 shell 中的变量非常相似,全部由大写字母组成。 = 运算符将值分配给变量。 任何以前的变量都会被覆盖。 删除已赋值前的所有空格。

值可以按照如下所示附加到宏值:
macro += word ... 
macro += macro1 

使用 += 运算符代替 = 时,+= 运算符附加新值,并在以前的变量内容和附加的值之间插入一个空格。

变量通过用 { } (花括号) 或 ( )(圆括号)括起变量名并在前面加一个 $(美元符号)来进行扩展。 如果变量名只包含一个字母,那么不需要用花括号或圆括号将它括起来。 不建议使用这种简短格式。

变量替换出现在两种不同的时刻,取决于它被使用的场合。 相关性行中的变量在此行被读取时被扩展。 shell 命令中的变量在 shell 被执行时被扩展。

变量的四种类型(按优先顺序从小到大排列):

描述
环境 变量被定义为 make 命令的环境的一部分。
全局 变量在 makefile 中或在被包含的 makefile 中定义。
命令行 变量被定义为命令行的一部分。
本地 特定为某种目标定义的变量。 局部变量如下:
$<
代表使目标过期(推论规则)的先决条件的全名或者目标(.DEFAULT 规则)的全名。
$*
代表使没有后缀的目标过期(在推论规则下)的先决条件的文件名段。
$@
代表当前目标的目标全名或库归档目标的归档文件名。
$%
如果目标是归档库的成员,代表目标规则中的库成员。

还可以通过附加 DF 来使用局部变量:

表明局部变量应用于名称的目录部分。 这是后面不带有 /(斜杠)的路径名。 对于当前目录,D 是一个 . :NONE.
F
表明局部变量应用于名称的文件名部分。

另外,make 命令设置或了解以下变量:

$ 单个 $(美元符号);即 $$ 扩展到单个美元符号。
LANG LC_ALL 和相应的环境变量(以 LC_ 开头)没有指定语言环境时,确定语言环境编目使用的语言环境。
LC_ALL 确定用于覆盖由 LANG 或其他任何 LC_ 环境变量设置的任何语言环境编目值的语言环境。
LC_CTYPE 确定对于字符形式的文本数据的按字节顺序解释的语言环境。例如,参数中的单字节对多字节字符串。
LC_MESSAGES 确定写消息使用的语言。
MAKEFLAGS 环境变量 MAKEFLAGS 包含在 make 命令行中指定的任何内容。 任何在 make 命令行中指定的内容都被附加到 MAKEFLAGS 变量中,然后将变量输入到 make 执行的所有程序的环境中。 注意 MAKEFLAGS 变量中的 -f-p 标志的操作未定义。 在这个变量中,命令行标志优先于 -f-p 标志。
vpath 允许指定搜索先决条件的目录列表。 这个目录列表就像 SHELL 中的 PATH 变量那样工作。 VPATH 变量可以用冒号隔开指定多个目录。 例如:
VPATH=src:/usr/local/src

这表明 make 命令按以下顺序搜索给出的目录:

  • 当前目录(甚至在没有 VPATH 时也会出现)
  • src(当前目录中的子目录)
  • /usr/local/src.

标志

描述
-D变量 设置变量值为 1。
-d选项 显示关于 make 检查(调试方式)的文件和次数的详细信息。 不带任何选项或带有 A 选项的 -d 标志显示所有可用的调试信息。 以下为个别可选的调试选项:
a
显示所有可能的调试信息。
a
显示关于归档搜索和高速缓存的调试信息。
显示关于目录搜索的调试信息。
g1
显示在构造任何对象前的关于输入图的调试信息。
g2
显示构造每个对象之后或出错退出之前关于输入图的调试信息。
m
显示关于构造目标的调试信息,包括修改日期。
显示关于后缀搜索的调试信息。
v
显示关于变量赋值的调试信息。
-e 指定环境变量覆盖 makefile 中的宏赋值。
-f MakeFile 指定读取一个 makefile 来代替缺省的 makefile。 如果 Makefile 是 -(连字符),那么读取标准输入。 可以指定多个 makefile 并按指定的顺序读取。
-i 忽略 makefile 中的 shell 命令的非零退出。 等同于在 makefile 中的每一个命令行前指定 -(连字符)。
-j[作业] 指定 make 应该用于构建独立目标的并行作业数。 Jobs 参数可以取任何正整数值。 如果未指定 作业 ,那么 make 命令不会限制用于构建主目标的并行作业数。
-k 遇到错误后继续处理,但仅限于对不依赖于在创建时生成了错误的目标的那些目标进行该操作。
-n 显示命令,但是并不运行它们。 然而,会执行以 +(加号)开始的行。
-p 在执行任何命令前显示所有宏定义集合和目标描述。
-q 如果对象文件没有过期,那么返回一个零状态码;如果目标过期,那么返回一个状态码。 如果指定了该选项,将不更新目标。 然而,会执行以 +(加号)为前缀的命令行。
-r 不使用缺省规则。
-S 如果发生错误,那么终止 make 命令。 这是缺省值,与 -k 标志相反。
-s 执行命令时不在屏幕上显示它们。
-t 创建一个目标或更新它的修改时间,使它看起来没有过期。 执行以 +(加号)开始的命令行。
TARGET 指定 Target 形式的目标名或设置变量值。

退出状态

当指定 -q 标志时,此命令返回以下退出值:

描述
重大安全事件数量 成功完成。
第 1 年 目标过期。
> 1 发生错误。

否则,此命令返回以下退出值:

描述
重大安全事件数量 成功完成。
> 1 发生错误。

示例

  1. 要制作在 makefile 中找到的首个目标,请输入:
    make
  2. 要显示但不运行 make 命令要用来制作文件的命令:
    make  -n search.o
    该执行将在使用一个新的描述文件时验证其是否正确。
  3. 要建立一个 makefile,例如 pgm,取决于两个文件(a.o b.o),这两个文件取决于它们相应的先决条件文件(a.cb.c)以及一个公共文件 incl.h,请输入:
    pgm: a.o b.o
              c89 a.o b.o -o pgm
    a.o: incl.h a.c
              c89 -c a.c
    b.o: incl.h b.c
              c89 -c b.c
  4. 要从 .c 文件优化 .o 文件,请输入:
    .c.o:
              c89 -c -o $*.c
    or:
    .c.o:
              c89 -c -o $<
  5. 要查看内置规则的内容,请输入:
    make  -p  -f /dev/null 2>/dev/null
  6. 要以并行方式使用 make 命令,最多可使用 10 个并行作业来构建 makefile 中指定的目标,请输入:
    make -j10

文件

描述
Makefile 包含相关性列表。
Makefile 包含相关性列表。
s.makefile 包含相关性列表。 这是一个 SCCS 文件。
s.Makefile 包含相关性列表。 这是一个 SCCS 文件。
/usr/ccs/lib/posix.mk 包含用于 make 命令的缺省的 POSIX 规则。
/usr/ccs/lib/aix.mk 包含用于 make 命令的缺省的规则。