推理规则
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 将使用优先级最高的定义。 以下列表显示了从高到低的优先级顺序:
在生成文件中定义的推理规则;更新的定义优先。
在
Tools.ini
中定义的推理规则;更新的定义优先。预定义推理规则。