Esse comportamento não é um erro. É uma característica. Um recurso e um possível erro do usuário para ser preciso.
O recurso em questão é uma das regras implícitas do Make. No seu caso, a regra implícita para "construir" arquivos *.sh
. O erro do usuário, seu erro, não está alterando o diretório de trabalho antes de invocar o makefile nos subdiretórios.
TL; DR: para corrigir isso, você pode fazer um ou mais dos seguintes procedimentos:
-
Corrija o script de shell para alterar o diretório de trabalho:
#!/bin/bash for f in *; do if [[ -d $f && -f $f/makefile ]]; then echo "Making clean in $f..." (cd $f; make clean) fi done
-
Torne as regras vazias explícitas:
clean: ;
-
Torne os alvos
clean
falsos:.PHONY: clean
Explicação detalhada:
Make tem várias regras implícitas. Isso permite invocar make em projetos simples sem escrever um makefile.
Tente isso para uma demonstração:
- crie um diretório vazio e mude para o diretório
- crie um arquivo chamado
clean.sh
. - executar
make clean
Saída:
$ make clean
cat clean.sh >clean
chmod a+x clean
BAM! Esse é o poder das regras implícitas de make. Consulte o manual sobre as regras implícitas para obter mais informações.
Tentarei responder à pergunta aberta restante:
Por que ele não invoca a regra implícita para o primeiro makefile? Como você substituiu a regra implícita pela regra clean
explícita.
Por que a regra clean
no segundo makefile não sobrescreve a regra implícita? Porque não tinha receita. As regras sem receita não sobrescrevem as regras implícitas, em vez disso, apenas acrescentam pré-requisitos. Consulte o manual sobre várias regras para obter mais informações. Veja também o manual sobre regras com receitas vazias explícitas .
Por que é um erro não alterar o diretório de trabalho antes de invocar um makefile em um subdiretório? Porque make não altera o diretório de trabalho. Make funcionará no diretório de trabalho herdado. Bem, tecnicamente, isso não é necessariamente um erro, mas na maioria das vezes é. Você deseja que os makefiles nos subdiretórios funcionem nos subdiretórios? Ou você quer que eles trabalhem no diretório pai?
Por que ignorar a regra clean
explícita do primeiro makefile na segunda invocação de clean.sh
? Porque agora o arquivo de destino clean
já existe. Como a regra clean
não tem pré-requisitos, não é necessário reconstruir o destino. Consulte o manual sobre os destinos falsos , que descreve exatamente esse problema.
Por que a busca pelo alvo three/makefile
na terceira invocação? Porque o make sempre tenta refazer os makefiles antes de fazer qualquer outra coisa. Isso é especialmente verdadeiro se o makefile for solicitado explicitamente usando -f
, mas não existe. Consulte o manual sobre como refazer os makefiles para obter mais informações.