J'ai utilisé un peu de rake (un programme make Ruby), et il a 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 pour le faire dans GNU make.
Apparemment, le code est presque là pour cela, depuis 2007 - http://www.mail-archive.com/[email protected]/msg06434.html .
Quoi qu'il en soit, j'ai fait peu de piratage pour extraire les cibles d'un makefile, que vous pouvez inclure dans un makefile.
list:
@grep '^[^#[:space:]].*:' Makefile
Il vous donnera une liste des cibles définies. Ce n'est qu'un début - cela ne filtre pas les dépendances, par exemple.
> make list
list:
copy:
run:
plot:
turnin:
alias makefile-targets='grep "^[^#[:space:]].*:" Makefile'
plus souvent, j'ai juste besoin d'examiner le makefile actuel, et l'achèvement de bash se développe mon alias.grep : Makefile
:?Réponses:
Il s'agit d'une tentative d'améliorer la grande approche de @ nobar comme suit:
sh -c
)-f <file>
@
pour l'empêcher d'être répercutée avant l'exécutionCurieusement, GNU
make
n'a aucune fonctionnalité pour lister uniquement les noms des cibles définies dans un makefile. L'-p
option produit une sortie qui inclut toutes les cibles, mais les enterre dans de nombreuses autres informations.Placez la règle suivante dans un makefile pour GNU
make
pour implémenter une cible nomméelist
qui répertorie simplement tous les noms de cible dans l'ordre alphabétique - c'est-à-dire: invoquer en tant quemake list
:Important : lors du collage, assurez-vous que la dernière ligne est en retrait avec exactement 1 caractère de tabulation réel. (les espaces ne fonctionnent pas ) .
Notez que trier la liste de cibles résultante est la meilleure option, car ne pas trier ne produit pas un ordre utile dans la mesure où l'ordre dans lequel les cibles apparaissent dans le makefile n'est pas conservé.
De plus, les sous-cibles d'une règle comprenant plusieurs cibles sont invariablement sorties séparément et, par conséquent, en raison du tri, n'apparaissent généralement pas côte à côte; Par exemple, une règle commençant par
a z:
n'aura pas de ciblesa
et seraz
listée côte à côte dans la sortie, s'il y a des cibles supplémentaires.Explication de la règle :
PHONY: list
$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null
make
nouveau afin d'imprimer et d'analyser la base de données dérivée du makefile:-p
imprime la base de données-Rr
supprime l'inclusion de règles et de variables intégrées-q
teste uniquement l'état à jour d'une cible (sans rien refaire), mais cela n'empêche pas en soi l'exécution des commandes de recette dans tous les cas; Par conséquent:-f $(lastword $(MAKEFILE_LIST))
garantit que le même makefile est ciblé que dans l'appel d'origine, qu'il ait été ciblé implicitement ou explicitement avec-f ...
.Avertissement : cela se cassera si votre makefile contient des
include
directives; pour résoudre ce problème, définissez la variableTHIS_FILE := $(lastword $(MAKEFILE_LIST))
avant toutes lesinclude
directives et utilisez-f $(THIS_FILE)
plutôt.:
est une cible délibérément invalide destinée à garantir qu'aucune commande n'est exécutée ;2>/dev/null
supprime le message d'erreur résultant. Remarque: Cela dépend-p
néanmoins de l'impression de la base de données, ce qui est le cas pour GNU make 3.82. Malheureusement, GNU make n'offre aucune option directe pour simplement imprimer la base de données, sans exécuter également la tâche par défaut (ou donnée); si vous n'avez pas besoin de cibler un Makefile spécifique, vous pouvez utilisermake -p -f/dev/null
, comme recommandé dans laman
page.-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 les cibles cachées qui, par convention, sont des cibles qui ne commencent ni par une lettre ni par un chiffre.'^$@$$'
... exclut lalist
cible elle-mêmeL'exécution
make list
imprime ensuite toutes les cibles, chacune sur sa propre ligne; vous pouvez diriger versxargs
pour créer une liste séparée par des espaces à la place.la source
rake --tasks
cela?-n
option.-n
option est de "Imprimer les commandes qui seraient exécutées ..." - en d'autres termes: une fonction de dry-run. Ce n'est pas non plus que votre citation manque l'italique du mot juste :make -p
en lui - même imprime la base de données, mais exécute invariablement également la tâche par défaut ; le manuel recommande le maladroitmake -p -f/dev/null
pour éviter cela..PHONY: *
Sous Bash (au moins), cela peut être fait automatiquement avec la complétion des onglets:
make
spacetabtabla source
. /etc/bash_completion
), et celles qui ne la prennent pas en charge du tout (par exemple, OSX 10.9)bash-completion
package. Trouvé à Fedora, RHEL, Gentoo, ect.$(RUN_TARGETS): run-%: ...
Cela ne fonctionnera évidemment pas dans de nombreux cas, mais si votre a
Makefile
été créé par CMake, vous pourrez peut-être l'exécutermake help
.la source
touch CMakeLists.txt && cmake . && make help
et cela devrait fonctionner. Je peux seulement deviner que vous utilisez un ancien cmake, ou que vous n'utilisez pas le générateur Unix Makefiles?J'ai combiné ces deux réponses: https://stackoverflow.com/a/9524878/86967 et https://stackoverflow.com/a/7390874/86967 et j'ai fait quelques échappements pour que cela puisse être utilisé depuis l'intérieur d'un makefile.
.
la source
sh -c "…"
n'est pas nécessaire, car c'est ce qui estmake
utilisé par défaut pour appeler les commandes de recette; (b) la commande que vous utilisez est trop simpliste, entraînant des faux positifs (comme vous le constatez); (c) si vous préfixez la commande avec@
, elle ne sera pas répercutée sur stdout avant l'exécution, évitant ainsi la nécessité de l'utiliser-s
lors de l'invocation.make -s
(via un alias Bash) plutôt que de préfixer les commandes dans le makefile avec@
. Il y a des cas où cela@
peut être utile, notamment comme préfixe pour desecho
commandes (où l'affichage de la commande serait redondant), mais en général je n'aime pas l'utiliser. De cette façon, je peux voir les "recettes" quand j'en ai besoin (en n'utilisant pas-s
), mais pas typiquement. Voici la documentation associée: GNU Make Manual, 5.2 Recipe Echoing .Si vous avez bash complétion pour
make
installé, le script de complétion définira une fonction_make_target_extract_script
. Cette fonction est destinée à créer unsed
script qui peut être utilisé pour obtenir les cibles sous forme de liste.Utilisez-le comme ceci:
la source
/etc/bash_completion
et / ou de fonction_make_target_extract_script
- vous semblez être sur Ubuntu> 12. Si vous ciblez à la/usr/share/bash-completion/completions/make
place, votre approche fonctionnera sur des plates-formes supplémentaires, telles que Fedora 20. Il existe des plates-formes (plus anciennes) qui ont ce fichier, mais pas la fonction (par exemple, Debian 7 et Ubuntu 12); d'autres plates-formes, telles que OSX, ne sont pas livrées avec une tabulation complète dumake
tout. Il serait peut-être utile d'afficher la définition de fonction réelle.Comme remarquer mklement0 , une fonction pour répertorier toutes les cibles Makefile manque dans GNU-make, et sa réponse et d'autres fournissent des moyens de le faire.
Cependant, le message d'origine mentionne également rake , dont le changement de tâches fait quelque chose de légèrement différent de simplement lister toutes les tâches dans le rakefile. Rake ne vous donnera qu'une liste de tâches qui ont des descriptions associées. Les tâches sans description ne seront pas répertoriées . Cela permet à l'auteur de fournir à la fois des descriptions d'aide personnalisées et d'omettre l'aide pour certaines cibles.
Si vous souhaitez imiter le comportement de rake, où vous fournissez descriptions pour chaque cible , il existe une technique simple pour ce faire: incorporer des descriptions dans les commentaires pour chaque cible que vous souhaitez répertorier.
Vous pouvez soit mettre 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:
Qui donnera
Vous pouvez également trouver un exemple de code court dans cet essentiel et ici aussi.
Encore une fois, cela ne résout pas le problème de la liste de 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 n'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 être utile.
la source
echo
commande comme description de la commande ( stackoverflow.com/a/52059487/814145 ).@echo "Target 1"
s'agit que d'un espace réservé et non d'une "commande d'écho de description". Le texte d'aide généré ne provient pas du@echo
. Dans un vrai Makefile, ceux-ciecho
seraient remplacés par une commande de construction ou quelque chose comme ça. Je vais modifier le message pour le rendre plus clair.Ma réponse préférée à cela a été publiée par Chris Down à Unix & Linux Stack Exchange. Je vais citer.
L'utilisateur Brainstone suggère un tuyau
sort -u
pour supprimer les entrées en double:Source: Comment lister toutes les cibles en make? (Unix et Linux SE)
la source
La réponse de @ nobar montre utilement comment utiliser la complétion d'onglet pour lister les cibles d'un 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 l' indique la réponse de @ hek2mgl :
. /etc/bash_completion
installe plusieurs fonctions de tabulation, dont celle pourmake
make
:. /usr/share/bash-completion/completions/make
-f <file>
.la source
En me concentrant sur une syntaxe simple pour décrire une cible de création et ayant une sortie propre, j'ai choisi cette approche:
Donc, traiter ce qui précède comme un Makefile et l'exécuter vous donne quelque chose comme
Explication de la chaîne de commandes:
la source
awk -F ':|##' '/^[^\t].+:.*##/ { printf "\033[36mmake %-28s\033[0m -%s\n", $$1, $$NF }' $(MAKEFILE_LIST) | sort
avec l'##
avant le commentaire sur la même ligne que la cible. Mais je pense que votre solution permet avant la lisibilité.grep: parentheses not balanced
sur ma machine OSX 10.15.Beaucoup de solutions réalisables ici, mais comme j'aime le dire, "si cela vaut la peine d'être fait une fois, cela vaut la peine de le faire à nouveau." J'ai voté pour la suggestion d'utiliser (tab) (tab), mais comme certains l'ont noté, il se peut que vous n'ayez pas de prise en charge de l'achèvement ou, si vous avez plusieurs fichiers d'inclusion, vous voudrez peut-être un moyen plus simple 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 nous le savons, le récursif le rend dangereux.
Ce que j'aime parce que:
Explication:
Exemple de sortie:
la source
Celui-ci m'a été utile car je voulais voir les cibles de build requises (et leurs dépendances) par la cible make. Je sais que faire des cibles ne peut pas commencer par un "." personnage. Je ne sais pas quelles langues sont prises en charge, j'ai donc opté pour les expressions de support egrep.
la source
C'est loin d'être propre, mais ça a fait le boulot, pour moi.
J'utilise
make -p
qui vide la base de données interne, stitchr de fossé, utilise un rapide et salegrep -A 100000
pour garder le bas de la sortie. Ensuite, je nettoie la sortie avec quelquesgrep -v
, et finalement j'utilisecut
pour obtenir ce qui est avant les deux points, à savoir les cibles.Cela suffit pour mes scripts d'aide sur la plupart de mes Makefiles.
EDIT: ajouté
grep -v Makefile
qu'il s'agit d'une règle internela source
Il s'agit d'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 leurs descriptions. Makefile de jsp met la description en commentaire, ce que j'ai souvent trouvé sera répété dans la commande echo de description de la cible. Donc, à la place, j'extrais la description de la commande echo pour chaque cible.
Exemple de Makefile:
Sortie de
make help
:Remarques:
echo
ou:
comme première commande de la recette.:
signifie "ne rien faire". Je l'utilise ici pour les cibles qui ne nécessitent aucun écho, comme laall
cible ci-dessus.help
cible ajoute le ":" dans lamake help
sortie.la source
Encore une autre réponse supplémentaire à ce qui précède.
testé sur MacOSX en utilisant uniquement cat et awk sur le terminal
affichera le fichier make comme ci-dessous:
dans le Makefile, ce doit être la même instruction, assurez-vous que vous échappez les variables en utilisant la variable $$ plutôt que la variable $.
Explication
chat - crache le contenu
| - le tube analyse la sortie vers le prochain awk
awk - exécute regex à l'exclusion de "shell" et n'accepte que les lignes "Az", puis imprime la première colonne $ 1
awk - supprime encore une fois le dernier caractère ":" de la liste
c'est une sortie approximative et vous pouvez faire des choses plus funky avec juste AWK. Essayez d'éviter sed car ce n'est pas aussi cohérent dans les variantes BSD c'est-à-dire que certains travaux sur * nix mais échouent sur BSD comme MacOSX.
Plus
Vous devriez pouvoir l'ajouter (avec des modifications) à un fichier pour make , dans le dossier bash-complétion par défaut /usr/local/etc/bash-completion.d/ ce qui signifie que lorsque vous "créez un onglet ", il terminera la cibles basées sur le script one liner.
la source
Je fais habituellement:
Il reviendrait avec quelque chose comme:
J'espère que ça aide
la source
Pour un script bash
Voici un moyen très simple de le faire dans
bash
- basé sur le commentaire de @ cibercitizen1 ci - dessus :Voir aussi la réponse plus officielle de @ Marc.2377, qui dit comment le module de complétion Bash le
make
fait.la source
Je ne sais pas pourquoi la réponse précédente était si compliquée:
la source
$(SHELLS): ...
), (b) l'inclusion de cibles qui commencent par un chiffre, (c) non inclusion de définitions de variables , (d) ciblant le makefile approprié s'il amake
été spécifié avec un chemin de makefile explicite. (a) est la lacune cruciale: même si vous avez ciblé de manière fiable le bon makefile, l'analyse du fichier brut ne fonctionnera pas dans le cas général, en raison du manque d'expansion des variables.awk -F: '/^[A-z]/ {print $$1}' Makefile
. Enfin, un point largement académique: utiliser[A-z]
plutôt que[:alpha:]
signifie que vous allez manquer des cibles qui commencent par un caractère étranger tel queá
.[[:alpha:]]
plutôt que[:alpha:]
([:alpha:]
représente l'ensemble de lettres sensible aux paramètres régionaux à l' intérieur d' une classe de caractères ([...]
), d'où le besoin effectif de double[[
/]]
.awk -F: '/^[A-Za-z]/ { print $$1 }' Makefile
utilise un seul processus et, espérons-le, une expression régulière plus correcte (bien que vous puissiez bien sûr avoir des cibles avec des soulignements, des nombres, etc., comme indiqué dans les commentaires précédents).