Digamos que eu tenha um Makefile que tenha dois destinos “principais”: foo.o
e clean
. O primeiro tem uma receita para criar o foo.o
arquivo. O último remove todos os arquivos temporários.
Para remover a necessidade de especificar as dependências foo.o
manualmente, tenho um target foo.d
que é um makefile válido especificando as dependências no formato foo.o foo.d : dep1 dep2 depn
. Este arquivo de dependência está incluído no makefile.
O makefile fica assim:
;; This buffer is for text that is not saved, and for Lisp evaluation.
;; To create a file, visit it with C-x C-f and enter text in its buffer.
foo.o: foo.c
cc -c -o $@ $<
foo.d: foo.c
sh deps.sh $< > $@
include foo.d
.PHONY: clean
clean:
rm …
Quando eu quero fazer foo.o
, tudo funciona corretamente: foo.d
obtém (re)feito, é incluído e foo.o
é feito. O problema é que quando eu quero fazer o clean
alvo, foo.d
fica incluso, ou até mesmo feito.
Como posso evitar fazer incluindo foo.d
quando o clean
alvo está sendo feito? (Ou, como incluir isso apenas quando foo.o
for feito?)
A solução pode usar recursos do GNU Make.
A solução é bastante simples, mas resulta em um código Makefile um tanto ilegível.
Primeiro, devemos saber que a
include
diretiva tenta incluir o arquivo e, se não existir, falha. Há também-include
(ousinclude
) que simplesmente não inclui o arquivo, caso ele não exista. Mas isso não é o que queremos, porque ainda tenta refazer o makefile incluído, se possível.Podemos evitar isso de duas maneiras: alterando o parâmetro da diretiva include de forma que o Makefile pense que não é capaz de criar esse arquivo incluído (por exemplo, caminho relativo vs absoluto etc.), ou omitindo o parâmetro quando o arquivo não existir. Isso pode ser feito de várias maneiras:
mas isso tem um problema: combina também com outros arquivos. Então podemos escrever isso:
ou mesmo isso:
E fizemos outro problema:
foo.d
não se faz. Isso é resolvido adicionando-o como outro destino dofoo.o
:ou adicionando-o como um comando:
ou diretamente, sem invocar
make
: