Blocos de descrição
Os blocos de descrição formam o núcleo de um makefile. Eles descrevem os destinos, ou os arquivos a serem criados, e suas dependências, os arquivos necessários para criar os destinos. Um bloco de descrição pode incluir comandos que descrevem como criar os destinos com base nas dependências. Um bloco de descrição é uma linha de dependência, opcionalmente seguida por um bloco de comandos:
targets... : dependents...
commands...
Linhas de dependência
Uma linha de dependência especifica um ou mais destinos e zero ou mais dependentes. Se um destino não existir ou tiver um carimbo de data/hora anterior a um dependente, o NMAKE executará os comandos no bloco de comandos. O NMAKE também executará o bloco de comandos se o destino for um pseudotarget. Veja uma linha de dependência de exemplo:
hi_bye.exe : hello.obj goodbye.obj helper.lib
Nessa linha de dependência, hi_bye.exe
é o destino. Suas dependências são hello.obj
, goodbye.obj
e helper.lib
. A linha de dependência informa ao NMAKE para criar o destino sempre que hello.obj
, goodbye.obj
ou helper.lib
tiver sido alterado mais recentemente do que hi_bye.exe
.
O destino deve estar no início da linha. Ele não pode ser recuado com espaços nem tabulações. Use dois-pontos (:
) para separar os destinos dos dependentes. Espaços ou tabulações são permitidos entre os destinos, o separador de dois-pontos (:
) e os dependentes. Para dividir a linha de dependência, use uma barra invertida (\
) após um destino ou dependente.
Antes de executar blocos de comando, o NMAKE examina todas as dependências e todas as regras de inferência aplicáveis para criar uma árvore de dependência. Uma árvore de dependência especifica as etapas necessárias para atualizar totalmente o destino. O NMAKE verifica recursivamente se um dependente é um destino em outra lista de dependências. Depois de criar a árvore de dependência, o NMAKE verifica os carimbos de data/hora. Se algum dependente na árvore for mais recente que o destino, o NMAKE criará o destino.
Destinos
A seção de destinos de uma linha de dependência especifica um ou mais destinos. Um destino pode ser qualquer nome de arquivo, nome do diretório ou pseudotarget válido. Separe vários destinos usando um ou mais espaços ou tabulações. Os destinos não diferenciam maiúsculas de minúsculas. Os caminhos são permitidos com nomes de arquivo. Um destino e seu caminho não pode exceder 256 caracteres. Se o destino anterior aos dois-pontos for um único caractere, use um espaço de separação. Caso contrário, o NMAKE interpretará a combinação de dois-pontos e letra como um especificador de unidade.
Vários destinos
O NMAKE avalia vários destinos em uma única dependência como se cada um fosse especificado em um bloco de descrição separado.
Por exemplo, esta regra:
bounce.exe leap.exe : jump.obj
echo Building...
é avaliada como:
bounce.exe : jump.obj
echo Building...
leap.exe : jump.obj
echo Building...
Dependências cumulativas
As dependências são cumulativas em um bloco de descrição, se um destino for repetido.
Por exemplo, esse conjunto de regras,
bounce.exe : jump.obj
bounce.exe : up.obj
echo Building bounce.exe...
é avaliada como:
bounce.exe : jump.obj up.obj
echo Building bounce.exe...
Quando você tem vários destinos em várias linhas de dependência em um único bloco de descrição, o NMAKE os avalia como se cada um fosse especificado em um bloco de descrição separado. No entanto, somente os destinos da última linha de dependência usam o bloco de comandos. O NMAKE tenta usar uma regra de inferência para os outros destinos.
Por exemplo, esse conjunto de regras,
leap.exe bounce.exe : jump.obj
bounce.exe climb.exe : up.obj
echo Building bounce.exe...
é avaliada como:
leap.exe : jump.obj
# invokes an inference rule
bounce.exe : jump.obj up.obj
echo Building bounce.exe...
climb.exe : up.obj
echo Building bounce.exe...
Destinos em vários blocos de descrição
Para atualizar um destino em mais de um bloco de descrição usando comandos diferentes, especifique dois pontos duas vezes (::) entre destinos e dependentes.
target.lib :: one.asm two.asm three.asm
ml one.asm two.asm three.asm
lib target one.obj two.obj three.obj
target.lib :: four.c five.c
cl /c four.c five.c
lib target four.obj five.obj
Efeitos colaterais da dependência
Você pode especificar um destino com dois-pontos (:) em duas linhas de dependência em locais diferentes. Se os comandos aparecerem apenas após uma das linhas, o NMAKE interpretará as dependências como se as linhas fossem adjacentes ou combinadas. Ele não invoca uma regra de inferência para a dependência que não tem comandos. Em vez disso, o NMAKE pressupõe que as dependências pertençam a um bloco de descrição e executa os comandos especificados com a outra dependência. Considere este conjunto de regras:
bounce.exe : jump.obj
echo Building bounce.exe...
bounce.exe : up.obj
é avaliada como:
bounce.exe : jump.obj up.obj
echo Building bounce.exe...
Esse efeito não ocorrerá se o dois-pontos (::
) for usado. Por exemplo, este conjunto de regras:
bounce.exe :: jump.obj
echo Building bounce.exe...
bounce.exe :: up.obj
é avaliada como:
bounce.exe : jump.obj
echo Building bounce.exe...
bounce.exe : up.obj
# invokes an inference rule
Pseudodestinos
Um pseudotarget é um rótulo usado no lugar de um nome de arquivo em uma linha de dependência. Ele é interpretado como um arquivo que não existe e que, portanto, está desatualizado. O NMAKE pressupõe que o carimbo de data/hora de um pseudotarget seja o mesmo que o mais recente de todos os seus dependentes. Se não tiver dependentes, a hora atual será assumida. Se um pseudotarget for usado como um destino, seus comandos serão sempre executados. Um pseudotarget usado como dependente também deve aparecer como um destino em outra dependência. No entanto, essa dependência não precisa ter um bloco de comandos.
Os nomes de pseudotarget seguem as regras de sintaxe de nome de arquivo para destinos. No entanto, se o nome não tiver uma extensão, ele poderá exceder o limite de 8 caracteres para nomes de arquivo e poderá ter até 256 caracteres de comprimento.
Pseudotargets são úteis quando você deseja que o NMAKE crie mais de um destino automaticamente. O NMAKE cria apenas os destinos especificados na linha de comando. Ou, se nenhum destino de linha de comando for especificado, ele criará apenas o primeiro destino da primeira dependência no makefile. Você pode informar ao NMAKE para criar vários destinos sem listá-los individualmente na linha de comando. Escreva um bloco de descrição com uma dependência que contenha um pseudotarget e liste os destinos que você deseja criar como seus dependentes. Em seguida, coloque esse bloco de descrição em primeiro no makefile ou especifique o pseudotarget na linha de comando do NMAKE.
Neste exemplo, UPDATE é um pseudotarget.
UPDATE : *.*
COPY $** c:\product\release
Quando UPDATE é avaliado, o NMAKE copia todos os arquivos do diretório atual para a unidade e o diretório especificados.
No makefile a seguir, o pseudotarget all
cria project1.exe
e project2.exe
se um all
ou nenhum destino for especificado na linha de comando. O pseudotarget setenv
altera a variável de ambiente LIB antes que os arquivos .exe
sejam atualizados:
all : setenv project1.exe project2.exe
project1.exe : project1.obj
LINK project1;
project2.exe : project2.obj
LINK project2;
setenv :
set LIB=\project\lib
Dependentes
Em uma linha de dependência, especifique zero ou mais dependentes após os dois-pontos (:
) ou dois-pontos duplos (::
), usando qualquer nome de arquivo ou pseudotarget válido. Separe vários dependentes usando um ou mais espaços ou tabulações. Os dependentes não diferenciam maiúsculas de minúsculas. Os caminhos são permitidos com nomes de arquivo.
Dependentes inferidos
Junto com os dependentes listados explicitamente na linha de dependência, o NMAKE pode assumir um dependente inferido. Um dependente inferido é derivado de uma regra de inferência e é avaliado antes de dependentes explícitos. Quando um dependente inferido está desatualizado em comparação com seu destino, o NMAKE invoca o bloco de comando para a dependência. Se um dependente inferido não existir ou estiver desatualizado em comparação com seus próprios dependentes, o NMAKE primeiro atualizará o dependente inferido. Para obter mais informações sobre dependentes inferidos, confira Regras de inferência.
Procurar dependentes em caminhos
Você pode especificar um caminho de pesquisa opcional para cada dependente. Aqui está a sintaxe para especificar um conjunto de diretórios a serem pesquisados:
{diretório[;diretório...]}dependente
Coloque nomes de diretório entre chaves ({ }
). Separe vários diretórios com ponto e vírgula (;
). Não são permitidos espaços nem tabulações. O NMAKE procura o dependente primeiro no diretório atual e, em seguida, na lista de diretórios na ordem especificada. Você pode usar uma macro para especificar parte ou todo um caminho de pesquisa. Somente o dependente especificado usa esse caminho de pesquisa.
Exemplo de caminho de pesquisa de diretório
Essa linha de dependência mostra como criar uma especificação de diretório para uma pesquisa:
reverse.exe : {\src\omega;e:\repo\backwards}retro.obj
O destino reverse.exe
tem um dependente, retro.obj
. A lista delimitada por chaves especifica dois diretórios. O NMAKE pesquisa primeiro retro.obj
no diretório atual. Se ele não estiver lá, o NMAKE pesquisará o diretório \src\omega
e, em seguida, o diretório e:\repo\backwards
.