258 votes

Comment obtenez-vous la liste des cibles dans un fichier makefile?

J'ai utilisé ratisser un peu (un Rubis faire le programme), et il a une option pour obtenir la 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 semble y avoir aucune option pour cela dans le GNU make.

Il semble que le code est presque là pour elle, à partir de 2007 - http://www.mail-archive.com/help-make@gnu.org/msg06434.html.

De toute façon, j'ai fait un peu de bidouille pour extraire les cibles à partir d'un fichier makefile que vous pouvez inclure dans un makefile.

cmds:
    @grep '^[^#[:space:]].*:' makefile

Il vous donnera une liste des cibles définies. C'est qu'un début - il ne filtre pas les dépendances, par exemple.

> make cmds
cmds:
copy:
run:
plot:
turnin:

233voto

nobar Points 5849

Sous Bash (au moins), cela peut être fait automatiquement avec la complétion par tabulation:

 make(space)(tab)(tab)
 

177voto

mklement0 Points 12597

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.

27voto

nobar Points 5849

J'ai combiné ces deux réponses: http://stackoverflow.com/a/9524878/86967 et http://stackoverflow.com/a/7390874/86967 et j'ai échappé un peu afin que cela puisse être utilisé à l'intérieur d'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
 

14voto

hek2mgl Points 38787

Si vous avez déjà terminé la procédure pour make installée, le script de finalisation 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
 

3voto

Jack Kelly Points 9640

Jetez un oeil à cette question , qui semble similaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X