描述块

描述块构成生成文件的核心。 它们描述目标(或要创建的文件)及其依赖项(创建目标所需的文件)。 描述块可能包括命令,这些命令描述如何从依赖项创建目标。 描述块是一个依赖项行,可选择后跟命令块:

targets... : dependents...
    commands...

依赖项行

依赖项行指定一个或多个目标,以及零个或以上依赖项。 如果目标不存在或时间戳早于依赖项时间戳,NMAKE 会在命令块中执行命令。 如果目标为伪目标,NMAKE 也会执行命令块。 依赖项行示例如下:

hi_bye.exe : hello.obj goodbye.obj helper.lib

在此依赖项行中,hi_bye.exe 是目标。 它的依赖项是 hello.objgoodbye.objhelper.lib。 依赖项行告知 NMAKE 只要 hello.objgoodbye.objhelper.lib 最近的更改多于 hi_bye.exe 就会生成目标。

目标必须位于行的开头。 不得用任何空格或制表符来缩进。 使用冒号 (:) 将目标与依赖项分开。 目标、冒号分隔符 (:) 和依赖项之间允许使用空格或制表符。 若要拆分依赖项行,请在目标或依赖项之后使用反斜杠 (\)。

在执行命令块之前,NMAKE 会扫描所有依赖项和任何适用的推理规则以生成依赖项树。 依赖项树指定完全更新目标所需的步骤。 NMAKE 以递归方式检查依赖项本身是否是另一个依赖项列表中的目标。 生成依赖项树后,NMAKE 会检查时间戳。 如果树中任意依赖项晚于目标,NMAKE 都会生成目标。

目标

依赖项行的目标部分指定一个或多个目标。 目标可以是任何有效的文件名、目录名称或伪目标。 使用一个或多个空格或制表符分隔多个目标。 目标不区分大小写。 路径允许包含文件名。 目标及其路径长度不能超过 256 个字符。 如果冒号前面的目标为单个字符,请使用一个分隔空格。 否则,NMAKE 会将字母冒号组合解释为驱动器说明符。

多个目标

NMAKE 计算单个依赖项中的多个目标,就像在单独的描述块中指定每个目标一样。

例如,以下规则:

bounce.exe leap.exe : jump.obj
   echo Building...

计算结果为:

bounce.exe : jump.obj
   echo Building...

leap.exe : jump.obj
   echo Building...

累计依赖项

如果目标重复,将累计一个描述块中的依赖项。

例如,以下规则集,

bounce.exe : jump.obj
bounce.exe : up.obj
   echo Building bounce.exe...

计算结果为:

bounce.exe : jump.obj up.obj
   echo Building bounce.exe...

当单个描述块的多个依赖项行中有多个目标时,NMAKE 会计算这些目标,就像在单独的描述块中指定每个目标一样。 但是,仅最后一个依赖项行中的目标使用命令块。 NMAKE 会尝试对其他目标使用推理规则。

例如,以下规则集,

leap.exe bounce.exe : jump.obj
bounce.exe climb.exe : up.obj
   echo Building bounce.exe...

计算结果为:

leap.exe : jump.obj
# invokes an inference rule

bounce.exe : jump.obj up.obj
   echo Building bounce.exe...

climb.exe : up.obj
   echo Building bounce.exe...

多个描述块中的目标

若要使用不同命令在多个描述块中更新某个目标,请在目标与依赖项之间指定两个连续冒号 (::)。

target.lib :: one.asm two.asm three.asm
    ml one.asm two.asm three.asm
    lib target one.obj two.obj three.obj
target.lib :: four.c five.c
    cl /c four.c five.c
    lib target four.obj five.obj

依赖项副作用

你可能在不同位置的两个依赖项行中使用冒号 (:) 指定某个目标。 如果命令仅出现在其中一行之后,NMAKE 会将其视为两行相邻或合并来解释依赖项。 它不会为没有命令的依赖项调用推理规则。 相反,NMAKE 会假定依赖项属于一个描述块,并执行与其他依赖项一起指定的命令。 请考虑以下规则集:

bounce.exe : jump.obj
   echo Building bounce.exe...

bounce.exe : up.obj

计算结果为:

bounce.exe : jump.obj up.obj
   echo Building bounce.exe...

如果使用双冒号 (::),则不会出现此效果。 例如,以下规则集:

bounce.exe :: jump.obj
   echo Building bounce.exe...

bounce.exe :: up.obj

计算结果为:

bounce.exe : jump.obj
   echo Building bounce.exe...

bounce.exe : up.obj
# invokes an inference rule

伪目标

伪目标是用于替代依赖项行中文件名的标签。 它被解释为不存在的文件,因而已过期。 NMAKE 假定伪目标的时间戳与其所有依赖项的最新时间戳相同。 如果没有依赖项,则假定为当前时间。 如果将伪目标用作目标,则始终执行其命令。 用作依赖项的伪目标还必须显示为另一个依赖项中的目标。 但是,该依赖项不需要具有命令块。

伪目标名称遵循目标的文件名语法规则。 但是,如果名称没有扩展名,它可能超过文件名的 8 个字符限制,并且最长可达 256 个字符。

如果希望 NMAKE 自动生成多个目标,伪目标非常有用。 NMAKE 仅生成在命令行中指定的目标。 或者,如果未指定命令行目标,它将仅生成生成文件中第一个依赖项中的第一个目标。 你可以指示 NMAKE 生成多个目标,而无需在命令行上单独列出它们。 使用包含伪目标的依赖项编写描述块,并列出要生成为其依赖项的目标。 然后,在生成文件中首先放置此描述块,或在 NMAKE 命令行中指定该伪目标。

在此示例中,UPDATE 是伪目标。

UPDATE : *.*
COPY $** c:\product\release

计算 UPDATE 后,NMAKE 会将当前目录中的所有文件复制到指定的驱动器和目录。

在以下生成文件中,如果在命令行中指定 all 或未指定任何目标,则伪目标 all 将生成 project1.exeproject2.exe。 伪目标 setenv 将在 .exe 文件更新之前更改 LIB 环境变量:

all : setenv project1.exe project2.exe

project1.exe : project1.obj
    LINK project1;

project2.exe : project2.obj
    LINK project2;

setenv :
    set LIB=\project\lib

依赖项

在依赖项行中,使用任何有效的文件名或伪目标在冒号 (:) 或双冒号 (::) 后指定零个或以上依赖项。 使用一个或多个空格或制表符分隔多个依赖项。 依赖项不区分大小写。 路径允许包含文件名。

推导出的依赖项

除了依赖项行中显式列出的依赖项之外,NMAKE 还会假定推导出的依赖项。 推导出的依赖项派生自推理规则,并在显式依赖项之前进行计算。 如果推导出的依赖项与目标相比已过期,NMAKE 会为此依赖项调用命令块。 如果推导出的依赖项不存在,或与自己的依赖项相比已过期,NMAKE 会首先更新推导出的依赖项。 有关推导出的依赖项的详细信息,请参阅推理规则

依赖项的搜索路径

可以为每个依赖项指定可选的搜索路径。 以下是指定用于搜索的一组目录的语法:

{directory[;directory...]}dependent

将目录名称括在大括号 ({ }) 中。 使用分号 (;) 分隔多个目录。 不允许使用空格或制表符。 NMAKE 首先在当前目录中查找依赖项,然后在目录列表中按指定顺序查找。 可以使用宏指定部分或完整搜索路径。 仅指定的依赖项使用此搜索路径。

目录搜索路径示例

此依赖项行演示如何为搜索创建目录规范:

reverse.exe : {\src\omega;e:\repo\backwards}retro.obj

目标 reverse.exe 具有一个依赖项 retro.obj。 大括号括起来的列表指定两个目录。 NMAKE 首先在当前目录中搜索 retro.obj。 如果不存在,NMAKE 会搜索 \src\omega 目录,然后搜索 e:\repo\backwards 目录。

另请参阅

NMAKE 参考