Compartilhar via


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:

  1. Uma regra de inferência definida em um makefile; definições posteriores têm precedência.

  2. Uma regra de inferência definida em Tools.ini; definições posteriores têm precedência.

  3. Uma regra de inferência predefinida.

Confira também

Referência de NMAKE