推理规则

NMAKE 中的推理规则提供了用于更新目标以及推理目标依赖项的命令。 推理规则中的扩展与具有相同基名称的单个目标及依赖项相匹配。 推理规则是用户定义规则或预定义规则;预定义规则可以予以重新定义。

如果过期依赖项没有相应命令,且 .SUFFIXES 包含该依赖项的扩展,NMAKE 将使用其扩展与目标及当前或指定目录中的现有文件相匹配的规则。 如果多个规则与现有文件匹配,则 .SUFFIXES 列表将确定要使用的规则;列表优先级从左到右递减。 如果依赖项文件不存在且未在另一个描述块中列为目标,则推理规则可以从具有相同基名称的另一个文件创建缺少的依赖项。 如果描述块的目标没有相应依赖项或命令,推理规则可以更新该目标。 即使描述块不存在,推理规则也可以生成命令行目标。 即使指定了显式依赖项,NMAKE 也可以为推理的依赖项调用规则。

定义规则

from_ext 表示依赖项文件的扩展名,to_ext 表示目标文件的扩展名。

.from_ext.to_ext:
   commands

扩展名不区分大小写。 可以调用宏来表示 from_ext 和 to_ext;在预处理期间可展开宏。 位于 from_ext 之前的句点 (.) 必须显示在行的开头。 冒号 (:) 前有零个或多个空格或制表符。 冒号后只能跟空格或制表符、用于指定命令的分号 (;)、用于指定注释的数字符号 (#) 或换行符。 不允许有额外的空格。 命令在描述块中指定。

规则中的搜索路径

{from_path}.from_ext{to_path}.to_ext:
   commands

仅在依赖项中指定的路径与推理规则路径完全匹配时,推理规则才适用于依赖项。 在 from_path 中指定依赖项目录,并在 to_path 中指定目标目录;目录中不允许有空格。 为每个扩展名仅指定一个路径。 需要为这两个扩展名各指定一个路径。 若要指定当前目录,请使用句点 (.) 或空大括号 ({ })。 宏可以表示 from_path 和 to_path;在预处理期间可调用它们。

搜索路径示例

{dbi\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $(YUDBI) $<

{ilstore\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $<

{misc\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $(YUPDB) $<

{misc\}.c{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $<

{msf\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $<

{bsc\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $(YUPDB) $<

{mre\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $(YUPDB) $<

{namesrvr\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $(YUPDB) $<

{src\cvr\}.cpp{$(ODIR)}.obj::
        $(CC) $(CFLAGS) $<

批模式规则

{from_path}.from_ext{to_path}.to_ext::
   commands

当某个推理规则处理 N 次命令时,批处理模式推理规则仅调用一次此推理规则。 如果没有批处理模式推理规则,则需要调用 N 次命令。 N 是触发推理规则的依赖项的数目。

其与标准推理规则的唯一语法差异在于,批处理模式推理规则以双冒号 (::) 结尾。

注意

调用的工具必须能够处理多个文件。 批处理模式推理规则必须将 $< 用作宏来访问依赖项文件。

批处理模式推理规则可以加快生成过程。 在批处理模式下可以更快速地向编译器提供文件,因为编译器驱动程序只调用一次。 例如,C 和 C++ 编译器在处理一组文件时运行速度更快,因为它可以在整个过程中保持内存驻留状态。

以下示例演示如何使用批处理模式推理规则:

#
# sample makefile to illustrate batch-mode inference rules
#
O = .
S = .
Objs = $O/foo1.obj $O/foo2.obj $O/foo2.obj $O/foo3.obj $O/foo4.obj
CFLAGS = -nologo

all : $(Objs)

!ifdef NOBatch
{$S}.cpp{$O}.obj:
!else
{$S}.cpp{$O}.obj::
!endif
   $(CC) $(CFLAGS) -Fd$O\ -c $<

$(Objs) :

#end of makefile

不使用批处理模式推理规则时,NMAKE 生成以下输出:

E:\tmp> nmake -f test.mak -a NOBatch=1

Microsoft (R) Program Maintenance Utility   Version 7.00.0000
Copyright (C) Microsoft Corp 1988-2001. All rights reserved.
        cl -nologo -Fd.\ -c .\foo1.cpp
foo1.cpp
        cl -nologo -Fd.\ -c .\foo2.cpp
foo2.cpp
        cl -nologo -Fd.\ -c .\foo3.cpp
foo3.cpp
        cl -nologo -Fd.\ -c .\foo4.cpp
foo4.cpp

使用批处理模式推理规则时,NMAKE 生成以下结果:

E:\tmp> nmake -f test.mak -a

Microsoft (R) Program Maintenance Utility   Version 7.00.0000
Copyright (C) Microsoft Corp 1988-2001. All rights reserved.

        cl -nologo -Fd.\ -c .\foo1.cpp .\foo2.cpp .\foo3.cpp .\foo4.cpp
foo1.cpp
foo2.cpp
foo3.cpp
foo4.cpp
Generating Code...

预定义的规则

预定义推理规则使用 NMAKE 提供的命令和选项宏。

规则 命令 默认操作 批处理规则 平台
.asm.exe $(AS) $(AFLAGS) $< ml $< x86
.asm.obj $(AS) $(AFLAGS) /c $< ml /c $< x86
.asm.exe $(AS) $(AFLAGS) $< ml64 $< X64
.asm.obj $(AS) $(AFLAGS) /c $< ml64 /c $< X64
.c.exe $(CC) $(CFLAGS) $< cl $< all
.c.obj $(CC) $(CFLAGS) /c $< cl /c $< 全部
.cc.exe $(CC) $(CFLAGS) $< cl $< all
.cc.obj $(CC) $(CFLAGS) /c $< cl /c $< 全部
.cpp.exe $(CPP) $(CPPFLAGS) $< cl $< all
.cpp.obj $(CPP) $(CPPFLAGS) /c $< cl /c $< 全部
.cxx.exe $(CXX) $(CXXFLAGS) $< cl $< all
.cxx.obj $(CXX) $(CXXFLAGS) /c $< cl /c $< 全部
.rc.res $(RC) $(RFLAGS) /r $< rc /r $< all

推导出的依赖项和规则

如果存在适用的推理规则,NMAKE 会为目标假定一个推导出的依赖项。 规则适用条件:

  • to_ext 与目标扩展名匹配。

  • from_ext 与具有目标基名称且存在于当前或指定目录中的文件的扩展名匹配。

  • from_ext 位于 .SUFFIXES 中,且匹配规则中没有其他 from_ext 具有更高的 .SUFFIXES 优先级。

  • 没有显式依赖项具有更高的 .SUFFIXES 优先级。

推导出的依赖项可能会导致意外的不良影响。 如果目标的描述块包含命令,NMAKE 会执行这些命令,而不会执行规则中的命令。

推理规则中的优先级

如果多次定义了某个推理规则,NMAKE 将使用优先级最高的定义。 以下列表显示了从高到低的优先级顺序:

  1. 在生成文件中定义的推理规则;更新的定义优先。

  2. Tools.ini 中定义的推理规则;更新的定义优先。

  3. 预定义推理规则。

另请参阅

NMAKE 参考