Certas maneiras padronizadas de refazer arquivos-alvo são usadas com muita frequência. Por exemplo, uma forma habitual de produzir um arquivo objeto é a partir de um arquivo fonte C usando o compilador C, cc.
As regras implícitas (implicit rules) ensinam ao make como usar essas técnicas habituais, de modo que você não precise especificá-las em detalhe sempre que quiser usá-las. Por exemplo, existe uma regra implícita para a compilação de C. Os nomes dos arquivos determinam quais regras implícitas são executadas. Por exemplo, a compilação de C costuma tomar um arquivo .c e produzir um arquivo .o. Assim, o make aplica a regra implícita de compilação de C quando vê essa combinação de terminações de nomes de arquivos.
Uma cadeia de regras implícitas pode aplicar-se em sequência; por exemplo, o make refaz um arquivo .o a partir de um arquivo .y passando por um arquivo .c.
As regras implícitas embutidas usam várias variáveis em suas receitas (recipes), de modo que, mudando os valores das variáveis, você pode mudar a forma como a regra implícita funciona. Por exemplo, os sinalizadores que a regra implícita de compilação de C passa ao compilador C podem ser controlados pela variável CFLAGS.
Você pode definir suas próprias regras implícitas escrevendo regras de padrão (pattern rules).
As regras de sufixo (suffix rules) são uma forma mais limitada de definir regras implícitas. As regras de padrão são mais gerais e mais claras, mas as regras de sufixo são mantidas por compatibilidade.
Para permitir que o make encontre um método habitual de atualizar um arquivo-alvo, tudo o que você precisa fazer é abster-se de especificar receitas você mesmo. Escreva uma regra sem receita, ou não escreva nenhuma regra. Então o make descobrirá qual regra implícita usar com base em que tipo de arquivo fonte existe ou pode ser produzido.
Por exemplo, suponha que o makefile seja assim:
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Como você menciona foo.o, mas não fornece uma regra para ele, o make procurará automaticamente uma regra implícita que diga como atualizá-lo. Isso acontece quer o arquivo foo.o exista atualmente ou não.
Se uma regra implícita for encontrada, ela pode fornecer tanto uma receita quanto um ou mais pré-requisitos (prerequisites) (os arquivos fonte). Você quereria escrever uma regra para foo.o sem receita se precisasse especificar pré-requisitos adicionais — como arquivos de cabeçalho — que a regra implícita não pode fornecer.
Cada regra implícita tem um padrão de alvo e padrões de pré-requisito. Pode haver muitas regras implícitas com o mesmo padrão de alvo. Por exemplo, numerosas regras produzem arquivos «.o»: uma, a partir de um arquivo «.c» com o compilador C; outra, a partir de um arquivo «.p» com o compilador Pascal; e assim por diante. A regra que de fato se aplica é aquela cujos pré-requisitos existem ou podem ser produzidos. Portanto, se você tem um arquivo foo.c, o make executará o compilador C; caso contrário, se você tem um arquivo foo.p, o make executará o compilador Pascal; e assim por diante.
Naturalmente, quando você escreve o makefile, você sabe qual regra implícita quer que o make use, e sabe que ele escolherá aquela porque sabe quais arquivos de pré-requisito devem existir. Para um catálogo de todas as regras implícitas predefinidas, veja Catálogo de regras embutidas.
Acima, dissemos que uma regra implícita se aplica se os pré-requisitos necessários «existem ou podem ser produzidos». Um arquivo «pode ser produzido» se for mencionado explicitamente no makefile como um alvo ou um pré-requisito, ou se uma regra implícita puder ser encontrada recursivamente para mostrar como produzi-lo. Quando um pré-requisito implícito é o resultado de outra regra implícita, dizemos que está ocorrendo encadeamento (chaining). Veja Cadeias de regras implícitas.
Em geral, o make procura uma regra implícita para cada alvo, e para cada regra de dois-pontos duplo, que não tenha receita. Um arquivo que é mencionado apenas como pré-requisito é considerado um alvo cuja regra não especifica nada, de modo que a busca de regra implícita acontece para ele também. Para os detalhes de como a busca é feita, veja Algoritmo de busca de regras implícitas.
Note que os pré-requisitos explícitos não influenciam a busca de regra implícita. Por exemplo, considere esta regra explícita:
foo.o: foo.p
O pré-requisito sobre foo.p não significa necessariamente que o make refará foo.o de acordo com a regra implícita de produzir um arquivo objeto, um arquivo .o, a partir de um arquivo fonte Pascal, um arquivo .p. Por exemplo, se foo.c também existir, a regra implícita de produzir um arquivo objeto a partir de um arquivo fonte C é usada em seu lugar, porque ela aparece antes da regra de Pascal na lista de regras implícitas predefinidas (veja Catálogo de regras embutidas).
Se você não quer que uma regra implícita seja usada para um alvo que não tem receita, você pode dar a esse alvo uma receita vazia escrevendo um ponto e vírgula (veja Definir receitas vazias).
Aqui está um catálogo de regras implícitas predefinidas que estão sempre disponíveis, a menos que o makefile as sobreponha ou cancele explicitamente. Para informações sobre como cancelar ou sobrepor uma regra implícita, veja Cancelar regras implícitas. A opção «-r» ou «--no-builtin-rules» cancela todas as regras predefinidas.
Este manual documenta apenas as regras padrão disponíveis em sistemas operacionais baseados em POSIX. Outros sistemas operacionais, como VMS, Windows, OS/2, etc. podem ter conjuntos diferentes de regras padrão. Para ver a lista completa de regras padrão e variáveis disponíveis na sua versão do GNU make, execute «make -p» em um diretório sem makefile.
Nem todas essas regras estarão sempre definidas, mesmo quando a opção «-r» não for dada. Muitas das regras implícitas predefinidas são implementadas no make como regras de sufixo, de modo que quais delas estarão definidas depende da lista de sufixos (a lista de pré-requisitos do alvo especial .SUFFIXES). A lista de sufixos padrão é:
.out, .a, .ln, .o, .c, .cc, .C, .cpp, .p, .f, .F, .m, .r, .y, .l, .ym, .lm, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el.
Todas as regras implícitas descritas a seguir cujos pré-requisitos têm um desses sufixos são, na verdade, regras de sufixo. Se você modificar a lista de sufixos, as únicas regras de sufixo predefinidas em vigor serão aquelas nomeadas por um ou dois dos sufixos que estão na lista que você especificar; regras cujos sufixos não estejam na lista ficam desabilitadas. Para detalhes completos sobre regras de sufixo, veja Regras de sufixo à moda antiga.
n.o é produzido automaticamente a partir de n.c com uma receita da forma «$(CC) $(CPPFLAGS) $(CFLAGS) -c».
n.o é produzido automaticamente a partir de n.cc, n.cpp ou n.C com uma receita da forma «$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c». Recomendamos que você use o sufixo «.cc» ou «.cpp» para arquivos fonte C++ em vez de «.C», para dar melhor suporte a sistemas de arquivos que não distinguem maiúsculas de minúsculas.
n.o é produzido automaticamente a partir de n.p com a receita «$(PC) $(PFLAGS) -c».
n.o é produzido automaticamente a partir de n.r, n.F ou n.f executando o compilador Fortran. A receita exata usada é a seguinte:
«$(FC) $(FFLAGS) -c».
«$(FC) $(FFLAGS) $(CPPFLAGS) -c».
«$(FC) $(FFLAGS) $(RFLAGS) -c».
n.f é produzido automaticamente a partir de n.r ou n.F. Esta regra executa apenas o pré-processador para converter um programa Ratfor ou um programa Fortran que precise de pré-processamento em um programa Fortran estrito. A receita exata usada é a seguinte:
«$(FC) $(CPPFLAGS) $(FFLAGS) -F».
«$(FC) $(FFLAGS) $(RFLAGS) -F».
n.sym é produzido a partir de n.def com uma receita da forma «$(M2C) $(M2FLAGS) $(DEFFLAGS)». n.o é produzido a partir de n.mod; a forma é: «$(M2C) $(M2FLAGS) $(MODFLAGS)».
n.o é produzido automaticamente a partir de n.s executando o montador, as. A receita exata é «$(AS) $(ASFLAGS)».
n.s é produzido automaticamente a partir de n.S executando o pré-processador C, cpp. A receita exata é «$(CPP) $(CPPFLAGS)».
n é produzido automaticamente a partir de n.o executando o compilador C para ligar o programa. A receita exata usada é «$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)».
Esta regra faz a coisa certa para um programa simples com apenas um arquivo fonte. Ela também faz a coisa certa se houver vários arquivos objeto (presumivelmente vindos de diversos outros arquivos fonte), um dos quais tem um nome que coincide com o do arquivo executável. Assim,
x: y.o z.o
quando x.c, y.c e z.c existem todos, executará:
cc -c x.c -o x.o cc -c y.c -o y.o cc -c z.c -o z.o cc x.o y.o z.o -o x rm -f x.o rm -f y.o rm -f z.o
Em casos mais complicados, como quando não há nenhum arquivo objeto cujo nome derive do nome do arquivo executável, você precisa escrever uma receita explícita para a ligação.
Cada tipo de arquivo automaticamente convertido em arquivo objeto «.o» será automaticamente ligado usando o compilador («$(CC)», «$(FC)» ou «$(PC)»; o compilador C «$(CC)» é usado para montar arquivos «.s») sem a opção «-c». Isso poderia ser feito usando os arquivos objeto «.o» como intermediários, mas é mais rápido fazer a compilação e a ligação em uma só etapa, e por isso é assim que é feito.
n.c é produzido automaticamente a partir de n.y executando o Yacc com a receita «$(YACC) $(YFLAGS)».
n.c é produzido automaticamente a partir de n.l executando o Lex. A receita real é «$(LEX) $(LFLAGS)».
n.r é produzido automaticamente a partir de n.l executando o Lex. A receita real é «$(LEX) $(LFLAGS)».
A convenção de usar o mesmo sufixo «.l» para todos os arquivos Lex, independentemente de produzirem código C ou código Ratfor, torna impossível ao make determinar automaticamente qual das duas linguagens você está usando em cada caso específico. Quando o make é solicitado a refazer um arquivo objeto a partir de um arquivo «.l», ele tem que adivinhar qual compilador usar. Ele adivinhará o compilador C, porque esse é mais comum. Se você está usando Ratfor, certifique-se de que o make saiba disso mencionando n.r no makefile. Ou, se você está usando Ratfor exclusivamente, sem nenhum arquivo C, remova «.c» da lista de sufixos de regras implícitas com:
.SUFFIXES: .SUFFIXES: .o .r .f .l …
n.ln é produzido a partir de n.c executando o lint. A receita exata é «$(LINT) $(LINTFLAGS) $(CPPFLAGS) -i». A mesma receita é usada sobre o código C produzido a partir de n.y ou n.l.
n.dvi é produzido a partir de n.tex com a receita «$(TEX)». n.tex é produzido a partir de n.web com «$(WEAVE)», ou a partir de n.w (e de n.ch, se existir ou puder ser produzido) com «$(CWEAVE)». n.p é produzido a partir de n.web com «$(TANGLE)» e n.c é produzido a partir de n.w (e de n.ch, se existir ou puder ser produzido) com «$(CTANGLE)».
n.dvi é produzido a partir de n.texinfo, n.texi ou n.txinfo, com a receita «$(TEXI2DVI) $(TEXI2DVI_FLAGS)». n.info é produzido a partir de n.texinfo, n.texi ou n.txinfo, com a receita «$(MAKEINFO) $(MAKEINFO_FLAGS)».
Qualquer arquivo n é extraído, se necessário, de um arquivo RCS chamado n,v ou RCS/n,v. A receita exata usada é «$(CO) $(COFLAGS)». n não será extraído do RCS se já existir, mesmo que o arquivo RCS seja mais novo. As regras para RCS são terminais (terminal) (veja Regras de padrão que casam com qualquer coisa), de modo que arquivos RCS não podem ser gerados a partir de outra fonte; eles têm que existir de fato.
Qualquer arquivo n é extraído, se necessário, de um arquivo SCCS chamado s.n ou SCCS/s.n. A receita exata usada é «$(GET) $(GFLAGS)». As regras para SCCS são terminais (terminal) (veja Regras de padrão que casam com qualquer coisa), de modo que arquivos SCCS não podem ser gerados a partir de outra fonte; eles têm que existir de fato.
Em benefício do SCCS, um arquivo n é copiado de n.sh e tornado executável (por todos). Isso é para scripts de shell que estão sob controle do SCCS. Como o RCS preserva a permissão de execução de um arquivo, você não precisa usar este recurso com o RCS.
Recomendamos que você evite usar o SCCS. O RCS é amplamente tido como superior, e também é livre. Ao escolher software livre no lugar de software proprietário comparável (ou inferior), você apoia o movimento do software livre.
Normalmente, você quererá mudar apenas as variáveis listadas na tabela acima, que são documentadas na seção seguinte.
No entanto, as receitas nas regras implícitas embutidas usam, na verdade, variáveis como COMPILE.c, LINK.p e PREPROCESS.S, cujos valores contêm as receitas listadas acima.
O make segue a convenção de que a regra para compilar um arquivo fonte .x usa a variável COMPILE.x. Da mesma forma, a regra para produzir um executável a partir de um arquivo .x usa LINK.x; e a regra para pré-processar um arquivo .x usa PREPROCESS.x.
Toda regra que produz um arquivo objeto usa a variável OUTPUT_OPTION. O make define essa variável de modo que ela contenha «-o $@», ou de modo que fique vazia, dependendo de uma opção de tempo de compilação. Você precisa da opção «-o» para garantir que a saída vá para o arquivo certo quando o arquivo fonte está em um diretório diferente, como ao usar VPATH (veja Busca de diretórios para pré-requisitos). No entanto, os compiladores de alguns sistemas não aceitam uma chave «-o» para arquivos objeto. Se você usa um sistema desses e usa VPATH, algumas compilações colocarão a saída no lugar errado. Uma solução possível para esse problema é dar a OUTPUT_OPTION o valor «; mv $*.o $@».
As receitas nas regras implícitas embutidas fazem uso liberal de certas variáveis predefinidas. Você pode alterar os valores dessas variáveis no makefile, com argumentos para o make ou no ambiente, a fim de alterar como as regras implícitas funcionam sem redefinir as próprias regras. Você pode cancelar todas as variáveis usadas por regras implícitas com a opção «-R» ou «--no-builtin-variables».
Por exemplo, a receita usada para compilar um arquivo fonte C diz, na verdade, «$(CC) -c $(CFLAGS) $(CPPFLAGS)». Os valores padrão das variáveis usadas são «cc» e nada, resultando no comando «cc -c». Redefinindo «CC» para «ncc», você poderia fazer com que «ncc» fosse usado em todas as compilações de C realizadas pela regra implícita. Redefinindo «CFLAGS» para «-g», você poderia passar a opção «-g» a cada compilação. Todas as regras implícitas que fazem compilação de C usam «$(CC)» para obter o nome do programa do compilador e todas incluem «$(CFLAGS)» entre os argumentos dados ao compilador.
As variáveis usadas em regras implícitas dividem-se em duas classes: as que são nomes de programas (como CC) e as que contêm argumentos para os programas (como CFLAGS). (O «nome de um programa» também pode conter alguns argumentos de comando, mas tem que começar com um nome de programa executável de fato.) Se o valor de uma variável contém mais de um argumento, separe-os com espaços.
As tabelas a seguir descrevem algumas das variáveis predefinidas mais comumente usadas. Esta lista não é exaustiva, e os valores padrão mostrados aqui podem não ser o que o make seleciona para o seu ambiente. Para ver a lista completa de variáveis predefinidas da sua instância do GNU make, você pode executar «make -p» em um diretório sem makefiles.
Aqui está uma tabela de algumas das variáveis mais comuns usadas como nomes de programas nas regras embutidas:
ARPrograma de manutenção de arquivos de arquivo (archive); o padrão é «ar».
ASPrograma para compilar arquivos de assembly; o padrão é «as».
CCPrograma para compilar programas C; o padrão é «cc».
CXXPrograma para compilar programas C++; o padrão é «g++».
CPPPrograma para executar o pré-processador C, com os resultados na saída padrão; o padrão é «$(CC) -E».
FCPrograma para compilar ou pré-processar programas Fortran e Ratfor; o padrão é «f77».
M2CPrograma a usar para compilar código fonte Modula-2; o padrão é «m2c».
PCPrograma para compilar programas Pascal; o padrão é «pc».
COPrograma para extrair um arquivo do RCS; o padrão é «co».
GETPrograma para extrair um arquivo do SCCS; o padrão é «get».
LEXPrograma a usar para converter gramáticas Lex em código fonte; o padrão é «lex».
YACCPrograma a usar para converter gramáticas Yacc em código fonte; o padrão é «yacc».
LINTPrograma a usar para executar o lint sobre código fonte; o padrão é «lint».
MAKEINFOPrograma para converter um arquivo fonte Texinfo em um arquivo Info; o padrão é «makeinfo».
TEXPrograma para produzir arquivos DVI do TeX a partir de fonte TeX; o padrão é «tex».
TEXI2DVIPrograma para produzir arquivos DVI do TeX a partir de fonte Texinfo; o padrão é «texi2dvi».
WEAVEPrograma para traduzir Web em TeX; o padrão é «weave».
CWEAVEPrograma para traduzir C Web em TeX; o padrão é «cweave».
TANGLEPrograma para traduzir Web em Pascal; o padrão é «tangle».
CTANGLEPrograma para traduzir C Web em C; o padrão é «ctangle».
RMComando para remover um arquivo; o padrão é «rm -f».
Aqui está uma tabela de variáveis cujos valores são argumentos adicionais para os programas acima. O valor padrão de todas elas é a cadeia vazia, salvo indicação em contrário.
ARFLAGSSinalizadores a dar ao programa de manutenção de arquivos de arquivo; o padrão é «rv».
ASFLAGSSinalizadores extras a dar ao montador (quando invocado explicitamente sobre um arquivo «.s» ou «.S»).
CFLAGSSinalizadores extras a dar ao compilador C.
CXXFLAGSSinalizadores extras a dar ao compilador C++.
COFLAGSSinalizadores extras a dar ao programa co do RCS.
CPPFLAGSSinalizadores extras a dar ao pré-processador C e aos programas que o usam (os compiladores C e Fortran).
FFLAGSSinalizadores extras a dar ao compilador Fortran.
GFLAGSSinalizadores extras a dar ao programa get do SCCS.
LDFLAGSSinalizadores extras a dar aos compiladores quando eles devem invocar o ligador «ld», como -L. As bibliotecas (-lfoo) devem, em vez disso, ser acrescentadas à variável LDLIBS.
LDLIBSSinalizadores ou nomes de bibliotecas dados aos compiladores quando eles devem invocar o ligador «ld». LOADLIBES é uma alternativa obsoleta (mas ainda suportada) a LDLIBS. Sinalizadores de ligador que não são de biblioteca, como -L, devem ir na variável LDFLAGS.
LFLAGSSinalizadores extras a dar ao Lex.
YFLAGSSinalizadores extras a dar ao Yacc.
PFLAGSSinalizadores extras a dar ao compilador Pascal.
RFLAGSSinalizadores extras a dar ao compilador Fortran para programas Ratfor.
LINTFLAGSSinalizadores extras a dar ao lint.
Às vezes, um arquivo pode ser produzido por uma sequência de regras implícitas. Por exemplo, um arquivo n.o poderia ser produzido a partir de n.y executando primeiro o Yacc e depois o cc. Tal sequência é chamada de cadeia (chain).
Se o arquivo n.c existe, ou é mencionado no makefile, nenhuma busca especial é necessária: o make descobre que o arquivo objeto pode ser produzido por compilação de C a partir de n.c; mais tarde, ao considerar como produzir n.c, a regra para executar o Yacc é usada. Por fim, tanto n.c quanto n.o são atualizados.
No entanto, mesmo que n.c não exista e não seja mencionado, o make sabe imaginá-lo como o elo perdido entre n.o e n.y! Nesse caso, n.c é chamado de arquivo intermediário (intermediate file). Uma vez que o make decidiu usar o arquivo intermediário, ele é registrado na base de dados como se tivesse sido mencionado no makefile, juntamente com a regra implícita que diz como criá-lo.
Os arquivos intermediários são refeitos usando suas regras, exatamente como todos os outros arquivos. Mas os arquivos intermediários são tratados de forma diferente em dois aspectos.
A primeira diferença está no que acontece se o arquivo intermediário não existe. Se um arquivo comum b não existe, e o make considera um alvo que depende de b, ele invariavelmente cria b e então atualiza o alvo a partir de b. Mas se b é um arquivo intermediário, então o make pode deixar como está: ele não criará b a menos que um de seus pré-requisitos esteja desatualizado. Isso significa que o alvo que depende de b também não será reconstruído, a menos que haja alguma outra razão para atualizar esse alvo: por exemplo, o alvo não existe, ou um pré-requisito diferente é mais novo que o alvo.
A segunda diferença é que, se o make de fato cria b para atualizar outra coisa, ele apaga b mais tarde, depois que ele não é mais necessário. Portanto, um arquivo intermediário que não existia antes do make também não existe depois do make. O make informa a você sobre a remoção exibindo um comando «rm» que mostra qual arquivo ele está apagando.
Você pode marcar explicitamente um arquivo como intermediário listando-o como pré-requisito do alvo especial .INTERMEDIATE. Isso tem efeito mesmo que o arquivo seja mencionado explicitamente de alguma outra forma.
Um arquivo não pode ser intermediário se for mencionado no makefile como alvo ou pré-requisito, de modo que uma maneira de evitar a remoção de arquivos intermediários é adicioná-lo como pré-requisito de algum alvo. No entanto, fazer isso pode levar o make a realizar trabalho extra ao buscar regras de padrão (veja Algoritmo de busca de regras implícitas).
Como alternativa, listar um arquivo como pré-requisito do alvo especial .NOTINTERMEDIATE força que ele não seja considerado intermediário (assim como qualquer outra menção ao arquivo faria). Além disso, listar o padrão de alvo de uma regra de padrão como pré-requisito de .NOTINTERMEDIATE garante que nenhum alvo gerado usando essa regra de padrão seja considerado intermediário.
Você pode desabilitar completamente os arquivos intermediários no seu makefile fornecendo .NOTINTERMEDIATE como um alvo sem pré-requisitos: nesse caso, ele se aplica a todos os arquivos do makefile.
Se você não quer que o make crie um arquivo apenas porque ele ainda não existe, mas também não quer que o make apague o arquivo automaticamente, você pode marcá-lo como um arquivo secundário (secondary). Para isso, liste-o como pré-requisito do alvo especial .SECONDARY. Marcar um arquivo como secundário também o marca como intermediário.
Uma cadeia pode envolver mais de duas regras implícitas. Por exemplo, é possível produzir um arquivo foo a partir de RCS/foo.y,v executando RCS, Yacc e cc. Então tanto foo.y quanto foo.c são arquivos intermediários que são apagados no final.
Nenhuma regra implícita pode aparecer mais de uma vez em uma cadeia. Isso significa que o make não chegará nem a considerar uma coisa tão absurda como produzir foo a partir de foo.o.o executando o ligador duas vezes. Essa restrição tem o benefício adicional de impedir qualquer laço infinito na busca por uma cadeia de regras implícitas.
Existem algumas regras implícitas especiais para otimizar certos casos que, de outra forma, seriam tratados por cadeias de regras. Por exemplo, produzir foo a partir de foo.c poderia ser tratado compilando e ligando com regras encadeadas separadas, usando foo.o como arquivo intermediário. Mas o que de fato acontece é que uma regra especial para esse caso faz a compilação e a ligação com um único comando cc. A regra otimizada é usada de preferência à cadeia passo a passo, porque vem antes na ordenação das regras.
Por fim, por razões de desempenho, o make não considerará regras não terminais que casam com qualquer coisa (isto é, «%:») ao buscar uma regra para construir um pré-requisito de uma regra implícita (veja Regras de padrão que casam com qualquer coisa).
Você define uma regra implícita escrevendo uma regra de padrão (pattern rule). Uma regra de padrão se parece com uma regra comum, exceto que seu alvo contém o caractere «%» (exatamente um deles). O alvo é considerado um padrão para casar com nomes de arquivos; o «%» pode casar com qualquer subcadeia não vazia, enquanto os outros caracteres casam apenas consigo mesmos. Os pré-requisitos também usam «%» para mostrar como seus nomes se relacionam com o nome do alvo.
Assim, uma regra de padrão «%.o : %.c» diz como produzir qualquer arquivo stem.o a partir de outro arquivo stem.c.
Note que a expansão usando «%» em regras de padrão ocorre depois de quaisquer expansões de variável ou de função, que acontecem quando o makefile é lido. Veja Como usar variáveis e Funções para transformar texto.
Uma regra de padrão contém o caractere «%» (exatamente um deles) no alvo; de resto, ela se parece exatamente com uma regra comum. O alvo é um padrão para casar com nomes de arquivos; o «%» casa com qualquer subcadeia não vazia, enquanto os outros caracteres casam apenas consigo mesmos.
Por exemplo, «%.c» como padrão casa com qualquer nome de arquivo que termine em «.c». «s.%.c» como padrão casa com qualquer nome de arquivo que comece com «s.», termine em «.c» e tenha pelo menos cinco caracteres. (Tem que haver pelo menos um caractere para casar com o «%».) A subcadeia que o «%» casa é chamada de radical (stem).
O «%» em um pré-requisito de uma regra de padrão representa o mesmo radical que foi casado pelo «%» no alvo. Para que a regra de padrão se aplique, seu padrão de alvo tem que casar com o nome de arquivo em consideração e todos os seus pré-requisitos (após a substituição de padrão) têm que nomear arquivos que existem ou podem ser produzidos. Esses arquivos tornam-se pré-requisitos do alvo.
Assim, uma regra da forma
%.o : %.c ; recipe…
especifica como produzir um arquivo n.o, com outro arquivo n.c como seu pré-requisito, desde que n.c exista ou possa ser produzido.
Pode haver também pré-requisitos que não usam «%»; tal pré-requisito se anexa a todos os arquivos produzidos por essa regra de padrão. Esses pré-requisitos invariáveis são úteis ocasionalmente.
Uma regra de padrão não precisa ter nenhum pré-requisito que contenha «%», nem, de fato, nenhum pré-requisito. Tal regra é, na prática, um curinga geral. Ela fornece uma maneira de produzir qualquer arquivo que case com o padrão de alvo. Veja Definir regras padrão de último recurso.
Mais de uma regra de padrão pode casar com um alvo. Nesse caso, o make escolherá a regra de «melhor ajuste». Veja Como os padrões casam.
As regras de padrão podem ter mais de um alvo; no entanto, todo alvo tem que conter um caractere %. Múltiplos padrões de alvo em regras de padrão são sempre tratados como alvos agrupados (veja Múltiplos alvos em uma regra), independentemente de usarem o separador : ou &:.
Há apenas uma exceção. Se um alvo de padrão está desatualizado ou não existe, mas o makefile não precisa construí-lo, esse alvo não faz com que os outros alvos sejam considerados desatualizados. Note que essa exceção histórica está prevista para ser removida em uma versão futura do GNU make, de modo que você não deve contar com ela. Se o make detectar essa situação, emitirá um aviso pattern recipe did not update peer target (a receita de padrão não atualizou o alvo correlato). No entanto, o make não consegue detectar todas essas situações. Certifique-se de sempre atualizar todos os padrões de alvo quando a receita for executada.
Aqui estão alguns exemplos de regras de padrão de fato predefinidas no make. Primeiro, a regra que compila arquivos «.c» em arquivos «.o»:
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Ela define uma regra que pode produzir qualquer arquivo x.o a partir de x.c. A receita usa as variáveis automáticas «$@» e «$<» para substituir os nomes do arquivo-alvo e do arquivo fonte em cada caso em que a regra se aplica (veja Variáveis automáticas).
Aqui está uma segunda regra embutida:
% :: RCS/%,v
$(CO) $(COFLAGS) $<
Ela define uma regra que pode produzir qualquer arquivo x, seja ele qual for, a partir do arquivo correspondente x,v no subdiretório RCS. Como o alvo é «%», essa regra se aplica a qualquer arquivo, desde que o arquivo de pré-requisito apropriado exista. Os dois-pontos duplos tornam a regra terminal (terminal). Isso significa que seu pré-requisito não pode ser um arquivo intermediário (veja Regras de padrão que casam com qualquer coisa).
Esta regra de padrão tem dois alvos:
%.tab.c %.tab.h: %.y
bison -d $<
Ela diz ao make que a receita «bison -d x.y» produz tanto x.tab.c quanto x.tab.h. Se o arquivo foo depende dos arquivos parse.tab.o e scan.o, e o arquivo scan.o depende do arquivo parse.tab.h, então, quando parse.y é alterado, a receita «bison -d parse.y» será executada apenas uma vez, e os pré-requisitos tanto de parse.tab.o quanto de scan.o serão satisfeitos. (Presumivelmente, o arquivo parse.tab.o será recompilado a partir de parse.tab.c e o arquivo scan.o a partir de scan.c, enquanto foo é ligado a partir de parse.tab.o, scan.o e seus outros pré-requisitos, continuando a funcionar muito bem dali em diante.)
Suponha que você esteja escrevendo uma regra de padrão para compilar um arquivo «.c» em um arquivo «.o». Como você deveria escrever o comando «cc» de modo que ele opere sobre o nome de arquivo fonte correto? Você não pode escrever esse nome na receita, porque o nome é diferente a cada vez que a regra implícita se aplica.
É aí que entra um recurso especial do make, as variáveis automáticas (automatic variables). Essas variáveis têm seus valores recalculados de novo para cada regra que é executada, com base no alvo e nos pré-requisitos dessa regra. Neste exemplo, você usaria «$@» para o nome do arquivo objeto e «$<» para o nome do arquivo fonte.
É muito importante perceber que o alcance em que os valores das variáveis automáticas estão disponíveis é limitado. Esses valores só têm valor dentro da receita. Em particular, você não pode usá-los em parte alguma da lista de alvos de uma regra; ali eles não têm valor e se expandem para a cadeia vazia. Além disso, você não pode acessá-los diretamente na lista de pré-requisitos de uma regra. Um erro comum é tentar usar $@ na lista de pré-requisitos; isso não funciona. No entanto, o GNU make tem um recurso especial, a expansão secundária (veja Expansão secundária), com o qual você pode usar os valores das variáveis automáticas na lista de pré-requisitos.
Aqui está uma tabela de variáveis automáticas:
$@O nome de arquivo do alvo da regra. Se o alvo é um membro de arquivo de arquivo, «$@» é o nome do arquivo de arquivo. Em uma regra de padrão que tem múltiplos alvos (veja Introdução às regras de padrão), «$@» é o nome do alvo que fez com que a receita da regra fosse executada.
$%O nome do membro do alvo, quando o alvo é um membro de arquivo de arquivo. Veja Atualizar arquivos de arquivo com o make. Por exemplo, se o alvo é foo.a(bar.o), então «$%» é bar.o e «$@» é foo.a. Se o alvo não é um membro de arquivo de arquivo, «$%» fica vazio.
$<O nome do primeiro pré-requisito. Se o alvo obteve sua receita de uma regra implícita, este é o primeiro pré-requisito adicionado pela regra implícita (veja Uso de regras implícitas).
$?Os nomes de todos os pré-requisitos que são mais novos que o alvo, separados por espaços. Se o alvo não existe, todos os pré-requisitos são incluídos. Para pré-requisitos que são membros de arquivo de arquivo, apenas o membro especificado é usado (veja Atualizar arquivos de arquivo com o make).
«$?» também é útil em regras explícitas, quando você quer operar apenas sobre os pré-requisitos que mudaram. Por exemplo, suponha que um arquivo de arquivo chamado lib deva guardar cópias de vários arquivos objeto. A regra a seguir copia para o arquivo de arquivo apenas os arquivos objeto que mudaram:
lib: foo.o bar.o lose.o win.o
ar r lib $?
$^Os nomes de todos os pré-requisitos, separados por espaços. Para pré-requisitos que são membros de arquivo de arquivo, apenas o membro especificado é usado (veja Atualizar arquivos de arquivo com o make). Um alvo tem apenas um pré-requisito para cada arquivo de que depende, por mais vezes que o mesmo arquivo apareça listado como pré-requisito. Assim, se você lista o mesmo pré-requisito mais de uma vez para um alvo, o valor de $^ contém apenas uma cópia desse nome. Esta lista não contém os pré-requisitos do tipo apenas-ordem; para esses, veja a variável «$|» a seguir.
$+Isto é como «$^», mas os pré-requisitos listados mais de uma vez são duplicados na ordem em que foram listados no makefile. Isto é útil principalmente em comandos de ligação, em que repetir nomes de arquivos de biblioteca em uma ordem específica tem significado.
$|Os nomes de todos os pré-requisitos do tipo apenas-ordem, separados por espaços.
$*O radical com que uma regra implícita casou (veja Como os padrões casam). Se o alvo é dir/a.foo.b e o padrão de alvo é a.%.b, o radical é dir/foo. O radical é útil para construir nomes de arquivos relacionados.
Em regras de padrão estáticas, o radical é a parte do nome de arquivo que casou com o «%» do padrão de alvo.
As regras explícitas não têm radical, de modo que «$*» não pode ser determinado dessa forma para elas. Em vez disso, se o nome do alvo termina com um sufixo reconhecido (veja Regras de sufixo à moda antiga), «$*» é definido como o nome do alvo com esse sufixo removido. Por exemplo, se o nome do alvo é «foo.c», então «$*» é definido como «foo», já que «.c» é um sufixo. O GNU make faz essa coisa estranha apenas por compatibilidade com outras implementações do make. Em geral, você deve evitar usar «$*» fora de regras implícitas ou de regras de padrão estáticas.
Se o nome do alvo em uma regra explícita não termina com um sufixo reconhecido, «$*» é definido como a cadeia vazia para essa regra.
Quatro das variáveis listadas acima têm como valor um único nome de arquivo, e três têm como valor uma lista de nomes de arquivos. Essas sete variáveis têm variantes que obtêm apenas o nome de diretório do arquivo, ou apenas o nome de arquivo dentro do diretório. Os nomes das variáveis variantes são formados acrescentando «D» ou «F» ao final, respectivamente. Essas variantes são, em parte, obsoletas, já que se pode obter o mesmo efeito com as funções dir e notdir (veja Funções para nomes de arquivos). Note, porém, que todas as variantes «D» omitem a barra final, enquanto a saída da função dir sempre apresenta a barra final. Aqui está uma tabela das variantes:
A parte de diretório do nome de arquivo do alvo, com a barra final removida. Se o valor de «$@» é dir/foo.o, então «$(@D)» é dir. Se «$@» não contém barra, esse valor é ..
A parte do nome de arquivo dentro do diretório, do nome de arquivo do alvo. Se o valor de «$@» é dir/foo.o, então «$(@F)» é foo.o. «$(@F)» é equivalente a «$(notdir $@)».
A parte de diretório e a parte do nome de arquivo dentro do diretório, do radical. Neste exemplo, são dir e foo.
A parte de diretório e a parte do nome de arquivo dentro do diretório, do nome do membro de arquivo de arquivo do alvo. Isto só faz sentido para alvos de membro de arquivo de arquivo da forma archive(member) e só é útil quando member pode conter um nome de diretório. (Veja Membros de arquivo como alvos.)
A parte de diretório e a parte do nome de arquivo dentro do diretório, do primeiro pré-requisito.
As listas das partes de diretório e das partes do nome de arquivo dentro do diretório, de todos os pré-requisitos.
As listas das partes de diretório e das partes do nome de arquivo dentro do diretório, de todos os pré-requisitos, incluindo múltiplas instâncias de pré-requisitos duplicados.
As listas das partes de diretório e das partes do nome de arquivo dentro do diretório, de todos os pré-requisitos que são mais novos que o alvo.
Note que usamos uma convenção estilística especial ao falar dessas variáveis automáticas. Escrevemos «o valor de “$<”» em vez de escrever «a variável <», como faríamos ao falar de variáveis comuns como objects e CFLAGS. Achamos que essa convenção parece mais natural neste caso especial. Por favor, não leia nenhum significado profundo nisso. «$<» se refere à variável chamada <, exatamente como «$(CFLAGS)» se refere à variável chamada CFLAGS. Você poderia igualmente escrever «$(<)» em vez de «$<».
Um padrão de alvo é constituído colocando-se um «%» entre um prefixo e um sufixo, qualquer um dos quais (ou ambos) pode ser vazio. O padrão casa com um nome de arquivo apenas se o nome de arquivo começa com o prefixo e termina com o sufixo, sem sobreposição entre os dois. O texto entre o prefixo e o sufixo é chamado de radical (stem). Assim, quando o padrão «%.o» casa com o nome de arquivo test.o, o radical é «test». Os pré-requisitos da regra de padrão são convertidos em nomes de arquivos reais substituindo-se o caractere «%» pelo radical. Assim, no mesmo exemplo, se um dos pré-requisitos está escrito como «%.c», ele se expande para «test.c».
Quando o padrão de alvo não contém barra (e normalmente não contém), os nomes de diretório no nome de arquivo são removidos do nome de arquivo antes de ser comparado com o prefixo e o sufixo do alvo. Depois da comparação do nome de arquivo com o padrão de alvo, os nomes de diretório, junto com a barra que os termina, são acrescentados ao início dos padrões de pré-requisito e dos nomes de arquivo de pré-requisito gerados a partir do nome de arquivo. Os diretórios são ignorados apenas para o propósito de encontrar a regra implícita a usar, não na aplicação dessa regra. Assim, «e%t» casa com o nome de arquivo src/eat, com «src/a» como o radical. Quando os pré-requisitos são convertidos em nomes de arquivos, os diretórios do radical são acrescentados ao início, enquanto o resto do radical é substituído pelo «%». O radical «src/a» com o padrão de pré-requisito «c%r» dá o nome de arquivo src/car.
Uma regra de padrão pode ser usada para construir um determinado arquivo apenas se houver um padrão de alvo que case com o nome desse arquivo, e se todos os pré-requisitos dessa regra existirem ou puderem ser construídos. As regras que você escreve têm precedência sobre as regras embutidas. Note, porém, que uma regra cujos pré-requisitos possam ser satisfeitos sem encadear outras regras implícitas (por exemplo, uma regra sem pré-requisitos, ou cujos pré-requisitos já existem ou são mencionados) tem sempre precedência sobre uma regra com pré-requisitos que precisam ser produzidos encadeando outras regras implícitas.
Pode haver mais de uma regra de padrão que satisfaça esses critérios. Nesse caso, o make escolherá a regra com o radical mais curto (ou seja, o padrão que casa de forma mais específica). Se houver mais de uma regra de padrão com o radical mais curto, o make escolherá a primeira encontrada no makefile.
Como resultado desse algoritmo, as regras mais específicas têm precedência sobre as mais gerais. Por exemplo:
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
%.o : %.f
$(COMPILE.F) $(OUTPUT_OPTION) $<
lib/%.o: lib/%.c
$(CC) -fPIC -c $(CFLAGS) $(CPPFLAGS) $< -o $@
Tendo essas regras, quando se pede para construir bar.o e tanto bar.c quanto bar.f existem, o make escolhe a primeira regra e compila bar.c em bar.o. Na mesma situação, se bar.c não existe, o make escolhe a segunda regra e compila bar.f em bar.o.
Quando se pede ao make para construir lib/bar.o e tanto lib/bar.c quanto lib/bar.f existem, é a terceira regra que é escolhida, porque o radical dessa regra («bar») é mais curto que o radical da primeira regra («lib/bar»). Se lib/bar.c não existe, a terceira regra deixa de ser elegível e a segunda regra é usada, mesmo que seu radical seja mais longo.
Quando o alvo de uma regra de padrão é apenas «%», ele casa com qualquer nome de arquivo, seja ele qual for. Chamamos essas regras de regras que casam com qualquer coisa (match-anything). Elas são muito úteis, mas pode levar muito tempo para o make considerá-las, já que ele tem que considerar todas essas regras para cada nome de arquivo listado como alvo ou pré-requisito.
Suponha que o makefile mencione foo.c. Para esse alvo, o make teria que considerar produzi-lo ligando o arquivo objeto foo.c.o, ou fazendo a compilação e a ligação de C em uma só etapa a partir de foo.c.c, ou fazendo a compilação Pascal e a ligação a partir de foo.c.p, e ainda muitas outras possibilidades.
Sabemos que essas possibilidades são absurdas, já que foo.c é um arquivo fonte C e não um arquivo executável. Se o make considerasse essas possibilidades, acabaria por rejeitá-las, porque arquivos como foo.c.o e foo.c.p não existem. Mas essas possibilidades são tantas que, se o make tivesse que considerá-las, ficaria muito lento.
Para ganhar velocidade, estabelecemos várias restrições sobre a forma como o make considera as regras que casam com qualquer coisa. Há dois tipos de restrição que podem ser aplicadas e, cada vez que você define uma regra que casa com qualquer coisa, tem que escolher um dos dois para essa regra.
Uma opção é especificar a regra que casa com qualquer coisa como terminal (terminal), definindo-a com dois-pontos duplos. Quando uma regra é terminal, ela não se aplica a menos que seus pré-requisitos existam de fato. Pré-requisitos que poderiam ser produzidos por outras regras implícitas não bastam. Em outras palavras, nenhum encadeamento adicional é permitido além de uma regra terminal.
Por exemplo, as regras implícitas embutidas que extraem fontes de arquivos RCS ou SCCS são terminais; como consequência, se o arquivo foo.c,v não existe, o make não chegará nem a considerar produzi-lo como um arquivo intermediário a partir de foo.c,v.o ou RCS/SCCS/s.foo.c,v. Os arquivos RCS e SCCS são, em geral, arquivos fonte últimos, que não devem ser refeitos a partir de nenhum outro arquivo; portanto, o make pode poupar tempo não procurando maneiras de refazê-los.
Se você não especifica uma regra que casa com qualquer coisa como terminal, ela é não terminal. Uma regra não terminal que casa com qualquer coisa não pode se aplicar a um pré-requisito de uma regra implícita, nem pode se aplicar a um nome de arquivo que indica um tipo específico de dados. Diz-se que um nome de arquivo indica um tipo específico de dados se algum alvo de uma regra implícita que não casa com qualquer coisa casa com ele.
Por exemplo, o nome de arquivo foo.c casa com o alvo da regra de padrão «%.c : %.y» (a regra que executa o Yacc). Independentemente de essa regra ser de fato aplicável (o que só acontece se houver um arquivo foo.y), o simples fato de seu alvo casar já basta para impedir que regras não terminais que casam com qualquer coisa sejam consideradas para o arquivo foo.c. Assim, o make não chegará nem a considerar produzir foo.c como arquivo executável a partir de foo.c.o, foo.c.c, foo.c.p, etc.
A motivação dessa restrição é a seguinte: as regras não terminais que casam com qualquer coisa são usadas para produzir arquivos que contêm um tipo específico de dados (como arquivos executáveis), ao passo que um nome de arquivo com um sufixo reconhecido indica outro tipo específico de dados (como um arquivo fonte C).
Para reconhecer determinados nomes de arquivo e impedir que regras não terminais que casam com qualquer coisa sejam consideradas, existem regras de padrão fictícias embutidas, especiais e prontas. Essas regras fictícias não têm pré-requisitos nem receita e são ignoradas para todos os demais propósitos. Por exemplo, a regra implícita embutida
%.p :
existe para fazer com que arquivos fonte Pascal como foo.p casem com um padrão de alvo específico e, assim, impedir que se desperdice tempo procurando por foo.p.o ou foo.p.c.
Regras de padrão fictícias como a de «%.p» são criadas para cada sufixo listado como válido para uso em regras de sufixo (veja Regras de sufixo à moda antiga).
Você pode sobrepor uma regra implícita embutida (ou uma que você mesmo tenha definido) definindo uma nova regra de padrão com o mesmo alvo e os mesmos pré-requisitos, mas uma receita diferente. Quando a nova regra é definida, a regra embutida é substituída. A posição da nova regra na ordenação das regras implícitas é determinada por onde você escreve a nova regra.
Você pode cancelar uma regra implícita embutida definindo uma regra de padrão com o mesmo alvo e os mesmos pré-requisitos, mas sem receita. Por exemplo, o seguinte cancela a regra que executa o montador:
%.o : %.s
Você pode definir uma regra implícita de último recurso escrevendo uma regra de padrão terminal que casa com qualquer coisa e que não tem pré-requisitos (veja Regras de padrão que casam com qualquer coisa). Isto é exatamente como qualquer outra regra de padrão; a única coisa especial é que ela casa com qualquer alvo. Assim, a receita de tal regra é usada para todos os alvos e pré-requisitos que não têm receita própria e aos quais nenhuma outra regra implícita se aplica.
Por exemplo, ao testar um makefile, você pode não se importar se os arquivos fonte contêm dados reais, apenas que eles existam. Nesse caso, você pode fazer o seguinte:
%::
touch $@
para fazer com que todos os arquivos fonte necessários (como pré-requisitos) sejam criados automaticamente.
Em vez disso, você pode definir uma receita a ser usada para alvos sem nenhuma regra — incluindo aqueles para os quais nem mesmo uma receita está especificada. Você faz isso escrevendo uma regra para o alvo .DEFAULT. A receita de tal regra é usada para todos os pré-requisitos que não aparecem como alvo de nenhuma regra explícita e aos quais nenhuma regra implícita se aplica. Naturalmente, não há regra .DEFAULT a menos que você a escreva.
Se você usa .DEFAULT sem receita nem pré-requisitos:
.DEFAULT:
a receita que estava antes guardada para .DEFAULT é apagada. Então o make age como se você nunca tivesse definido .DEFAULT coisa nenhuma.
Se você não quer que um alvo obtenha sua receita de uma regra de padrão que casa com qualquer coisa ou de .DEFAULT, mas também não quer que nenhuma receita seja executada para esse alvo, você pode dar a ele uma receita vazia (veja Definir receitas vazias).
Você também pode usar uma regra de último recurso para sobrepor parte de outro makefile. Veja Sobrepor parte de outro Makefile.
As regras de sufixo (suffix rules) são a forma à moda antiga de definir regras implícitas para o make. As regras de sufixo estão ultrapassadas, porque as regras de padrão são mais gerais e mais claras. Elas têm suporte no GNU make por compatibilidade com makefiles antigos. Há dois tipos de regras de sufixo: de sufixo duplo (double-suffix) e de sufixo único (single-suffix).
Uma regra de sufixo duplo é definida por um par de sufixos: o sufixo de alvo e o sufixo de fonte. Ela casa com qualquer arquivo cujo nome termina com o sufixo de alvo. O pré-requisito implícito correspondente é produzido substituindo-se o sufixo de alvo no nome de arquivo pelo sufixo de fonte. Uma regra de sufixo duplo «.c.o» (cujos sufixos de alvo e de fonte são «.o» e «.c», respectivamente) é equivalente à regra de padrão «%.o : %.c».
Uma regra de sufixo único é definida por um único sufixo, que é o sufixo de fonte. Ela casa com qualquer nome de arquivo, e o nome do pré-requisito implícito correspondente é produzido acrescentando-se o sufixo de fonte ao final. Uma regra de sufixo único cujo sufixo de fonte é «.c» é equivalente à regra de padrão «% : %.c».
As definições de regras de sufixo são reconhecidas comparando-se o alvo de cada regra com a lista predefinida de sufixos conhecidos. Quando o make encontra uma regra cujo alvo é um sufixo conhecido, ele considera essa regra uma regra de sufixo único. Quando o make encontra uma regra cujo alvo é a concatenação de dois sufixos conhecidos, ele considera essa regra uma regra de sufixo duplo.
Por exemplo, «.c» e «.o» estão ambos na lista padrão de sufixos conhecidos. Portanto, se você define uma regra cujo alvo é «.c.o», o make a considera uma regra de sufixo duplo cujo sufixo de fonte é «.c» e cujo sufixo de alvo é «.o». Aqui está a definição à moda antiga da regra para compilar um arquivo fonte C:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
As regras de sufixo não podem ter pré-requisitos próprios. Se tiverem, elas são tratadas como arquivos comuns com nomes estranhos, e não como regras de sufixo. Assim, a regra:
.c.o: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
diz como produzir o arquivo .c.o a partir do arquivo de pré-requisito foo.h, e é completamente diferente da regra de padrão:
%.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
Esta última diz como produzir arquivos «.o» a partir de arquivos «.c» e, ao mesmo tempo, faz com que todos os arquivos «.o» produzidos por essa regra de padrão dependam também de foo.h.
Uma regra de sufixo sem receita também não tem sentido. Ela não remove regras anteriores, ao contrário de uma regra de padrão sem receita, que remove a regra anterior (veja Cancelar regras implícitas). Ela simplesmente registra o sufixo, ou o par de sufixos concatenados, como alvo na base de dados.
Os sufixos conhecidos são, em suma, os nomes dos pré-requisitos do alvo especial .SUFFIXES. Você pode adicionar seus próprios sufixos escrevendo uma regra que acrescente pré-requisitos a .SUFFIXES. Faça assim:
.SUFFIXES: .hack .win
Isto acrescenta «.hack» e «.win» ao final da lista de sufixos.
Se você quer remover os sufixos conhecidos padrão, em vez de acrescentar a eles, escreva uma regra para .SUFFIXES sem pré-requisitos. Por um arranjo especial, isto remove todos os pré-requisitos existentes de .SUFFIXES. Você pode então escrever outra regra para acrescentar os sufixos que quiser. Por exemplo:
.SUFFIXES: # Remove os sufixos padrão .SUFFIXES: .c .o .h # Define a sua própria lista de sufixos
O sinalizador «-r» ou «--no-builtin-rules» faz com que a lista de sufixos padrão fique vazia.
A variável SUFFIXES é definida com a lista padrão de sufixos antes de o make ler qualquer makefile. Você pode mudar a lista de sufixos com uma regra para o alvo especial .SUFFIXES, mas isso não muda essa variável.
Aqui está o procedimento que o make usa para buscar uma regra implícita para um alvo t. Esse procedimento é seguido para cada regra de dois-pontos duplo sem receita, para cada alvo de uma regra comum que não tem receita, e para cada pré-requisito que não é alvo de nenhuma regra. Ele também é seguido recursivamente para pré-requisitos que vêm de regras implícitas, na busca por uma cadeia de regras.
Este algoritmo não menciona as regras de sufixo, porque elas são convertidas em regras de padrão equivalentes depois que os makefiles são lidos.
Para um alvo de membro de arquivo de arquivo da forma «archive(member)», o algoritmo a seguir é executado duas vezes, primeiro usando o nome de alvo inteiro t e, se nenhuma regra for encontrada na primeira vez, novamente usando «(member)» como o alvo t.
Se todos os pré-requisitos existem ou deveriam existir, ou se não há nenhum pré-requisito, esta regra se aplica.
.DEFAULT, se houver uma. Nesse caso, t recebe a mesma receita que .DEFAULT tem. Caso contrário, t não tem receita.
Quando uma regra que se aplica é encontrada, para cada padrão de alvo dessa regra que não seja o que casou com t ou n, o «%» do padrão é substituído por s e o nome de arquivo resultante é guardado até que a receita para refazer o arquivo-alvo t seja executada. Depois que a receita é executada, cada um desses nomes de arquivos guardados é registrado na base de dados e marcado como atualizado e com o mesmo status de atualização do arquivo t.
Quando a receita de uma regra de padrão é executada para t, as variáveis automáticas são definidas de acordo com o alvo e os pré-requisitos. Veja Variáveis automáticas.