Digamos que eu tenha um makefile com a regra
%.o: %.c
gcc -Wall -Iinclude ...
Quero que * .o seja reconstruído sempre que um arquivo de cabeçalho for alterado. Em vez de elaborar uma lista de dependências, sempre que qualquer arquivo de cabeçalho for /include
alterado, todos os objetos no diretório devem ser reconstruídos.
Não consigo pensar em uma maneira legal de mudar a regra para acomodar isso, estou aberto a sugestões. Pontos de bônus se a lista de cabeçalhos não precisar ser codificada
Respostas:
Se você estiver usando um compilador GNU, o compilador pode montar uma lista de dependências para você. Fragmento de Makefile:
ou
onde
SRCS
é uma variável apontando para sua lista inteira de arquivos de origem.Existe também a ferramenta
makedepend
, mas nunca gostei tanto quantogcc -MM
fonte
depend
executá-lo apenas quando os arquivos de origem foram alterados? Parece funcionar sempre, independentemente ...build/file.o
?A maioria das respostas é surpreendentemente complicada ou errônea. No entanto, exemplos simples e robustos foram postados em outro lugar [ codereview ]. É certo que as opções fornecidas pelo pré-processador GNU são um pouco confusas. No entanto, a remoção de todos os diretórios do destino de construção com
-MM
está documentada e não é um bug [ gpp ]:A opção (um pouco mais recente)
-MMD
é provavelmente o que você deseja. Para completar, um exemplo de um makefile que suporta vários diretórios src e diretórios de construção com alguns comentários. Para uma versão simples sem diretórios de compilação, consulte [ codereview ].Este método funciona porque se houver várias linhas de dependência para um único destino, as dependências serão simplesmente unidas, por exemplo:
é equivalente a:
conforme mencionado em: Makefile várias linhas de dependência para um único destino?
fonte
CPP
deve ser lidoCPPS
a.cpp
,b.cpp
) em./src/
, essa substituição não faria$(OBJ)=./build/src/a.o ./build/src/b.o
?Como postei aqui, o gcc pode criar dependências e compilar ao mesmo tempo:
O parâmetro '-MF' especifica um arquivo para armazenar as dependências.
O traço no início de '-include' diz ao Make para continuar quando o arquivo .d não existir (por exemplo, na primeira compilação).
Observe que parece haver um bug no gcc em relação à opção -o. Se você definir o nome do arquivo do objeto como obj / _file__c.o, o arquivo .d gerado ainda conterá o arquivo .o, não obj / _file__c.o.
fonte
man gcc
diz-MM
implica-E
, que "para após o pré-processamento". Em-MMD
vez disso, você precisa : stackoverflow.com/a/30142139/895245Que tal algo como:
Você também pode usar os curingas diretamente, mas tendo a descobrir que preciso deles em mais de um lugar.
Observe que isso só funciona bem em projetos pequenos, uma vez que assume que todo arquivo de objeto depende de todo arquivo de cabeçalho.
fonte
make clean all
todas as vezes.gcc
linha não é executada, mas a regra interna (%o: %.c
regra) é executada.A solução de Martin acima funciona muito bem, mas não lida com arquivos .o que residem em subdiretórios. Godric aponta que o sinalizador -MT cuida desse problema, mas simultaneamente impede que o arquivo .o seja escrito corretamente. O seguinte cuidará de ambos os problemas:
fonte
Isso fará o trabalho muito bem e até mesmo manipulará subdiretórios sendo especificados:
testei com gcc 4.8.3
fonte
Aqui está uma linha dupla:
Isso funciona com a receita padrão do make, contanto que você tenha uma lista de todos os seus arquivos de objeto em
OBJS
.fonte
Eu prefiro esta solução, em vez da resposta aceita por Michael Williamson, ela captura as alterações em fontes + arquivos embutidos, em seguida, fontes + cabeçalhos e, finalmente, apenas fontes. A vantagem aqui é que a biblioteca inteira não é recompilada se apenas algumas mudanças forem feitas. Não é uma grande consideração para um projeto com alguns arquivos, mas se você tiver 10 ou 100 fontes, notará a diferença.
fonte
O seguinte funciona para mim:
fonte
Uma versão ligeiramente modificada da resposta de Sophie que permite enviar os arquivos * .d para uma pasta diferente (vou colar apenas a parte interessante que gera os arquivos de dependência):
Observe que o parâmetro
é usado para garantir que os destinos (ou seja, os nomes dos arquivos de objeto) nos arquivos * .d gerados contenham o caminho completo para os arquivos * .o e não apenas o nome do arquivo.
Não sei por que este parâmetro NÃO é necessário ao usar -MMD em combinação com -c (como na versão de Sophie ). Nesta combinação, parece gravar o caminho completo dos arquivos * .o nos arquivos * .d. Sem essa combinação, -MMD também grava apenas os nomes de arquivo puros sem quaisquer componentes de diretório nos arquivos * .d. Talvez alguém saiba por que -MMD grava o caminho completo quando combinado com -c. Não encontrei nenhuma dica na página de manual do g ++.
fonte