Regras de inferência
As regras de inferência no NMAKE fornecem comandos para atualizar destinos e inferir dependentes para destinos. As extensões em uma regra de inferência correspondem a um único destino e o dependente que têm o mesmo nome base. As regras de inferência são definidas pelo usuário ou predefinidas; as regras predefinidas podem ser redefinidas.
Se uma dependência desatualizada não tiver comandos e se .SUFFIXES
contiver a extensão do dependente, o NMAKE usará uma regra cujas extensões correspondem ao destino e a um arquivo existente no diretório atual ou especificado. Se mais de uma regra corresponder aos arquivos existentes, a lista .SUFFIXES
determinará qual usar; a prioridade da lista decresce da esquerda para a direita. Se um arquivo dependente não existir e não estiver listado como um destino em outro bloco de descrição, uma regra de inferência poderá criar o dependente ausente de outro arquivo que tenha o mesmo nome base. Se o destino de um bloco de descrição não tiver dependentes nem comandos, uma regra de inferência poderá atualizar o destino. As regras de inferência podem criar um destino de linha de comando mesmo que não exista nenhum bloco de descrição. O NMAKE poderá invocar uma regra para um dependente inferido mesmo que um dependente explícito seja especificado.
Definindo uma regra
O from_ext representa a extensão de um arquivo dependente e to_ext representa a extensão de um arquivo de destino.
.from_ext.to_ext:
commands
As extensões não diferenciam maiúsculas de minúsculas. As macros podem ser invocadas para representar from_ext e to_ext; as macros são expandidas durante o pré-processamento. O ponto (.
) que precede from_ext deve aparecer no início da linha. Os dois-pontos (:
) são precedidos por zero ou mais espaços ou tabulações. Eles podem ser seguidos apenas por espaços ou tabulações, um ponto e vírgula (;
) para especificar um comando, um sinal de número (#
) para especificar um comentário ou um caractere de nova linha. Nenhum outro espaço é permitido. Os comandos são especificados como em blocos de descrição.
Caminho de pesquisa em regras
{from_path}.from_ext{to_path}.to_ext:
commands
Uma regra de inferência se aplica a uma dependência somente se os caminhos especificados na dependência corresponderem exatamente aos caminhos da regra de inferência. Especifique o diretório do dependente no from_path e no diretório de destino no to_path; não são permitidos espaços. Especifique apenas um caminho para cada extensão. Um caminho em uma extensão requer um caminho na outra. Para especificar o diretório atual, use um ponto (.
) ou chaves vazias ({ }
). As macros podem representar from_path e to_path; eles são invocados durante o pré-processamento.
Exemplo de caminhos de pesquisa
{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) $<
Regras de modo do lote
{from_path}.from_ext{to_path}.to_ext::
commands
As regras de inferência do modo de lote fornecem apenas uma invocação da regra de inferência quando N comandos passam por essa regra de inferência. Sem regras de inferência do modo de lote, isso exigiria que N comandos fossem invocados. N é o número de dependentes que disparam a regra de inferência.
A única diferença sintática da regra de inferência padrão é que uma regra de inferência do modo de lote termina com dois-pontos (::
).
Observação
A ferramenta que está sendo invocada deve ser capaz de lidar com vários arquivos. A regra de inferência do modo de lote deve usar $<
como a macro para acessar arquivos dependentes.
As regras de inferência do modo de lote podem acelerar o processo de build. É mais rápido fornecer arquivos para o compilador no modo de lote, porque o driver do compilador é invocado apenas uma vez. Por exemplo, o compilador do C e C++ é executado mais rapidamente ao manipular um conjunto de arquivos, pois ele pode permanecer residente na memória durante todo o processo.
O exemplo a seguir mostra como usar regras de inferência no modo de lote:
#
# 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
O NMAKE produz a seguinte saída sem regras de inferência no modo de lote:
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
O NMAKE produz o seguinte resultado com as regras de inferência no modo de lote:
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...
Regras predefinidas
As regras de inferência predefinidas usam macros de comando e opções fornecidas pelo NMAKE.
Regra | Comando | Ação padrão | Regra do lote | Plataforma |
---|---|---|---|---|
.asm.exe |
$(AS) $(AFLAGS) $< |
ml $< |
não | x86 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml /c $< |
sim | x86 |
.asm.exe |
$(AS) $(AFLAGS) $< |
ml64 $< |
não | x64 |
.asm.obj |
$(AS) $(AFLAGS) /c $< |
ml64 /c $< |
sim | x64 |
.c.exe |
$(CC) $(CFLAGS) $< |
cl $< |
não | all |
.c.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
sim | all |
.cc.exe |
$(CC) $(CFLAGS) $< |
cl $< |
não | all |
.cc.obj |
$(CC) $(CFLAGS) /c $< |
cl /c $< |
sim | all |
.cpp.exe |
$(CPP) $(CPPFLAGS) $< |
cl $< |
não | all |
.cpp.obj |
$(CPP) $(CPPFLAGS) /c $< |
cl /c $< |
sim | all |
.cxx.exe |
$(CXX) $(CXXFLAGS) $< |
cl $< |
não | all |
.cxx.obj |
$(CXX) $(CXXFLAGS) /c $< |
cl /c $< |
sim | all |
.rc.res |
$(RC) $(RFLAGS) /r $< |
rc /r $< |
não | all |
Dependentes inferidos e regras
O NMAKE pressupõe um dependente inferido para um destino se houver uma regra de inferência aplicável. Uma regra se aplica se:
to_ext corresponde à extensão do destino.
from_ext corresponde à extensão de um arquivo que tem o nome base do destino e que existe no diretório atual ou especificado.
from_ext está em
.SUFFIXES
; nenhum outro from_ext em uma regra de correspondência tem uma prioridade mais alta.SUFFIXES
.Nenhum dependente explícito tem uma prioridade mais alta
.SUFFIXES
.
Os dependentes inferidos podem causar efeitos colaterais inesperados. Se o bloco de descrição do destino contiver comandos, o NMAKE executará esses comandos em vez dos comandos da regra.
Precedência em regras de inferência
Se uma regra de inferência for definida mais de uma vez, o NMAKE usará a definição de precedência mais alta. A lista a seguir mostra a ordem de precedência da mais alta para a mais baixa:
Uma regra de inferência definida em um makefile; definições posteriores têm precedência.
Uma regra de inferência definida em
Tools.ini
; definições posteriores têm precedência.Uma regra de inferência predefinida.