J'ai utilisé un peu rake (a Ruby make)), et il dispose d'une option pour obtenir une liste de toutes les cibles disponibles, par exemple
> 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...
...
mais il ne semble pas y avoir d’option permettant de faire cela dans GNU make.
Apparemment, le code est presque là pour ça, à partir de 2007 - http://www.mail-archive.com/[email protected]/msg06434.html .
Quoi qu'il en soit, j'ai fait un petit bidouillage pour extraire les cibles d'un fichier Make, que vous pouvez inclure dans un fichier Make.
list:
@grep '^[^#[:space:]].*:' Makefile
Il vous donnera une liste des cibles définies. Ce n'est qu'un début - par exemple, il ne filtre pas les dépendances.
> make list
list:
copy:
run:
plot:
turnin:
Ceci est une tentative pour améliorer la bonne approche de @ nobar comme suit:
sh -c
inutiles)-f <file>
@
pour l'empêcher d'être répété avant l'exécutionCurieusement, GNU make
n'a pas de fonction permettant de lister uniquement les noms des cibles définies dans un fichier makefile. L'option -p
Produit une sortie qui inclut toutes les cibles, mais enterre eux dans beaucoup d'autres informations.
Placez la règle suivante dans un fichier make pour GNU make
afin d'implémenter une cible nommée list
qui répertorie simplement tous les noms de cibles. dans l'ordre alphabétique - c'est-à-dire: invoquer comme make list
:
.PHONY: list
list:
@$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
Important : Lorsque vous collez ceci, , assurez-vous que la dernière ligne est en retrait de exactement 1 onglet réel char. (les espaces font pas fonctionnent) .
Notez que tri la liste de cibles résultante est la meilleure option, car pas le tri ne produit pas un ordre utile dans l'ordre d'affichage des cibles. dans le makefile est pas préservé.
De plus, les sous-cibles d’une règle comprenant plusieurs cibles sont invariablement sorties séparément et seront donc, en raison du tri, généralement pas l'un à côté de l'autre; Par exemple, une règle commençant par a z:
aura pas aura les cibles a
et z
listées côte à côte dans la sortie, s'il y a des cibles supplémentaires.
Explication de la règle :
PHONY: list
$(MAKE) -prRn -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null
make
afin d'imprimer et d'analyser la base de données dérivée du fichier makefile: -p
Imprime la base de données-Rr
Supprime l'inclusion de règles et de variables intégrées-q
Ne teste que l'état actuel d'une cible (sans rien refaire), mais cela n'empêche pas l'exécution de commandes de recette dans tous les cas; Par conséquent:-f $(lastword $(MAKEFILE_LIST))
garantit que le même fichier Make est ciblé comme dans l'appel d'origine, qu'il ait été ciblé de manière implicite ou explicite avec -f ...
.include
directives; pour y remédier, définissez la variable THIS_FILE := $(lastword $(MAKEFILE_LIST))
avant toutes les directives include
et utilisez -f $(THIS_FILE)
à la place. :
Est une cible délibérément invalide destinée à assurez-vous qu'aucune commande n'est exécutée; 2>/dev/null
Supprime le message d'erreur résultant. Remarque: Ceci repose sur -p
Pour imprimer néanmoins la base de données, ce qui est le cas à partir de GNU make 3.82. Malheureusement, GNU make offer no option directe à juste imprimer la base de données, sans aussi exécuter la tâche par défaut (ou donnée); si vous n'avez pas besoin de cibler un Makefile spécifique, vous pouvez utiliser make -p -f/dev/null
, comme recommandé dans la page man
.-v RS=
/^# File/,/^# Finished Make data base/
if ($$1 !~ "^[#.]")
#
... ignore les non-cibles dont les blocs commencent par # Not a target:
.
... ignore les cibles spéciales:
egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
Supprime les cibles indésirables de la sortie: '^[^[:alnum:]]'
... exclut caché cibles qui, par convention, sont des cibles qui ne commencent ni par une lettre ni par un chiffre.'^$@$$'
... exclut la cible list
elle-mêmeLancer make list
Affiche ensuite toutes les cibles, chacune sur sa propre ligne; vous pouvez diriger vers xargs
pour créer une liste séparée par des espaces.
Sous Bash (au moins), cela peut être fait automatiquement en complétant l'onglet:
make(space)(tab)(tab)
J'ai combiné ces deux réponses: https://stackoverflow.com/a/9524878/86967 et https://stackoverflow.com/a/7390874/86967 et en a fait s'échapper pour que cela puisse être utilisé depuis un fichier makefile.
.PHONY: no_targets__ list
no_targets__:
list:
sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | sort"
.
$ make -s list
build
clean
default
distclean
doc
fresh
install
list
makefile ## this is kind of extraneous, but whatever...
run
Cela ne fonctionnera évidemment pas dans de nombreux cas, mais si votre Makefile
a été créé par CMake, vous pourrez peut-être exécuter make help
.
$ make help
The following are some of the valid targets for this Makefile:
... all (the default if no target is provided)
... clean
... depend
... install
etc
Si vous avez l'achèvement de bash pour make
installé, le script d'achèvement définira une fonction _make_target_extract_script
. Cette fonction est destinée à créer un script sed
pouvant être utilisé pour obtenir les cibles sous forme de liste.
Utilisez-le comme ceci:
# Make sure bash completion is enabled
source /etc/bash_completion
# List targets from Makefile
sed -nrf <(_make_target_extract_script --) Makefile
Comme mklement0 souligne , une fonctionnalité permettant de lister toutes les cibles Makefile manque dans GNU-make, et sa réponse, ainsi que d'autres, fournit des moyens de le faire.
Cependant, le message d'origine mentionne également rake , dont le commutateur tâches fait quelque chose de légèrement différent de la liste de toutes les tâches du fichier rakefile. Rake ne vous donnera qu'une liste de tâches associées à des descriptions. Tâches sans description ne sera pas répertorié . Cela donne à l'auteur la possibilité de fournir des descriptions d'aide personnalisées et d'omettre l'aide pour certaines cibles.
Si vous souhaitez émuler le comportement de rake, où vous fournissez descriptions pour chaque cible , il existe une technique simple pour ce faire: intégrez des descriptions dans les commentaires de chaque cible que vous souhaitez répertorier.
Vous pouvez soit placer la description à côté de la cible ou, comme je le fais souvent, à côté d'une spécification PHONY au-dessus de la cible, comme ceci:
.PHONY: target1 # Target 1 help text
target1: deps
[... target 1 build commands]
.PHONY: target2 # Target 2 help text
target2:
[... target 2 build commands]
...
.PHONY: help # Generate list of targets with descriptions
help:
@grep '^.PHONY: .* #' Makefile | sed 's/\.PHONY: \(.*\) # \(.*\)/\1 \2/' | expand -t20
Qui donnera
$ make help
target1 Target 1 help text
target2 Target 2 help text
...
help Generate list of targets with descriptions
Vous pouvez également trouver un exemple de code court dans this Gist et ici aussi.
Encore une fois, cela ne résout pas le problème de lister toutes les cibles dans un Makefile. Par exemple, si vous avez un gros Makefile qui a peut-être été généré ou que quelqu'un d'autre a écrit et que vous voulez un moyen rapide de lister ses cibles sans le fouiller, cela ne vous aidera pas.
Toutefois, si vous écrivez un Makefile et que vous souhaitez générer un texte d'aide de manière cohérente et auto-documentée, cette technique peut s'avérer utile.
La réponse de @ nobar montre utilement comment utiliser la complétion de tabulation pour répertorier les cibles d'un fichier makefile .
Cela fonctionne très bien pour les plates-formes qui fournissent cette fonctionnalité par défaut (par exemple, Debian, Fedora ).
Sur d’autres plateformes (par exemple Ubuntu ), vous devez explicitement charger cette fonctionnalité. , comme suggéré par la réponse de @ hek2mgl :
. /etc/bash_completion
installe plusieurs fonctions de complétion par des tabulations, y compris celle pour make
make
: . /usr/share/bash-completion/completions/make
_complete_make() { COMPREPLY=($(compgen -W "$(make -pRrq : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($1 !~ "^[#.]") {print $1}}' | egrep -v '^[^[:alnum:]]' | sort | xargs)" -- "${COMP_WORDS[$COMP_CWORD]}")); }
complete -F _complete_make make
-f <file>
.Ceci est une modification de la réponse très utile de jsp ( https://stackoverflow.com/a/45843594/814145 ). J'aime l’idée d’obtenir non seulement une liste de cibles mais aussi leur description. Le Makefile de jsp place la description sous forme de commentaire, que je trouvais souvent répété dans la commande echo de description de la cible. Au lieu de cela, j'extrais la description de la commande echo pour chaque cible.
Exemple de Makefile:
.PHONY: all
all: build
: "same as 'make build'"
.PHONY: build
build:
@echo "Build the project"
.PHONY: clean
clean:
@echo "Clean the project"
.PHONY: help
help:
@echo -n "Common make targets"
@echo ":"
@cat Makefile | sed -n '/^\.PHONY: / h; /\(^\t@*echo\|^\t:\)/ {H; x; /PHONY/ s/.PHONY: \(.*\)\n.*"\(.*\)"/ make \1\t\2/p; d; x}'| sort -k2,2 |expand -t 20
Sortie de make help
:
$ make help
Common make targets:
make all same as 'make build'
make build Build the project
make clean Clean the project
make help Common make targets
Remarques:
echo
ou :
commande en tant que première commande de la recette. :
signifie "ne fait rien". Je l'utilise ici pour les cibles pour lesquelles aucun écho n'est nécessaire, tel que all
cible ci-dessus.help
ajoute le ":" dans le fichier make help
sortie.Celui-ci m'a été utile car je voulais voir les cibles de construction requises (et leurs dépendances) par la cible de création. Je sais que faire des cibles ne peut pas commencer par un "." personnage. Je ne sais pas quelles langues sont supportées, alors je suis allé avec les expressions entre crochets d'egrep.
cat Makefile | egrep "^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$"
Beaucoup de solutions réalisables ici, mais comme j'aime à dire, "si ça vaut la peine de le faire une fois, ça vaut la peine de le refaire." J'ai recommandé la suggestion d'utilisation (onglet) (onglet), mais comme certains l'ont déjà noté, il se peut que vous n'ayez pas de prise en charge de l'achèvement ou que, si vous avez plusieurs fichiers inclus, vous souhaitiez peut-être un moyen plus facile de savoir où une cible est définie.
Je n'ai pas testé ce qui suit avec des sous-marques ... Je pense que cela ne fonctionnerait pas. Comme on le sait, les marques récursives sont considérées comme nuisibles.
.PHONY: list ls
ls list :
@# search all include files for targets.
@# ... excluding special targets, and output dynamic rule definitions unresolved.
@for inc in $(MAKEFILE_LIST); do \
echo ' =' $$inc '= '; \
grep -Eo '^[^\.#[:blank:]]+.*:.*' $$inc | grep -v ':=' | \
cut -f 1 | sort | sed 's/.*/ &/' | sed -n 's/:.*$$//p' | \
tr $$ \\\ | tr $(open_paren) % | tr $(close_paren) % \
; done
# to get around escaping limitations:
open_paren := \(
close_paren := \)
= Makefile =
includes
ls list
= util/kiss/snapshots.mk =
rotate-db-snapshots
rotate-file-snapshots
snap-db
snap-files
snapshot
= util/kiss/main.mk =
dirs
install
%MK_DIR_PREFIX%env-config.php
%MK_DIR_PREFIX%../srdb
Ceci est loin d'être propre, mais a fait le travail, pour moi.
make -p 2&>/dev/null | grep -A 100000 "# Files" | grep -v "^$" | grep -v "^\(\s\|#\|\.\)" | grep -v "Makefile:" | cut -d ":" -f 1
J'utilise make -p
qui vide la base de données interne, ditch stderr, utilise un fichier rapide et sale grep -A 100000
pour conserver le bas de la sortie. Ensuite, je nettoie la sortie avec un couple de grep -v
, et utilise finalement cut
pour obtenir ce qui se trouve avant le colon, à savoir les cibles.
C'est assez pour mes scripts d'aide sur la plupart de mes Makefiles.
EDIT: ajouté grep -v Makefile
c'est une règle interne
Encore une autre réponse supplémentaire à ci-dessus.
testé sur MacOSX en utilisant uniquement cat et awk sur terminal
cat Makefile | awk '!/Shell/ && /^[A-z]/ {print $1}' | awk '{print substr($0, 1, length($0)-1)}'
va sortir du fichier make comme ci-dessous:
cible1
cible2
cible3
dans le Makefile, ce devrait être la même instruction, assurez-vous d'échapper aux variables en utilisant la variable $$ plutôt que la variable $.
Explication
cat - crache le contenu
- pipe analyse la sortie vers le prochain awk
awk - exécute une expression rationnelle excluant "Shell" et n'acceptant que les lignes "A-z", puis affiche la première colonne $ 1
awk - encore une fois supprime le dernier caractère ":" de la liste
ceci est une sortie approximative et vous pouvez faire plus de choses géniales avec seulement AWK. Essayez d’éviter sed car il n’est pas aussi cohérent dans les variantes de BSD, c’est-à-dire que certains fonctionnent sur * nix mais échouent sur des BSD tels que MacOSX.
Plus
Vous devriez pouvoir ajouter ceci (avec des modifications) à un fichier pour make , dans le dossier par défaut bash-completion/usr /local/etc/bash-completion.d/ signifiant lorsque vous faites "onglet ) " .. il complétera le cibles basées sur le script one liner.