web-dev-qa-db-fra.com

Énumérer les objectifs/cibles dans GNU faire qui contiennent des variables dans leur définition

J'ai un makefile assez volumineux qui crée plusieurs cibles à la volée en calculant des noms à partir de variables. (par exemple, foo $ (VAR): $ (PREREQS)). Est-il possible de convaincre les créateurs de créer une liste de cibles après avoir étendu ces variables?

J'aimerais pouvoir obtenir les cibles pour un fichier Make aribitrary. J'essaie d'écrire une fonction d'achèvement pour mon shell.

98
BitShifter

Pouvez-vous analyser le résultat de make -pn (c'est-à-dire make --print-data-base --dry-run)? Il imprime toutes les variables, règles, règles implicites et les commandes qui seront exécutées avec des détails laborieux.

78
Jack Kelly
make -qp | awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split($1,A,/ /);for(i in A)print A[i]}'     

Tiré de l'achèvement de make arg, qui fonctionne à merveille.

112
todd hodes

Je ne sais pas si c'est seulement une chose géniale, mais cela fonctionne bien:

make help

13
Zdenik

Plusieurs répondants ont suggéré d'utiliser make -pn, qui imprimera la base de données de règles sans exécuter quoi que ce soit - plus ou moins. Le problème avec cette approche est que -n invoque toujours toutes les marques récursives et qu'il effectue encore beaucoup plus de travail que nécessaire, car il imprime toutes les commandes qu'il aurait appelées dans une construction normale. Une solution plus efficace consisterait à créer un fichier Make trivial, dummy.mk, avec le contenu suivant:

__all_targets__: ; #no-op

Invoquez maintenant make as make -p -f Makefile -f dummy.mk __all_targets__. Sur toute construction substantielle, la différence dans la quantité de production générée par make est significative. Par exemple:

$ gmake -pn | wc
 138985 2632330 69612711
$ gmake -f Makefile -f /tmp/dummy.mk -pn __all_targets__ | wc
  21673   93437  878985

Le temps d'exécution était lui aussi nettement meilleur - 2.063s pour la première version, 0.059s pour la seconde.

10
Eric Melski

Découvrez bash finish pour make sur GitHub.

9
js.

Éditer: FYI, le référentiel git de l’aboutissement bash de Debian dans une autre réponse incorpore maintenant une version améliorée de ce script adaptée aux cas d’utilisation de l’achèvement bash.

#!/bin/bash

SCRIPT='
  /^# Make data base/,/^# Files/d             # skip until files section
  /^# Not a target/,+1          d             # following target isnt
  /^\.PHONY:/                   d             # special target
  /^\.SUFFIXES:/                d             # special target
  /^\.DEFAULT:/                 d             # special target
  /^\.PRECIOUS:/                d             # special target
  /^\.INTERMEDIATE:/            d             # special target
  /^\.SECONDARY:/               d             # special target
  /^\.SECONDEXPANSION/          d             # special target
  /^\.DELETE_ON_ERROR:/         d             # special target
  /^\.IGNORE:/                  d             # special target
  /^\.LOW_RESOLUTION_TIME:/     d             # special target
  /^\.SILENT:/                  d             # special target
  /^\.EXPORT_ALL_VARIABLES:/    d             # special target
  /^\.NOTPARALLEL:/             d             # special target
  /^\.ONESHELL:/                d             # special target
  /^\.POSIX:/                   d             # special target
  /^\.NOEXPORT:/                d             # special target
  /^\.MAKE:/                    d             # special target

# The stuff above here describes lines that are not
#  explicit targets or not targets other than special ones
# The stuff below here decides whether an explicit target
#  should be output.

  /^[^#\t:=%]+:([^=]|$)/ {                    # found target block
    h                                         # hold target
    d                                         # delete line
  }
  /^# File is an intermediate prerequisite/ { # nope
    s/^.*$//;x                                # unhold target
    d                                         # delete line
  }
  /^([^#]|$)/ {                               # end of target block
    s/^.*$//;x                                # unhold target
    s/:.*$//p                                 # write current target
    d                                         # hide any bugs
  }
'

make -npq .DEFAULT 2>/dev/null | sed -n -r "$SCRIPT" \
  | sort | uniq

Il s’agit d’un script beaucoup plus complet que le script de complétion debian bash, car il fournit des résultats pour les règles générées. C’est ce que demande la question.

Ce n'est pas le script original auquel j'ai lié le lien, mais il est beaucoup plus simple et rapide.

7
codeshot

Ceci est le code pour un alias basé sur la solution Todd Hodes

alias mtargets='make -qp | awk -F":" "/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ {split(\$1,A,/ /);for(i in A)print A[i]}"'
4
Nguyễn Minh Vũ

Cela donnera une belle sortie:

make -pn | Perl -F: -ane 'print "$F[0]\n" if /^\w+\s*:/' | sort
3
Andor

Il existe une très bonne solution avec de la magie sed et egrep ici: https://Gist.github.com/pvdb/777954

3
Atilla Filiz

Je suppose que je suis un peu en retard à cette fête, mais si vous recherchez une commande spécifique, vous pouvez essayer

make -qp | grep -v '^# ' | grep -v '^[[:space:]]' | grep --only-matching '^.*:'

Cela fonctionne principalement, bien qu'il puisse toujours inclure des éléments non-cibles, comme une directive vpath. Si vous ne dépendez pas des règles intégrées de make, vous pouvez utiliser make -qpR comme première commande du pipeline.

2
DGrady

Solution de rubis:

`make -qp`.split("\n").select{|l| l =~ /^\w/ && l !~ /=/}.map{|l| l.sub(/:.*/,'')}
1
gdub

Je travaille sur le Solaris 10 anda turbo C Shell. La solution proposée ne fonctionne pas pour mon projet de makefile. même après avoir modifié la ligne de commande ci-dessus en syntaxe tcsh . Cependant, j’ai découvert que vous pouvez obtenir une solution simple en utilisant 

remake --tasks | grep -v "clean some static output or just grep tabs on start of line" | awk ´{print $1}´

refaire la version:

remake --version

est

GNU Make 3.82+dbg0.8
Built for sparc-Sun-sparc2-9

et quelques autres données de version sans importance

1
Aviv

Trouvé cette solution dans un autre thread:

sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\""

Vous pouvez également l'ajouter à votre Makefile:

list:
    sh -c "cat Makefile | egrep \"^[[:alnum:][:punct:]]{0,}:[[:space:]]{0,}[[:alnum:][:punct:][:space:]]{0,}$\\""

Et exécutez make list.

0
thisismydesign

Je suis allé à la recherche de la même question et suis venu avec cette rotation:

make -pn | sed -rn '/^[^# \t\.%].*:/p'

Cela supprime toutes les lignes de commentaire, les règles de modèle (lignes commençant par des tabulations), tous les éléments intrinsèques (exemples de modèles .c.o et %.o: %.c).

0
Jamie