Reglas de inferencia
Las reglas de inferencia de NMAKE proporcionan comandos para actualizar destinos e inferir dependientes para destinos. Las extensiones de una regla de inferencia hacen coincidir un único destino y un dependiente que tienen el mismo nombre base. Las reglas de inferencia las define el usuario o están predefinidas; las reglas predefinidas se pueden redefinir.
Si una dependencia obsoleta no tiene comandos y si .SUFFIXES
contiene la extensión del destino dependiente, NMAKE usa una regla cuyas extensiones coinciden con el destino y un archivo existente en el directorio actual o en el especificado. Si más de una regla coincide con los archivos existentes, la lista .SUFFIXES
determina qué usar; la prioridad de lista desciende de izquierda a derecha. Si un archivo dependiente no existe y no aparece en la lista como destino en otro bloque de descripción, una regla de inferencia puede crear el archivo dependiente que falta a partir de otro archivo que tenga el mismo nombre base. Si el destino de un bloque de descripción no tiene comandos ni archivos dependientes, una regla de inferencia puede actualizar el destino. Las reglas de inferencia pueden crear un destino de línea de comandos, aunque no exista ningún bloque de descripción. NMAKE puede invocar una regla para un archivo dependiente inferido, aunque se especifique un dependiente explícito.
Definir una regla
from_ext representa la extensión de un archivo dependiente, mientras que to_ext representa la extensión de un archivo de destino.
.from_ext.to_ext:
commands
Los valores no distinguen mayúsculas de minúsculas. Se pueden invocar macros que representen from_ext y to_ext; las macros se expanden durante el preprocesamiento. El punto (.
) que precede a from_ext debe aparecer al principio de la línea. El signo de dos puntos (:
) está precedido por cero o más espacios o pestañas. Solo puede ir seguido de espacios o pestañas, un signo de punto y coma (;
) para especificar un comando, un signo de número (#
) para especificar un comentario o un carácter de nueva línea. No se permiten otros espacios. Los comandos se especifican como en bloques de descripción.
Rutas de búsqueda en reglas
{from_path}.from_ext{to_path}.to_ext:
commands
Las reglas de inferencia solo se aplica a una dependencia si las rutas de acceso especificadas en la dependencia coinciden exactamente con las rutas de acceso de la regla de inferencia. Especifique el directorio del archivo dependiente en from_path y el directorio del destino en to_path; no se permiten espacios. Especifique solo una ruta de acceso para cada extensión. Una ruta de acceso en una extensión requiere una ruta de acceso en la otra. Para especificar el directorio actual, use un punto (.
) o llaves vacías ({ }
). Las macros pueden representar from_path y to_path; se invocan durante el preprocesamiento.
Ejemplo de rutas de acceso de búsqueda
{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) $<
Reglas de modo por lotes
{from_path}.from_ext{to_path}.to_ext::
commands
Las reglas de inferencia del modo por lotes proporcionan solo una invocación de la regla de inferencia cuando N comandos pasan por esta regla de inferencia. Sin reglas de inferencia en modo por lotes, habría que invocar a N comandos. N es el número de dependientes que desencadenan la regla de inferencia.
La única diferencia sintáctica de la regla de inferencia estándar es que las reglas de inferencia del modo por lotes terminan con dos puntos (::
).
Nota:
La herramienta que se invoca debe ser capaz de controlar varios archivos. La regla de inferencia del modo por lotes debe usar $<
como macro para acceder a los archivos dependientes.
Las reglas de inferencia en modo por lotes pueden acelerar el proceso de compilación. Es más rápido proporcionar archivos al compilador en modo por lotes, ya que el controlador del compilador se invoca solo una vez. Por ejemplo, el compilador de C y C++ se ejecuta más rápido al controlar un conjunto de archivos, ya que puede permanecer en memoria durante todo el proceso.
En el ejemplo siguiente se muestra cómo usar reglas de inferencia del modo por lotes:
#
# 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 genera la siguiente salida sin reglas de inferencia del modo por lotes:
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 genera el siguiente resultado con reglas de inferencia del modo por lotes:
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...
Reglas predefinidas
Las reglas de inferencia predefinidas utilizan macros de comando y de opciones proporcionadas por NMAKE.
Regla | Get-Help | Acción predeterminada | Regla por lotes | Plataforma |
---|---|---|---|---|
.asm.exe |
$(AS) $(AFLAGS) $< |
ml $< |
no | x86 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml /c $< |
sí | x86 |
.asm.exe |
$(AS) $(AFLAGS) $< |
ml64 $< |
no | x64 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml64 /c $< |
sí | x64 |
.c.exe |
$(CC) $(CFLAGS) $< |
cl $< |
no | todo |
.c.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
sí | all |
.cc.exe |
$(CC) $(CFLAGS) $< |
cl $< |
no | todo |
.cc.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
sí | all |
.cpp.exe |
$(CPP) $(CPPFLAGS) $< |
cl $< |
no | todo |
.cpp.obj |
$(CPP) $(CPPFLAGS) /c $< |
cl /c $< |
sí | all |
.cxx.exe |
$(CXX) $(CXXFLAGS) $< |
cl $< |
no | todo |
.cxx.obj |
$(CXX) $(CXXFLAGS) /c $< |
cl /c $< |
sí | all |
.rc.res |
$(RC) $(RFLAGS) /r $< |
rc /r $< |
no | todo |
Dependientes inferidos y reglas
NMAKE asume que existe una dependencia inferida para un destino si existe alguna regla de inferencia aplicable. Las reglas se aplican si:
to_ext coincide con la extensión del destino.
from_ext coincide con la extensión de un archivo que tiene el nombre base del destino y que existe en el directorio actual o especificado.
from_ext está en
.SUFFIXES
; ningún otro from_ext de una regla de coincidencia tiene una prioridad.SUFFIXES
de más alta.Ningún archivo dependiente explícito tiene una prioridad de
.SUFFIXES
más alta.
Los dependientes inferidos pueden causar efectos secundarios inesperados. Si el bloque de descripción del destino contiene comandos, NMAKE los ejecuta, en lugar de los comandos de la regla.
Prioridad en las reglas de inferencia
Si se define una regla de inferencia más de una vez, NMAKE usa la definición de mayor prioridad. En la siguiente lista se muestra el orden de prioridad, de mayor a menor:
Una regla de inferencia definida en un archivo Make; las definiciones posteriores tienen prioridad.
Una regla de inferencia definida en
Tools.ini
; las definiciones posteriores tienen prioridad.Una regla de inferencia predefinida.