C'est une tentative d'amélioration @nobar de l'approche qui, comme suit:
- utilise un système plus robuste de commande pour extraire les noms de cible, qui nous l'espérons empêche tout faux positifs (et de loin avec les inutiles
sh -c
)
- ne pas toujours cible le makefile dans le courant de répertoire; respecte les makefiles spécifié explicitement avec
-f <file>
- exclut les objectifs cachés - par convention, ces sont des cibles dont le nom commence ni une lettre ni un chiffre
- fait de le faire avec un seul bidon cible
- les préfixes de la commande avec
@
pour l'empêcher d'être repris avant l'exécution
Curieusement, GNU make
n'a pas de fonction pour lister uniquement les noms des objectifs définis dans un makefile. L' -p
option produit une sortie qui comprend toutes les cibles, les enterre, mais dans beaucoup d'autres informations.
Placer la règle suivante dans un makefile pour GNU make
pour mettre en œuvre une cible nommée list
que simplement des listes de tous les noms dans l'ordre alphabétique - c'est à dire: invoquer comme make list
:
.PHONY: list
list:
@$(MAKE) -pRrq : -f $(MAKEFILE_LIST) 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs
Remarque: Sur le collage, assurez-vous que la dernière ligne est en retrait par exactement 1 onglet.
Notez que le tri de la liste des cibles est la meilleure option, car pas de tri ne produit pas utile de commande dans l'ordre dans lequel les cibles apparaissent dans le fichier makefile est pas conservé.
Aussi, le sous-objectifs d'une règle composée de plusieurs cibles sont toujours de sortie séparément et, par conséquent, en raison de tri, habituellement, de ne pas apparaître à côté l'un de l'autre; par exemple, une règle en commençant par a z:
aura pas de cibles a
et z
énumérés à côté de l'autre à la sortie, si il y a d'autres cibles.
Explication de la règle:
- .
PHONY: list
- déclare liste cible un faux cible, c'est à dire, un pas en se référant à un fichier, qui doit donc avoir sa recette invoquée de manière inconditionnelle
-
$(MAKE) -prRn : -f $(MAKEFILE_LIST) 2>/dev/null
- Invoque
make
de nouveau afin de l'imprimer et d'analyser la base de données dérivée de le makefile:
-
-p
imprime la base de données
-
-Rr
supprime l'inclusion de règles intégrées et les variables
-
-q
seulement des tests de la mise à jour d'état d'une cible (sans refaire quoi que ce soit), mais cela n'empêche pas l'exécution de la recette des commandes dans tous les cas; d'où:
-
:
est délibérément non valide cible , qui est destinée à assurer qu'aucune commande n'est exécutée; 2>/dev/null
supprime l'erreur qui en résulte message. Remarque: Cela dépend de l' -p
d'impression de la base de données néanmoins, ce qui est le cas de GNU make 3.82. Malheureusement, GNU make propose aucune option directe pour imprimer la base de données.
-
-f $(MAKEFILE_LIST)
garantit que le même fichier makefile est ciblée comme dans l'original invocation; mise en garde: cette volonté de rompre avec les chemins contenant des espaces.
-
-v RS=
- C'est un langage awk qui rompt l'entrée dans un bloc contigu de lignes non-vides.
-
/^# File/,/^# Finished Make data base/
- Correspond à la gamme de lignes de la sortie qui contient toutes les cibles (vrai de GNU make 3.82) - en limitant l'analyse de cette gamme, il n'est pas nécessaire de traiter avec de faux positifs provenant d'autres sections de la sortie.
-
if ($$1 !~ "^[#.]")
- Sélectivement ignore blocs:
-
#
... ignore non-cibles, dont les blocs de démarrage avec # Not a target:
-
.
... ignore les objectifs spécifiques
- Tous les autres blocs doivent commencer avec une ligne contenant uniquement le nom d'un définies explicitement cible suivie par
:
-
egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
supprime les cibles indésirables à partir de la sortie:
-
'^[^[:alnum:]]'
... exclut caché des objectifs qui - par convention - sont des cibles qui commencent ni une lettre ni un chiffre.
-
'^$@$$'
... exclut l' list
de la cible elle-même
-
xargs
- Convertit efficacement les lignes de sortie pour une seule ligne, séparés par des espaces, de la liste; omettre cette option si vous souhaitez que chaque nom de la cible à apparaître sur sa propre ligne.