Eu usei o rake um pouco (um programa Ruby make) e tem uma opção para obter uma lista de todos os destinos disponíveis, por exemplo
> rake --tasks
rake db:charset # retrieve the charset for your data...
rake db:collation # retrieve the collation for your da...
rake db:create # Creates the databases defined in y...
rake db:drop # Drops the database for your curren...
...
mas parece não haver opção para fazer isso no GNU make.
Aparentemente, o código está quase lá para ele em 2007 - http://www.mail-archive.com/[email protected]/msg06434.html .
Enfim, fiz pouco hack para extrair os alvos de um makefile, que você pode incluir em um makefile.
list:
@grep '^[^#[:space:]].*:' Makefile
Ele fornecerá uma lista dos destinos definidos. É apenas um começo - não filtra as dependências, por exemplo.
> make list
list:
copy:
run:
plot:
turnin:
alias makefile-targets='grep "^[^#[:space:]].*:" Makefile'
Na maioria das vezes, só preciso examinar o makefile atual e a conclusão do bash se expande meu apelido.grep : Makefile
:?Respostas:
Esta é uma tentativa de melhorar a excelente abordagem do @ nobar da seguinte maneira:
sh -c
)-f <file>
@
para impedir que ele seja ecoado antes da execuçãoCuriosamente, o GNU
make
não tem nenhum recurso para listar apenas os nomes dos destinos definidos em um makefile. A-p
opção produz resultados que incluem todos os destinos, mas os enterram em muitas outras informações.Coloque a seguinte regra em um makefile para o GNU
make
implementar um destino nomeadolist
que simplesmente lista todos os nomes de destinos em ordem alfabética - ie: invoke asmake list
:Importante : Ao colar isso, verifique se a última linha é recuada com exatamente 1 caractere de tabulação real. (espaços não funcionam) .
Observe que a classificação da lista de destinos resultante é a melhor opção, pois a não classificação não produz uma ordem útil, pois a ordem na qual os destinos aparecem no makefile não é preservada.
Além disso, os subalvos de uma regra que compreende vários destinos são sempre emitidos separadamente e, portanto, devido à classificação, geralmente não são aparecem próximos um do outro; por exemplo, uma regra que começa com
a z:
o não têm metasa
ez
listados ao lado do outro na saída, se houver alvos adicionais.Explicação da regra :
PHONY: list
$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null
make
novamente para imprimir e analisar o banco de dados derivado do makefile:-p
imprime o banco de dados-Rr
suprime a inclusão de regras e variáveis internas-q
apenas testa o status atualizado de um destino (sem refazer nada), mas isso por si só não impede a execução de comandos de receita em todos os casos; conseqüentemente:-f $(lastword $(MAKEFILE_LIST))
garante que o mesmo makefile seja direcionado como na invocação original, independentemente de ter sido direcionado implícita ou explicitamente-f ...
.Advertência : Isso será interrompido se o seu makefile contiver
include
diretivas; Para resolver isso, defina a variávelTHIS_FILE := $(lastword $(MAKEFILE_LIST))
antes de qualquerinclude
diretiva e use-f $(THIS_FILE)
.:
é um destino deliberadamente inválido que visa garantir que nenhum comando seja executado ;2>/dev/null
suprime a mensagem de erro resultante. Nota: Isso depende da-p
impressão do banco de dados, no entanto, como é o caso do GNU make 3.82. Infelizmente, o GNU make não oferece opção direta para apenas imprimir o banco de dados, sem também executar a tarefa padrão (ou fornecida); se você não precisar segmentar um Makefile específico, poderá usá-lomake -p -f/dev/null
, conforme recomendado naman
página.-v RS=
/^# File/,/^# Finished Make data base/
if ($$1 !~ "^[#.]")
#
... ignora não-alvos, cujos blocos começam com# Not a target:
.
... ignora alvos especiais:
egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
remove destinos indesejados da saída:'^[^[:alnum:]]'
... exclui oculto alvos , que - por convenção - são alvos que não começam com uma letra nem um dígito.'^$@$$'
... exclui olist
próprio alvoA corrida
make list
então imprime todos os destinos, cada um em sua própria linha; você pode canalizar paraxargs
criar uma lista separada por espaço.fonte
rake --tasks
que é?-n
opção.-n
opção é "Imprimir os comandos que seriam executados ..." - em outras palavras: um recurso de execução a seco. Também não é que sua citação esteja faltando o itálico da palavra apenas :make -p
por si só imprime o banco de dados, mas invariavelmente também executa a tarefa padrão ; o manual recomenda o desajeitadomake -p -f/dev/null
para evitar isso..PHONY: *
Em Bash (pelo menos), isso pode ser feito automaticamente com a conclusão da guia:
make
spacetabtabfonte
. /etc/bash_completion
) e aquelas que não são compatíveis com ela. (por exemplo, OSX 10.9)bash-completion
pacote. Encontrado no Fedora, RHEL, Gentoo, ect.$(RUN_TARGETS): run-%: ...
Obviamente, isso não funcionará em muitos casos, mas se o seu
Makefile
foi criado pelo CMake, você poderá executá-lomake help
.fonte
touch CMakeLists.txt && cmake . && make help
e deve funcionar. Só posso supor que você está usando um cmake antigo ou não está usando o gerador Unf Makefiles?Combinei essas duas respostas: https://stackoverflow.com/a/9524878/86967 e https://stackoverflow.com/a/7390874/86967 e escapei para que isso pudesse ser usado dentro de um makefile.
.
fonte
sh -c "…"
é desnecessário, porque é o que,make
por padrão, usa para chamar comandos de receita; (b) o comando que você usa é muito simplista, resultando em falsos positivos (como você observa); (c) se você prefixar o comando@
, ele não será ecoado para stdout antes da execução, evitando a necessidade de usar-s
na invocação.make -s
(por meio de um alias do Bash) em vez de prefixar comandos no makefile@
. Existem alguns casos em que@
podem ser úteis, principalmente como prefixo deecho
comandos (onde a exibição do comando seria redundante), mas em geral eu não gosto de usá-lo. Dessa forma, posso ver as "receitas" quando preciso ( não usando-s
), mas não normalmente. Aqui está a documentação relacionada: GNU Make Manual, 5.2 Eco de receita .Se você tiver a conclusão do bash
make
instalada, o script de conclusão definirá uma função_make_target_extract_script
. Esta função visa criar umsed
script que pode ser usado para obter os destinos como uma lista.Use-o assim:
fonte
/etc/bash_completion
e / ou função_make_target_extract_script
- você parece estar no Ubuntu> 12. Se você mirar em/usr/share/bash-completion/completions/make
vez disso, sua abordagem funcionará em plataformas adicionais, como o Fedora 20. Existem plataformas (mais antigas) que possuem este arquivo, mas não a função (por exemplo, Debian 7 e Ubuntu 12); outras plataformas, como OSX, não vêm com o preenchimento de guiasmake
. Talvez postar a definição real da função seja útil.Como mklement0 aponta , um recurso para listar todos os destinos Makefile está faltando no GNU-make, e sua resposta e outras fornecem maneiras de fazer isso.
No entanto, a postagem original também menciona rake , cujas tarefas mudam algo ligeiramente diferente do que apenas listar todas as tarefas no arquivo rake. O Rake fornecerá apenas uma lista de tarefas que têm descrições associadas. Tarefas sem descrições não serão listadas . Isso permite ao autor fornecer descrições personalizadas da ajuda e também omitir a ajuda para determinados destinos.
Se você deseja imitar o comportamento do rake, onde fornece descrições para cada destino , existe uma técnica simples para fazer isso: incorpore descrições nos comentários para cada destino que você deseja listar.
Você pode colocar a descrição ao lado do destino ou, como costumo fazer, ao lado de uma especificação PHONY acima do destino, assim:
Qual trará
Você também pode encontrar um exemplo de código curto nesta lista e aqui também.
Novamente, isso não resolve o problema de listar todos os destinos em um Makefile. Por exemplo, se você tem um grande Makefile que talvez tenha sido gerado ou que alguém escreveu, e você deseja uma maneira rápida de listar seus destinos sem procurar, isso não ajudará.
No entanto, se você estiver escrevendo um Makefile e desejar gerar uma forma de texto de ajuda de maneira consistente e auto-documentável, essa técnica poderá ser útil.
fonte
echo
comando como descrição do comando ( stackoverflow.com/a/52059487/814145 ).@echo "Target 1"
é apenas um espaço reservado e não um "comando de eco de descrição". O texto de ajuda gerado não é proveniente do@echo
. Em um Makefile real, elesecho
seriam substituídos por um comando de construção ou algo parecido. Vou editar a postagem para deixar isso mais claro.Minha resposta favorita foi postada por Chris Down no Unix e Linux Stack Exchange. Vou citar.
O usuário Brainstone sugere canalizar
sort -u
para remover entradas duplicadas:Fonte: Como listar todos os destinos no make? (Unix e Linux SE)
fonte
A resposta do @ nobar mostra útil como usar o preenchimento de guias para listar os destinos de um makefile .
Isso funciona muito bem para plataformas que fornecem essa funcionalidade por padrão (por exemplo, Debian, Fedora ).
Em outras plataformas (por exemplo, Ubuntu ), você deve carregar explicitamente essa funcionalidade, como está implícito na resposta de @ hek2mgl :
. /etc/bash_completion
instala várias funções de preenchimento de guias, incluindo amake
make
:. /usr/share/bash-completion/completions/make
-f <file>
.fonte
Focando uma sintaxe fácil para descrever um destino de criação e ter uma saída limpa, escolhi esta abordagem:
Portanto, tratar o acima como um Makefile e executá-lo fornece algo como
Explicação para a cadeia de comandos:
fonte
awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort
com##
o comentário anterior na mesma linha do alvo. Mas acho que sua solução permite antes a legibilidade.grep: parentheses not balanced
na minha máquina OSX 10.15.Muitas soluções viáveis aqui, mas como eu gosto de dizer, "se vale a pena fazer uma vez, vale a pena fazer novamente". Votei na sugestão de usar (guia) (guia), mas, como alguns observaram, talvez você não tenha suporte para a conclusão ou, se houver muitos arquivos incluídos, convém uma maneira mais fácil de saber onde um destino está definido.
Eu não testei o abaixo com sub-marcas ... Eu acho que não iria funcionar. Como sabemos, as recursivas são consideradas prejudiciais.
Que eu gosto porque:
Explicação:
Saída de amostra:
fonte
Este foi útil para mim, porque eu queria ver os alvos de compilação necessários (e suas dependências) pelo make make. Eu sei que criar alvos não pode começar com um "." personagem. Não sei quais idiomas são suportados, então fui com as expressões entre colchetes do egrep.
fonte
Isso está longe de ser limpo, mas fez o trabalho para mim.
Eu uso
make -p
que despeja o banco de dados interno, ditch stderr, use um rápido e sujogrep -A 100000
para manter a parte inferior da saída. Depois, limpo a saída com algumasgrep -v
e finalmente usocut
para obter o que está antes dos dois pontos, a saber, os alvos.Isso é suficiente para meus scripts auxiliares na maioria dos meus Makefiles.
EDIT: adicionado
grep -v Makefile
que é uma regra internafonte
Esta é uma modificação da resposta muito útil do jsp ( https://stackoverflow.com/a/45843594/814145 ). Gosto da ideia de obter não apenas uma lista de alvos, mas também suas descrições. O Makefile do jsp coloca a descrição como o comentário, que eu achei muitas vezes repetido no comando echo da descrição do alvo. Então, em vez disso, extraio a descrição do comando echo para cada destino.
Makefile de exemplo:
Saída de
make help
:Notas:
echo
ou:
como o primeiro comando da receita.:
significa "não fazer nada". Eu o uso aqui para os alvos em que nenhum eco é necessário, comoall
destino acima.help
destino adicionar o ":" namake help
saída.fonte
Mais uma resposta adicional acima.
testado no MacOSX usando apenas cat e awk no terminal
irá produzir o arquivo make como abaixo:
no Makefile, deve ser a mesma instrução, assegure-se de que você escape das variáveis usando $$ variable em vez de $ variable.
Explicação
gato - cospe o conteúdo
| - pipe analisa a saída para o próximo awk
awk - executa regex excluindo "shell" e aceitando apenas linhas "Az" e depois imprime a primeira coluna $ 1
awk - mais uma vez remove o último caractere ":" da lista
esse é um resultado difícil e você pode fazer coisas mais descoladas com apenas AWK. Tente evitar o sed, pois não é tão consistente nas variantes do BSDs, ou seja, alguns funcionam no * nix, mas falham nos BSDs como o MacOSX.
Mais
Você deve poder adicionar isso (com modificações) a um arquivo para make , na pasta padrão de conclusão do bash /usr/local/etc/bash-completion.d/, o que significa quando você "cria a guia tab ". destinos com base no script de um liner.
fonte
Eu costumo fazer:
Voltaria com algo como:
Eu espero que isso ajude
fonte
Para um script Bash
Aqui está uma maneira muito simples de fazer isso
bash
- com base no comentário de @ cibercitizen1 acima :Veja também a resposta mais autorizada de @ Marc.2377, que diz como faz o módulo de conclusão do Bash
make
.fonte
Não sei por que a resposta anterior foi tão complicada:
fonte
$(SHELLS): ...
), (b) inclusão de metas que começam com um dígito, (c) não inclusão de definições de variáveis ; (d) visando o makefile adequado, semake
especificado com um caminho explícito do makefile. (a) é a falha crucial: mesmo que você tenha como alvo confiável o makefile correto , a análise do arquivo bruto não funcionará no caso geral, devido à falta de expansão variável.awk -F: '/^[A-z]/ {print $$1}' Makefile
. Finalmente, um ponto amplamente acadêmico: usar, em[A-z]
vez de,[:alpha:]
significa que você perderá alvos que começam com um personagem estrangeiro comoá
.[[:alpha:]]
, em vez de[:alpha:]
([:alpha:]
representa o conjunto locale-aware de letras dentro de uma classe de caracteres ([...]
), daí a necessidade efetiva de duplo[[
/]]
.awk -F: '/^[A-Za-z]/ { print $$1 }' Makefile
usa um único processo e, esperançosamente, uma expressão regular mais correta (embora você possa, obviamente, ter alvos com sublinhados, números etc. também, como observado nos comentários anteriores).